# __APP_NAME__

Generated by [`@dreamtree-org/ai-builder`](https://www.npmjs.com/package/@dreamtree-org/ai-builder).
Express API + (Vite/React SPA) wired to **`@dreamtree-org/korm-js`** (data) and
**`@dreamtree-org/twreact-ui`** (UI). Multi-tenant, module-driven RBAC,
CSS-variable theming. SPA only (no SEO).

## Quick start

```bash
cp .env.example .env          # set DB_URL + JWT_SECRET
npm run setup                 # install + build + db:sync + seed:rbac + install AI skills
npm run dev                   # API on :5002  (client dev: npm run client:dev)
```

`npm run setup` also installs the AI skills (ai-builder + korm-js + twreact-ui
`init --ai claude`) so your assistant knows how to build, the data contract, and the
UI catalog. Swap the provider by re-running `init --ai cursor|copilot|gemini|openai`.

Prefer step-by-step? `npm install` → `npm run db:sync` → `npm run seed:rbac` → `npm run dev`.

> **Commit your lockfiles.** The first `npm run setup` (or `npm install`) generates
> `package-lock.json` (root) and `client/package-lock.json` — both are tracked, not
> gitignored. Commit them: Docker and CI then run `npm ci` for reproducible builds
> (falling back to `npm install` only if a lockfile is missing).

## Docker

```bash
cp .env.example .env
docker compose up --build      # API + SPA on :5002 (AUTO_MIGRATE runs db:sync + seed:rbac)
```

The image is multi-stage (builds the SPA, runs the API as a non-root user, with a
`/health` healthcheck). For mysql/postgres, point `DB_URL` (or the platform DB) at a
DB service — see the commented block in `docker-compose.yml`.

## How it works

- **`modules.config.js`** is the single source of truth: it drives the RBAC
  permission seed, the model→module map, nav, and route guards. Add a feature by
  adding a module here, not by hand-wiring permissions.
- **All data access** goes through KORM: `POST /api/crud/:Model` with a JSON body
  `{ action, where, data, select, with, ... }`.
- **RBAC** runs in the data layer (`models/BaseModel.validate`): JWT auth +
  `(module, action)` check; `BaseTenantModel` adds branch scoping and row-level
  (`resource_grants`) filtering for instance-scoped models.
- **UI:** compose `@dreamtree-org/twreact-ui` only — never re-implement a
  component. A gap is a GitHub issue against the twreact-ui repo.

## Scripts

| Script | Purpose |
| --- | --- |
| `npm run setup` | One-shot: install + build + db:sync + seed:rbac + install AI skills |
| `npm run dev` | Run the API (`node --watch`) |
| `npm run build` | Build the client SPA into `client/dist` |
| `npm run db:sync` | Create/alter tables from `schema/sync.json` |
| `npm run seed:rbac` | Seed permissions + tenant-admin from the registry |
| `npm run db:seed` | Seed domain data from `schema/sync.json` seed arrays |
| `npm run db:schema-generate` | Introspect the live DB into `schema/schema.json` |
| `npm test` | Unit tests — backend + client (Vitest) |
| `npm run test:e2e` | End-to-end user journeys (Playwright) |

## Testing

User journeys are drafted in [`tests/USER-JOURNEYS.md`](tests/USER-JOURNEYS.md) —
each maps to a Playwright spec in `tests/e2e/`. Unit tests (Vitest) live in
`tests/unit/` (backend) and `client/src/**/*.test.js` (client).

```bash
npm test                       # Vitest unit (backend + client)
npm run e2e:setup              # one-time: db:sync + seed:rbac + build
npx playwright install         # one-time: download browsers
npm run test:e2e               # run the user-journey suite
```
