File Structure Guide
This guide explains where new files should go as Blue North grows.
Preferred Layout
platform/
app/ Next.js routes only
components/
ui/ reusable design-system primitives
shell/ app chrome and navigation
features/
auth/
components/
actions/
data/
types.ts
campaigns/
voters/
turf/
canvassing/
knowledge/
admin/
sandbox/
lib/
supabase/ Supabase clients/session helpers
data/ legacy/static data loaders
*.ts small shared utilities/stores
supabase/
migrations/ SQL migrations
Route Files
Route files in platform/app should mostly:
- parse route/search params
- call feature entry components
- set route metadata when needed
- perform small redirects or auth gates
They should not become the home for large UI components or business logic.
Feature Folders
A feature folder may contain:
components/: feature-specific UIdata/: repositories, query functions, mappersactions/: server actions or mutation wrapperstypes.ts: feature-owned TypeScript typesconstants.ts: local constantstests/: focused tests when we add test tooling
Example:
platform/features/campaigns/
components/campaign-switcher.tsx
data/campaigns.repo.ts
types.ts
Component Rules
Use platform/components/ui only for generic primitives. A campaign-specific table, form, or dashboard panel belongs in a feature.
Examples:
- Generic button:
components/ui/button.tsx - Campaign switcher:
features/campaigns/components/campaign-switcher.tsx - Voter search table:
features/voters/components/voter-search-table.tsx
Import Direction
Preferred import direction:
app -> features -> lib/components/ui
features -> lib
features -> components/ui
components/ui -> no product features
lib -> no React UI unless explicitly a hook/store
Avoid importing from one feature into another unless the dependency is truly domain-level and stable. If two features need the same logic, move the shared piece to lib or a smaller shared domain module.
Migration Rule
Do not pause feature work to move the whole app at once. Move code into features/* when:
- you are actively touching it
- the new home is obvious
- the move reduces future confusion
- build/deploy remains easy to verify
Small, repeated boundary improvements are safer than one giant restructuring PR.