boilerplate-stack/
├── app/
│   ├── [locale]/                    # Locale-based routing
│   │   ├── (admin)/                 # Admin sections
│   │   │   ├── admin-dashboard/     # Platform super-admin
│   │   │   └── org-dashboard/       # Organization admin (B2B)
│   │   ├── (auth)/                  # Authentication pages
│   │   ├── (frontend)/              # Public pages
│   │   └── (private)/               # Private dashboard
│   ├── api/                         # API route handlers
│   ├── docs/                        # User-facing /docs site (MDX + nav)
│   ├── layout.tsx                   # Root layout
│   ├── manifest.ts                  # Dynamic PWA manifest
│   ├── sitemap.ts                   # Dynamic sitemap.xml
│   └── robots.ts                    # Dynamic robots.txt
├── components/
│   ├── admin/                       # Admin components
│   ├── billing/                     # Pricing, credits
│   ├── chat/                        # AI chat interface
│   └── ui/                          # shadcn/ui components
├── config/                          # Declarative source of truth
│   ├── affiliates.ts                # Affiliate tiers, commission rates, hold period
│   ├── ai.ts                        # LLM providers, models, agents, embeddings
│   ├── app.ts                       # Branding, business model, feature flags, logs
│   ├── email.ts                     # Email provider selection + credentials
│   ├── pricing.ts                   # Plans, packs, licenses, currencies, Stripe IDs
│   ├── referral.ts                  # Referral program (trigger, rewards, codes)
│   └── workspace.ts                 # Workspace defaults, signup bonus, slug rules
├── content/                         # MDX source for /docs pages
├── core/                            # Domain layer (queries + mutations + error codes)
│   ├── accounts/                   # Personal + workspace accounts, memberships
│   ├── affiliates/                 # Partner program (conversions, payouts)
│   ├── ai/                          # Stream gating, post-stream accounting
│   ├── billing/                     # Stripe webhook business logic, credits
│   ├── changelog/                   # Changelog entries CRUD
│   ├── chat/                        # Chat sessions + messages
│   ├── cron/                        # pg_cron schedule sync helpers
│   ├── documents/                   # RAG documents + chunk metadata
│   ├── licenses/                    # One-shot license records + features/limits
│   ├── logs/                        # Error-log admin reads
│   ├── organizations/               # Admin org/user CRUD
│   ├── referrals/                   # Referral program (codes, attributions, qualify)
│   └── roles/                       # Dynamic role definitions
├── hooks/                           # React hooks (use-chat, use-account, etc.)
├── i18n/                            # BCP-47 locale config + messages
├── lib/                             # Cross-cutting utilities (auth, security, supabase, etc.)
├── public/                          # Static assets (icons, fonts, legacy /docs/index.html)
├── scripts/                         # init-project.js, sync-ai-rules.sh, etc.
├── supabase/                        # schema.sql, cms-schema.sql, migrations/, functions/
├── tests/                           # Playwright (a11y, responsive, E2E)
├── __tests__/                       # Vitest unit tests (i18n parity, sanitize)
├── types/                           # TypeScript types
├── instrumentation.ts              # Next.js instrumentation hook (Sentry, OTel)
└── proxy.ts                        # Middleware: locale routing, auth gates, CSRF

Layered architecture

Per .claude/rules/architecture.md, every request flows through the same layers. Keep route handlers thin; push business logic into core/; read config from config/*; never bypass RLS without a deliberate createServiceClient() call.

app/[locale]/(group)/page.tsx        ← presentation only, thin
app/api/<resource>/route.ts          ← orchestration: auth gate + Zod + call core/
core/<domain>/queries.ts             ← read functions (cached where safe)
core/<domain>/mutations.ts           ← write functions (server actions)
core/<domain>/error-codes.ts         ← typed error enum + class
lib/<cross-cutting>/                 ← supabase, security, stripe, ai, email, etc.
config/*.ts                          ← declarative source of truth
supabase/schema.sql + migrations/    ← both must stay in sync

A route handler does four things and nothing more: enter through apiSecurity.* / withSecurity(), parse + Zod-validate the body, call a core/<domain>/{queries,mutations}.ts function, then map the result to an HTTP response with a code from error-codes.ts. If a route handler holds raw Supabase calls and ad-hoc business logic, refactor it into core/.

core/ exists so the same domain function can be reused across route handlers, server actions, jobs, and tests — a single place to apply caching tags, Zod parsers, and error codes, with clear RLS-vs-service-role decisions per function.