Quickstart — first project
A 5-minute taste of the loop: author atoms → validate → codegen → run. Uses the SenLang bridge as the target.
For the full walkthrough with a real entity, multiple features and the 6-tab editor, see Examples → Habit Tracker.
What you’ll author
Section titled “What you’ll author”- 1
vision - 1
module - 1
featurewith Layer 2 behavior (a singlesetStatestep) - 1
criterionlinked viaverifies
Total: 4 atoms, 1 relation.
-
Project skeleton.
Terminal window mkdir hello-atoms && cd hello-atomsbun init -ybun add @atomprd/spec @atomprd/core @atomprd/codegen @atomprd/codegen-senlang -
Manifest. Create
atoms/manifest.json:{"version": "0.3","atoms": [{"id": "vis_main_a1b2","kind": "vision","name": "Hello Atoms","problemStatement": "Show the smallest possible AtomPRD → SenLang round-trip.","valueProposition": "Toy demo."},{"id": "mod_main_c3d4","kind": "module","name": "Counter"},{"id": "feat_increment_e5f6","kind": "feature","name": "Increment counter","intent": {"userStory": "As a user I tap a button and the counter goes up by 1."},"behavior": {"steps": [{ "kind": "setState", "path": "state.count","value": { "$expr": { "op": "+", "args": [{ "$ref": "state.count" }, 1] } } }]}},{"id": "cri_increments_g7h8","kind": "criterion","name": "Tapping increment increases count by 1","pattern": "WHEN","actor": "user","trigger": "taps the increment button","system_response": "the count display increases by 1","behavior": {"before_after": {"state_diff": { "count": { "before": 0, "after": 1 } },"api_calls": []}}}],"relations": [{ "type": "verifies", "from": "cri_increments_g7h8", "to": "feat_increment_e5f6" }]} -
Validate. Create
validate.ts:import { PrdManifestSchema } from "@atomprd/spec";import manifest from "./atoms/manifest.json" assert { type: "json" };const r = PrdManifestSchema.safeParse(manifest);if (!r.success) { console.error(r.error.issues); process.exit(1); }console.log("OK:", r.data.atoms.length, "atoms,", r.data.relations.length, "relations");Terminal window bun run validate.ts# OK: 4 atoms, 1 relations -
Codegen. Create
gen.ts:import { PrdDocument } from "@atomprd/core";import { runTemplate } from "@atomprd/codegen";import { senlangTemplate } from "@atomprd/codegen-senlang";import manifest from "./atoms/manifest.json" assert { type: "json" };const doc = PrdDocument.load(manifest);const result = await runTemplate(senlangTemplate, {doc,outDir: "./out",});console.log(`Wrote ${result.files.length} files to ./out`);Terminal window bun run gen.ts# Wrote N files to ./out -
Inspect. You should see
out/app.sen.json,out/scenarios/cri_increments_g7h8.json, and a source-map sidecar. Render it:src/main.tsx import { createRoot } from 'react-dom/client'import { SenAppV2 } from '@senlang/renderer-react'import doc from '../out/app.sen.json'createRoot(document.getElementById('root')!).render(<SenAppV2 document={doc} />)
That’s the loop end-to-end. The same shape scales up: more atoms, more relations, more behavior steps, more criteria. The bridge stays the same.
Where to next
Section titled “Where to next”- Examples → Habit Tracker — 21 atoms, 6 features, multi-screen ui_view, two fixtures, all 4 patterns.
- Concepts → Two-layer model — why Behavior is a separate jsonb.
- Authoring → Six-tab editor — the cloud authoring UX.
- Codegen → SenLang bridge — the deterministic lowering rules.