
SportsGPT is a stats-and-standings product, and it's home to two of the family's best interactions: the search — a faceted, hotkey-driven leaderboard you can fly through — and an animation — a gallery modal that swipes and springs like a native app. They're a nice pairing because one is about speed of thought and the other about speed of feel.
Search as a control surface
The leaderboard isn't a search box bolted onto a table — it's a small control surface. Query, division, season, a versus mode, and per-stat sort columns all live as state and compose into one filtered, sorted view, with a keyboard hotkey to focus (and clear) the field:
// src/app/leaderboard/Shell.tsx
const [query, setQuery] = useState("");
const [activeDiv, setActiveDiv] = useState<DivisionKey>("All");
const [selectedSeason, setSelectedSeason] = useState<number | "all">("all");
const [versusMode, setVersusMode] = useState(false);
const [passCol, setPassCol] = useState<PassCol>("pass_yards");
const [passDir, setPassDir] = useState<SortDir>("desc");
const searchRef = useRef<HTMLInputElement>(null);
useSearchHotkey(searchRef, () => setQuery("")); // focus on hit, clear on EscapeEverything downstream is a useMemo over that state, so typing, faceting, and
re-sorting are instant and never hit the network — the dataset is in memory and
the UI is just a projection of these few values. It's the pattern ScienceGPT and
TariffsGPT share, tuned here for the speed a stats nerd expects.
A gallery modal that springs and swipes
The gallery modal is the animation people remember. It composes Framer Motion's
MotionConfig (one shared spring for the whole modal), a per-image
enter/exit, and a spring-animated filmstrip — all wrapped in react-swipeable
so touch gestures drive the same transitions as the arrow keys:
// src/app/gallery/components/SharedModal.tsx
const handlers = useSwipeable({ /* onSwipedLeft/Right → change image */ });
<MotionConfig transition={{ x: { type: "spring", stiffness: 300, damping: 30 }, opacity: { duration: 0.2 } }}>
<motion.div
key={currentIdx}
initial={{ opacity: 0, scale: 0.96 }}
animate={{ opacity: 1, scale: 1 }}
>
{/* current image */}
</motion.div>
{/* the thumbnail strip slides to keep the active frame centered */}
<motion.div
initial={{ left: `calc(50% - ${offsetPx}px)` }}
animate={{ left: `calc(50% - ${offsetPx}px)` }}
transition={{ type: "spring", stiffness: 320, damping: 32 }}
/>
</MotionConfig>The trick that makes it feel expensive: the filmstrip's left is animated as a
spring toward a computed offset, so the active thumbnail always glides to center
no matter how fast you swipe. One MotionConfig keeps every transition on the
same physical model, so nothing feels out of step.
Why it matters
SportsGPT shows the two halves of a great UI. Search is architecture — hold the
right state, project it with useMemo, and speed is free. Animation is
restraint — one shared spring, a couple of well-chosen transitions, and gestures
mapped to the same motions as keys. Do both and the app feels alive.
Brendan Stanton
Founder, NYSgpt
Read more
TerminalGPT — a localhost dashboard where the disk is the database
How HQ turns the files Claude Code already writes to disk into a live, searchable control room — with a panel that survives navigation, a daemon that outlives the server, and status rings that show the state of every session.
ScienceGPT — a domain-agnostic search engine wearing a physics costume
Built over the Nuclear Science References database, ScienceGPT's real contribution is a reusable search stack: multiple query modes, a typed combobox bound to a distinct-values table, and record cards that could front any structured corpus.

TariffsGPT — a command palette, a real Stripe upgrade, and PDFs that pay you back
Three production-grade pieces: a command palette that navigates, acts, and falls back to the assistant; a Stripe upgrade with a fail-closed mock path; and a customs-form parser that reads a CBP 7501 PDF and computes the refund you're owed.