Where things are
| Path | What it holds |
|---|---|
app/[locale]/ | The pages: landing, create (new), a plan (p/[slug]), its created screen and Max's screens (p/[slug]/max) |
components/ | The UI, grouped by area: landing/, plan/, sheets/, max/ |
lib/actions/ | Server actions |
lib/data/ | Reading a plan and working out who is looking at it |
lib/max/ | Max's logic, as pure functions |
lib/hooks/ | Client hooks: device identity, the plan's viewer, Max |
messages/ | All copy, one file per language |
styles/styles.css, app/globals.css | The design system, then the screens built with it |
prisma/ | The schema and its migrations |
tests/ | unit/ for Max's logic, integration/ for the server actions |
docs/ | This documentation site |
Pages and languages
Every page lives under app/[locale]/. The locale is the first part of the URL: /fr, /en or /es, with French as the default. app/[locale]/layout.tsx is the root layout: it loads the fonts, the messages and the header.
Copy never sits in components. Each string has a key in messages/en.json, fr.json and es.json, and the three files have the same keys.
Server actions
Each action in lib/actions/ comes in two files:
item.core.ts,attendee.core.ts,plan.core.tshold the logic. They take a database client, validate their input with the schemas inlib/validation.ts, and can be tested on their own.item.ts,attendee.ts,plan.tsare what the UI calls. They add rate limiting, set the device cookie where it is needed and revalidate the plan's page.
The plan page
app/[locale]/p/[slug]/page.tsx loads the plan on the server and hands it to PlanBoard, a client component. PlanBoard owns the two sheets (answer, add an item), which open from the ?sheet= query parameter, and wires in Max.