Product Design
The Product Layer
How I structured the route map, fan and org views, and page responsibilities so the same system can serve different kinds of readers without splitting into separate products.
ByColby Reichenbach
I structured the product around page jobs and reader intent, not around one oversized baseball dashboard.
When I started building AiBS, I did not want the product to become one giant page full of cards, charts, and filters competing for attention. That kind of design can look powerful at first, but it makes the product harder to read and harder to maintain because every page ends up trying to answer every question at once.
The product is organized around route purpose instead. The home page has one job. Game pages have another. Team pages have another. Umpire pages have another. Articles and About handle longer written analysis and system explanation. Reports exist for postgame review. The route structure is not just URL organization. It is one of the core architectural decisions in the product.
I also knew early on that the same baseball facts would need different framing depending on the reader. Fan and org views are built into the application layer for exactly that reason. One system, one source of facts, two presentation modes.
Route architecture
The product architecture is legible enough to read directly from the app tree.
The product is built on Next.js App Router with React Server Components. The route surface breaks into distinct families, each with a defined job. The diagram below shows the public, authenticated, and admin surfaces, with fan and org mode as a cross-cutting layer that applies across several of them.
- •/ Home: the ABS landscape front page
- •/game/[gamePk] Game pages: state-aware challenge and event context, pregame through final
- •/teams and /teams/[teamId] Team pages: challenge identity, usage patterns, and decision behavior
- •/umpires and /umpires/[umpireId] Umpire pages: review exposure, volatility, and consequence
- •/articles and /articles/[slug] Articles: longer baseball analysis published inside the product
- •/about and /about/[slug] About: system architecture and design documentation
- •/reports/[gamePk] Reports: postgame challenge review
- •/v/[vizId] Visualization sharing
- •/u/[username] Public user profiles
- •/query Query (authenticated, access-controlled)
- •Admin surface: access management, AI review, community moderation, editorial workflow
View modes
Fan and org mode are part of the application architecture, not just two visual themes.
Fan and org mode did not start as a cosmetic toggle. They exist because the same baseball state needs different framing for different readers. Fan mode leans toward story, readability, and cleaner narrative ordering. It makes review moments, matchup context, and challenge behavior easier to follow without forcing the user into dense operational language. Org mode pushes further toward review management, timing, modeled context, and decision-oriented detail where the product has enough evidence to support that framing.
The mode changes presentation and emphasis, not the underlying facts. There are not two separate data pipelines or two separate truth layers. Both modes read from the same challenge records and baseball state. The route resolves the view mode and shapes the output accordingly.
Fan and org mode currently affects six page route families: the home page, game pages, team index and detail, and umpire index and detail. The AI surfaces also carry audience mode into prompt construction and task-family resolution, so the conversational tone adapts alongside the page framing.
Game pages
Pregame, live, and final are three different products sharing one route.
The game page is where route purpose is most visible. Pregame focuses on matchup tendencies, likely review windows, and setup context. Live focuses on challenge patterns, current review consequences, and the ongoing shape of the game. Final shifts toward postgame challenge analysis, realized swings, missed opportunities, and low-value usage review.
Many sports products flatten all three states into one page and let the user figure out which information is relevant at any given moment. A live game page should behave like a live page. A final game page should shift toward review and consequence. The state is not a filter. It is the primary context.
Once page state is explicit, the loaders, charts, and AI surfaces attached to the route can be scoped more precisely to the actual job the page is doing.
Articles and About
Longer writing lives inside the product because the product already has the context the writing depends on.
Articles are part of the product because the baseball context, review surfaces, and analytical framing the writing depends on are already here. Keeping analysis inside the same system puts it closer to the data that supports it. When an article references challenge patterns, team behavior, or umpire trends, the supporting data lives in the same product the reader is already using.
The About desk serves a different purpose. Architecture choices, modeling boundaries, product design decisions, and system documentation live here as permanent pages rather than buried in code comments or scattered dev notes. These are the articles you are reading right now.
Both desks are part of the product architecture. They are maintained and updated like the rest of the system.
How the product loads data
Route logic stays close to the server-side model of the page.
The application is SQL-first and server-rendered. Server components and route handlers read from shared helpers in src/lib. Analytics pages are built from page-model helpers rather than doing route-local math in every file. Query logic and data-shaping logic live close to the server-side model of the product rather than being recreated differently in each route.
Centralizing that work also helps with consistency. When the same summary or model output appears in multiple places, there is one retrieval and shaping path rather than several that diverge over time. The browser is not treated as a trusted data or authorization layer. Product logic, data loading, and permission boundaries hold on the server side.
The current codebase serves 27 page routes and 37 API routes. Server components handle the initial data load and rendering. Client components handle interactivity, chart rendering, and AI chat surfaces. That split keeps the product responsive while keeping data integrity server-side.
I wanted the page purpose to feel obvious enough that the route structure becomes invisible.
