Root Directory
App workspace
App/
├── src/ # Source code
├── public/ # Static assets (images, icons, brand)
├── next.config.mjs # Next.js config (image domains, etc.)
├── tsconfig.json # TypeScript config (`@/*` → `./src/*`)
├── tailwind.config.ts # TailwindCSS theme + plugins
├── postcss.config.mjs # PostCSS configuration
├── vercel.json # Vercel deployment config (branch → environment mapping)
├── package.json # Dependencies + scripts
├── yarn.lock # Lockfile
└── components.json # shadcn/ui registry config
Repository layout
civiq-validation/
├── App/ # The Next.js application (described above)
├── docs/ # Docusaurus documentation site (this site)
├── supabase/
│ ├── functions/ # Edge Functions (Deno) — see Supabase Backend docs
│ ├── migrations/ # SQL migrations
│ ├── snippets/ # Saved SQL snippets
│ ├── templates/ # Auth email templates
│ ├── seed.sql # Seed data for local dev
│ └── config.toml # Supabase CLI config
└── README.md
Configuration files
| File | Purpose |
|---|---|
next.config.mjs | Image domain allow-list (Supabase Storage host) + experimental flags |
tsconfig.json | TS compiler options + @/* path alias |
tailwind.config.ts | Theme, plugins (tailwindcss-animate), content globs |
vercel.json | Branch-based deployments for main, dev, staging |
package.json | Project metadata, runtime + dev dependencies, scripts (dev, build, start) |
components.json | shadcn/ui configuration |
supabase/config.toml | Local Supabase project + edge-function settings |
Middleware Entry Point
Location: src/middleware.ts
Purpose: Next.js Edge middleware entry. Delegates to src/lib/supabase/updateSession.ts, which refreshes the Supabase session, redirects unauthenticated requests to /auth/sign-in, and POSTs to /api/permissions/revalidate on real browser refreshes.
Permission-key gating itself does not live in the middleware. See Middleware & Route Protection.
File Naming Conventions
Server Actions
- Pattern:
*-action.ts(e.g.create-campaign-action.ts). - Marked with
"use server". ReturnsFormState.
Services
- Pattern:
get*.ts,fetch*.ts,create*.ts,update*.ts. - Server-only. Returns
QueryResponse.
Components
- Pattern:
kebab-case.tsx. Domain-grouped undersrc/components/{domain}/.
Types
- Pattern:
camelCase.tsnamed after the domain noun.
Hooks
- Pattern:
use*.ts/use*.tsx.
Best Practices
-
Separation of Concerns
- Actions handle mutations and call services.
- Services handle data access and never mutate UI.
- Components handle UI; route guards handle access.
- Types provide envelopes (
QueryResponse,FormState).
-
Code Organization
- Group by domain (
campaign,petitions,teams). - Co-locate Zod schemas with the form they validate.
- Group by domain (
-
Reusability
- Common UI primitives in
components/ui/andcomponents/common/. - Sidebar bundles in
components/routes/readpermissionKeysfromTeamsContext.
- Common UI primitives in
-
Type Safety
- All public surfaces typed; runtime validation via Zod at every action boundary.
Directory size summary (approx)
| Directory | Files | Purpose |
|---|---|---|
actions/ | 30+ | Server Actions for mutations |
app/ | 100+ | Next.js routes, pages, layouts, API routes |
components/ | 250+ | React components (UI, domain features, route bundles) |
context/ | 7 | React Context providers |
hooks/ | 12 | Custom React hooks |
lib/ | 25+ | Utilities, Supabase clients, permission/Redis helpers |
middleware/ | 10+ | Legacy route pipelines (reference); active middleware lives at src/middleware.ts |
services/ | 50+ | Data access layer (incl. accessCheck/, roles/) |
types/ | 19 | TypeScript types |