This codebase keeps the product surface stable by separating routing, application orchestration, business logic, and persistence.
app/Thin Next.js pages and route handlers. These should parse inputs, call the appropriate feature or application module, and return UI or serialized responses.features/UI feature shells and reusable page-level client logic. Feature modules may compose components and hooks, but they should not import route files.lib/application/Use-case orchestration for read models, admin flows, cron flows, and API-facing operations. Application modules should stay framework-agnostic and should not importnext/*orapp/*.lib/engine/Core competition and trading workflows such as decisions, execution, resolution, cohort lifecycle, and market sync orchestration.lib/db/SQLite connection management, schema, transactions, ids, and query modules.lib/openrouter/,lib/polymarket/,lib/scoring/,lib/utils/Provider integrations, scoring helpers, parsing, and shared utility logic.
- Route handlers in
app/api/*should go throughlib/application/*, not directly into low-level DB or engine internals. - Page files in
app/*should stay as thin wrappers aroundfeatures/*. - Thin public barrels should stay thin. Large internal refactors should happen behind stable entrypoints like:
lib/application/cron.tslib/application/cohorts.tslib/application/markets/index.tslib/application/models/index.tslib/db/index.tslib/engine/decision.tslib/engine/execution.tslib/engine/resolution.tslib/openrouter/parser/parseDecision.tslib/types/entities.ts
Automated checks live in scripts/check-architecture.mjs.
That script currently enforces:
- line-count caps on the main public entrypoints and route/page wrappers
- import-boundary restrictions for feature modules, application modules, and thin API routes
Browser smoke coverage lives in /playwright.
After UI refactors, the minimum browser pass should verify:
- public navigation on desktop and mobile
- a seeded family detail route
- a seeded cohort detail route and decision expansion behavior
- a seeded market detail route
- admin login plus authenticated admin costs and logs pages
The Playwright suite uses a deterministic seeded SQLite database prepared before the Next.js dev server starts. That keeps browser tests stable and avoids depending on local data/ files.
Current browser commands:
npm run test:e2efor the seeded rich-data scenarionpm run test:e2e:emptyfor the empty-state scenario
If a file starts doing more than one of these jobs, it should probably be split:
- input parsing
- orchestration
- domain/business rules
- database access
- presentation/rendering