Skip to content

Architecture Map

A one-page guide to where things live in the LenserFight monorepo.

Layer overview

LayerPathResponsibility
Appapps/web/Entry point, routing, provider composition. No domain logic.
Featurelibs/features/*Vertical slices (battles, profile, home, lenserboard). Pages, hooks, feature components.
Datalibs/data/*Repositories, Supabase client, React Query wrappers, caching strategy.
Domainlibs/domain/*Business types, invariants, pure logic. No I/O.
UIlibs/ui/*Reusable components, forms, layout, theme tokens. No feature imports.
Infralibs/infra/*Analytics, moderation, storage adapters.
Sharedlibs/shared/*Error handling, auth guards, utilities shared across feature boundaries.
DBsupabase/Migrations, RLS policies, SQL functions, pgTAP tests.

Import direction: featuredatadomain; featureui; never reverse.

Layer summaries

apps/web/ — The React application shell. It composes providers (auth, query client, theme, helmet), declares routes, and renders feature pages. If you are adding a new page, register it here.

libs/features/* — One directory per product area. Each feature exports its pages via src/index.ts. Feature code may import from data, domain, ui, shared, and utils — never from another feature.

libs/data/* — All Supabase queries live here. Repositories call RPCs and map results to domain types. React Query hooks (useQuery, useInfiniteQuery) are defined here or in the feature that owns the query.

libs/domain/* — Pure TypeScript: types, enums, validation helpers, business rules. No React, no Supabase imports. The source of truth for what a Battle, Lenser, or XPEvent is.

supabase/ — Schema lives in migrations/. Functions and triggers live inline in migrations. Tests in supabase/tests/ run with pgTAP. Do not edit merged migration files — always add a new file.

"Where does X live?" lookup

Contribution targetWhere to touch
New column on an existing tableNew migration in supabase/migrations/ + pgTAP test in supabase/tests/
New Supabase RPCMigration (function definition) + libs/data/repositories/src/lib/ caller + type in libs/domain/
New battle field in UIMigration → repository → domain type → feature component in libs/features/battles/
New page / routeFeature page in libs/features/<area>/src/lib/pages/ → register route in apps/web/src/app/
New reusable componentlibs/ui/components/src/lib/ → export from src/index.ts
New CLI commandapps/cli/src/commands/ + spec file in same directory
i18n / translation stringapps/web/public/locales/ for forum; docs/ locale directories for docs
SDK surfacelibs/sdk/src/lib/ → export from src/index.ts