Files
Ghost_Kitchen/CLAUDE.md
T
lukasandClaude Sonnet 5 ea459e72b3 Add the customer ordering page
Builds the main customer-facing flow: browse the Brand's menu, add
items to a cart, and check out either as a guest (name + contact) or,
if signed in, as the account customer — both call the existing
placeOrder server function, which already distinguishes the two. On
success, navigates to a new /orders/$orderId status page showing each
Order Item's Preparation Steps, queue position, ETA, and (per the
domain rules already established) a Cancel button while cancellable
and a pickup-confirmation button once ready.

Styled with SCSS Modules per CLAUDE.md; added the sass dependency and
the src/styles/ structure it describes (globals.scss imported once in
__root.tsx, alongside the existing Tailwind stylesheet the not-yet-
mounted header-user.tsx component depends on).

Verified end-to-end against a throwaway local Postgres: menu renders
with seeded items, cart quantities update, guest checkout places a
real order, and the status page reflects a real cancellation.

Also fixes CLAUDE.md's Commands section, which documented pnpm even
though this repo only has npm (package-lock.json, no pnpm installed).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-09 20:31:32 +02:00

7.1 KiB

CLAUDE.md

Guidance for Claude Code when working in this repository.

Project overview

[1-2 sentences: what this app does, who it's for]

Stack:

  • TanStack Start (React, file-based routing via TanStack Router)
  • TypeScript (strict mode)
  • Vite
  • SCSS Modules
  • Drizzle ORM + PostgreSQL
  • Better Auth
  • npm

Commands

npm run dev          # start dev server (http://localhost:3000)
npm run build        # production build
npm run typecheck    # tsc --noEmit
npm run lint         # eslint
npm test             # vitest run

Always run typecheck and lint before considering a task done. If build fails with TypeScript errors, run typecheck first to isolate them.

Project structure

src/
├── routes/            # file-based routes (TanStack Router)
│   ├── __root.tsx      # root layout, wraps every page
│   └── index.tsx        # home page
├── routeTree.gen.ts    # AUTO-GENERATED — never edit by hand
├── router.tsx           # router instance/config
├── components/
│   ├── ui/               # base primitives (buttons, inputs, etc.)
│   └── <domain>/         # feature-specific components, e.g. posts/, auth/
├── lib/                  # shared utilities, API clients, helpers
├── db/
│   ├── schema.ts         # Drizzle schema definitions
│   ├── index.ts          # Drizzle client instance
│   └── migrations/       # generated SQL migrations — never hand-edit
├── styles/
│   ├── globals.scss      # global styles, resets
│   └── _variables.scss   # shared SCSS variables/mixins (partial)
public/                  # static assets
drizzle.config.ts         # Drizzle Kit config (schema path, out dir, dialect)

Routing conventions

  • Routes live under src/routes/ and map to URLs by file name/path.
  • __root.tsx is the root layout every route renders inside.
  • routeTree.gen.ts is generated by TanStack Router — never edit it directly; it regenerates on dev/build from the files in routes/.
  • Use route loaders for data fetching tied to a route, not useEffect.
  • Keep server-only code (secrets, DB access) out of files that ship to the client; be careful with verbatimModuleSyntax so server code doesn't leak into client bundles.

Styling (SCSS Modules)

  • Every component that needs styles gets a co-located Component.module.scss next to Component.tsx — not a shared stylesheet.
  • Import as import styles from './Component.module.scss' and apply classes via className={styles.foo}; never reference a module class by string outside that import.
  • Class names in .module.scss files are camelCase (e.g. .cardHeader, not .card-header) so they read naturally as styles.cardHeader.
  • Shared tokens (colors, spacing, breakpoints) live in src/styles/_variables.scss and are pulled in with @use '~/styles/variables' as *; — don't hardcode colors/spacing that already exist as a variable.
  • src/styles/globals.scss is for resets and truly global rules only (imported once in __root.tsx); component-specific styles always go in a module, never in globals.
  • Avoid deep nesting (max ~3 levels) and avoid !important.

Code style

  • TypeScript strict mode; avoid any. Prefer inferred types everywhere possible — let TypeScript infer return types and variable types rather than annotating them. Only add explicit types where inference can't reach: function parameters (always type these), exported values whose inferred type would be unclear to a caller, or when inference produces something wider than intended (e.g. use as const or a literal type instead of annotating).
  • Functional React components only, no class components.
  • Use arrow functions everywhere (components, handlers, utilities) instead of the function keyword — e.g. const getUser = async (id: string) => {...} and export const Button = (props: ButtonProps) => {...}.
  • [Naming conventions: PascalCase components, camelCase functions/vars, etc.]
  • [Import order / path aliases, e.g. ~/ or @/ for src/]
  • Co-locate a component's test file next to it unless it's a shared primitive in components/ui/ (see "Styling" for .module.scss placement).
  • No comments unless they're unavoidable for understanding — e.g. explaining why a non-obvious workaround exists, documenting a constraint imposed by an external system, or flagging a case that genuinely can't be made self-evident through naming/structure. Never comment what the code already says; prefer clearer names and smaller functions over a comment explaining an unclear one.

Data layer (Drizzle + Postgres)

  • Schema lives in src/db/schema.ts; the Drizzle client is created once in src/db/index.ts and imported from there — don't instantiate new clients elsewhere.
  • Only import db/* from server-only code (route loaders/actions, server functions) — never from client components, to avoid leaking DB credentials into the client bundle.
  • Query with Drizzle's query builder (db.select()..., db.query.table...) rather than raw SQL, unless a query genuinely needs it.
  • After changing schema.ts, generate a migration rather than editing the database by hand:
    pnpm drizzle-kit generate   # create a migration from schema changes
    pnpm drizzle-kit migrate    # apply pending migrations
    
  • Never hand-edit files under db/migrations/ — they're generated and should be treated as a history, not touched retroactively.
  • [Connection details: env var name for DATABASE_URL, whether using a connection pool like postgres.js or node-postgres, local dev DB setup e.g. Docker Compose]

Testing

  • [Test runner and conventions, e.g. Vitest + Testing Library]
  • [Where tests live: colocated *.test.ts(x) vs a __tests__ dir]
  • Run the relevant test file after changes, not just the full suite, unless asked to verify broadly.

Things to avoid

  • Don't hand-edit routeTree.gen.ts or files under db/migrations/.
  • Don't run destructive Drizzle commands (drizzle-kit push against a populated DB, or anything that drops columns/tables) without confirming first — prefer generate + migrate so changes are reviewable.
  • Don't introduce a new state-management library without asking — prefer route loaders / TanStack Query cache / local state first.
  • Don't add new dependencies without checking package.json for an existing one that already covers the need.
  • [Any other project-specific guardrails]

Git / PR conventions

  • [Commit message style, branch naming, whether Claude should commit automatically or leave changes staged for review]

Agent skills

Issue tracker

Issues live as Gitea issues on the self-hosted instance at git.lukas-harat.com (lukas/Ghost_Kitchen), accessed via the REST API with curl (no tea CLI installed). See docs/agents/issue-tracker.md.

Triage labels

Default canonical label strings (needs-triage, needs-info, ready-for-agent, ready-for-human, wontfix) used as-is. See docs/agents/triage-labels.md.

Domain docs

Single-context: CONTEXT.md + docs/adr/ at the repo root. See docs/agents/domain.md.