Generate the application
Two ways in: the CLI, which is what you will use once you trust the model, and the browser designer, which is better the first time because it renders the ERD, validates as you type and keeps versions. Both call the same pipeline, so both produce the same application.
Path A — the command line
-
Check the model
Optional, because the generator runs the checker itself, but it is instant and it tells you the truth before anything is written.
shellbun language/checker.ts language/examples/crm.eml.mmd # crm.eml.mmd 0 errors · 0 warnings -
Generate
One command.
--no-setupkeeps it from installing and migrating straight away, which you want the first time so you can look at what it produced.shellbun packages/generator/src/cli/generate.ts generate \ --input language/examples/crm.eml.mmd \ --output generated-projects/crm \ --name crm \ --port 4001 --frontend-port 4000 \ --records-per-entity 25 \ --force --no-setupIt prints what it found as it goes: entities and their attribute counts, then the rules, hooks, sagas, state machines and categories it compiled. Read that list — it is the fastest way to notice a directive that did not parse.
-
Point it at a database
shellcd generated-projects/crm cp backend/.env.example backend/.env # edit backend/.env: # DATABASE_URL=postgresql://postgres:postgres@127.0.0.1:5432/crmThe generated
.env.exampleguesses a local socket connection for your machine. It is a guess; the URL is the one line worth checking by hand. -
Install, migrate, seed
shellbun install bun run db:setup # migrations, then every seed in orderThe seeds run in a deliberate order: users and roles, then reference types and your model's enums, then the dictionary (tables, columns, windows, tabs, fields), then categories, then sample business data, then rule definitions, then workflow definitions. The last two are the model's rules and workflows arriving in the database.
-
Run it
shellbun run dev # backend :4001, frontend :4000Sign in with the admin user the backend creates on first start —
ADMIN_EMAILandADMIN_PASSWORDinbackend/.env,admin@admin.com/adminby default.
--dry-run lists the files it would write without writing them.
--records-per-entity sizes the seeded sample data (1000 by default — use 25 while you are
iterating). --skip-frontend / --skip-backend generate one half.
--run-tests-fast runs the generated suite afterwards, skipping the bulk-seed volume tests.
Path B — the browser
The generator ships as an application in its own right. Run bun run dev at the repository
root and open localhost:3000. It walks a project through six steps: define, discover,
logic, generate, enhance, deploy.
bun run seed:admin -- --email you@example.com.
.mmd file you already have rather than describing a domain from scratch.
Validate renders the diagram through the same normalizer the preview uses and reports the result: the entity count when it parses, and Mermaid's own error with a line number and caret when it does not.
Use the browser while the shape of the model is still moving: the live ERD catches a wrong cardinality faster than reading operators, and Versions gives you a way back. Use the CLI once the model lives in version control, because it is scriptable, it is what CI runs, and it produces the same output.
What lands on disk
crm/
├── backend/ # NestJS + Fastify + Kysely
│ ├── migrations/ # bus_ tables, sys_ dictionary, indexes
│ ├── seeds/ # users, references + your enums, dictionary,
│ │ # categories, sample data, rules, workflows
│ └── src/modules/
│ ├── bus/ # generic CRUD over every business entity
│ ├── sys/ # the Application Dictionary API
│ ├── rules/ # GoRules evaluation
│ ├── workflow/ # the step executor
│ ├── hooks/handlers/ # ⭐ your hook bodies live here, never overwritten
│ ├── audit/ # append-only change log
│ └── auth/ # sessions, roles, permissions
├── frontend/ # TanStack Start + React 19 (198 files)
│ └── src/
│ ├── routes/ # one screen per entity, plus /admin/*
│ ├── components/ # dynamic table, dynamic form, admin shells
│ └── hooks/ # entity, field and lookup queries
├── tests/ # generated bun:test end-to-end suite (77 files)
├── model/ # the .mmd this was generated from, shipped along
├── docker/ · Dockerfile · docker-compose.yml
└── .github/workflows/ # CI for both halves
Regenerating safely
You will regenerate constantly — the model changes, the application follows. The rules about what survives are simple and worth knowing before you start editing generated code.
| What | On regeneration |
|---|---|
hooks/handlers/<Entity>.ts | Kept. Written once; new hooks are appended. Your logic is safe. |
hooks/handlers/index.ts | Rewritten — it is pure wiring. |
| Workflows and rules marked from the model | Rewritten. The model owns them. |
| Workflows built in the app's own designer | Kept. They carry source: designer and regeneration never touches them. |
| Dictionary help you edited | Kept. Seeds backfill help only where it is null. |
Everything else under src/ | Rewritten. Treat it as build output. |
Regenerating replaces the front-end source underneath a running dev server, which usually kills it.
Stop the app, regenerate, run bun run db:setup if the model's schema, enums, rules or
workflows changed, then start it again.