Skip to main content

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 UI
  • data/: repositories, query functions, mappers
  • actions/: server actions or mutation wrappers
  • types.ts: feature-owned TypeScript types
  • constants.ts: local constants
  • tests/: 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.