One declarative intent file -> a real, running fullstack app. The AI writes intent; the compiler writes the code. And the SAME intent compiles to two different stacks by changing one flag.
This is a runnable proof-of-concept of the IntentStack PRD. A single app.intent.yaml
is compiled by intentstack into a complete application — frontend, backend, database
schema, API and form/table wiring — all generated from one source of truth.
intent/app.intent.yaml (one source of truth)
|
parse -> normalize -> validate -> Core IR -> plan -> emit -> format -> verify
|
+------------------+-------------------+
v v
target: web_ts_minimal target: next_shadcn
Vite + React + daisyUI Next.js App Router + shadcn/ui
Hono API Route handlers
Drizzle + SQLite <----- shared data layer -----> Drizzle + SQLite
| Path | What it is |
|---|---|
intentstack/ |
The compiler workspace: Node reference emitter plus Rust crates for the emerging compiler core and CLI wrapper. |
demo/intent/app.intent.yaml |
The canonical example: a VoiceAgent landing page (navbar, hero, features, lead form, footer) + a leads dashboard, backed by a Lead entity and create_lead / list_leads actions. |
demo/intent/broken.example.yaml |
A deliberately broken intent that shows the validator catching mistakes (with "did you mean?" suggestions and fix_hints) before any code is generated. |
demo/app/ |
Generated app, target web_ts_minimal (Vite/React/daisyUI + Hono). |
demo/app-next/ |
Generated app, target next_shadcn (Next.js + shadcn/ui) — from the same intent. |
AGENTS.md |
The contract an AI agent follows: edit intent, never the generated code. |
From this folder:
# install the compiler's one dependency (a YAML parser)
cd intentstack && npm install && cd ..
# validate — no code generated
node intentstack/src/index.js check --project demo
# watch the validator reject a broken intent
node intentstack/src/index.js check --project demo --intent demo/intent/broken.example.yaml
# compile the SAME intent to two different stacks (only --target changes)
node intentstack/src/index.js build --project demo --out app # -> demo/app (Vite/React/daisyUI + Hono)
node intentstack/src/index.js build --project demo --target next_shadcn --out app-next # -> demo/app-next (Next.js + shadcn/ui)Run either app:
cd demo/app && npm install && npm run dev # web :5173, api :8787
# or
cd demo/app-next && npm install && npm run dev # http://localhost:3000Submit the demo form, then open the dashboard — the lead travels form -> API -> SQLite -> table, with zero hand-written React or backend code.
Not that it generates React (many tools do). It's that:
- the agent writes stable, typed semantic commands, not framework code;
- the validator rejects bad references (
Leadx,craete_lead, an unknown component) with a suggested fix before a single file is emitted; - the same intent is portable —
web_ts_minimalandnext_shadcnare produced from one file; the Drizzle/SQLite data layer is byte-identical across both, and only the framing (React/Hono vs Next/route-handlers, daisyUI vs shadcn) differs; - regeneration is idempotent and touches only
generated/-style zones, so hand-written code is preserved.
A target adapter is one module exporting managedZones + planFiles(graph)
(intentstack/src/targets/*.js), registered in targets/index.js and registry.js.
The Core IR, data-model facade (emit/shared/datamodel.js) and database driver contract
(emit/shared/db_driver.js) are reused as-is.
Implemented: new, check, build, plan, diff, apply, explain, doctor,
migrate, list_capabilities, schema, graph, collab, suggest, voice, editor, openapi, testgen, deploy, themes, marketplace, stats, verify; two target adapters;
entities -> Drizzle schema + schema-checksummed SQL migration manifest + additive evolution migrations + explicit migration runner + zod validators; record actions -> Hono routes /
Next route handlers; shared top-level navigation; pages/sections -> navbar, hero, card_grid, stats,
pricing_cards, content, form, table, record_detail, footer, custom_component; custom component source safety checks and generated CSP; derived API clients; inline
table detail/edit/delete row actions; dynamic detail pages; embedded docs examples via content.example.add +
embed_only sections; normalize phase for compact field refs; generated Prettier formatting; generated npm run build
verification; JSON Schema; visual graph HTML export; patch history; basic auth guards; durable workflow run log/retry; workflow/integration metadata and provider-specific integration clients;
webhook dispatch; realtime subscribe_records SSE streams plus WebSocket transport for web_ts_minimal; optional multi-tenant record isolation; SQLite and PostgreSQL database drivers for schema, migrations, clients, package deps and app docs; visual editor HTML export plus local editor --serve patch-apply/writeback server, drag/drop section reorder, and live page preview rendered from current intent; semantic collaboration conflict detection against incoming git refs; context-aware patch suggestions; voice/text-to-patch commands; Rust intent_core with YAML/JSON parsing, semantic diagnostics, symbol table, resolved refs, typed graph, bindings, pass summaries, and Rust-native generated file planning; generated health/metrics endpoints; trace context headers, structured request logs, and optional OTLP/HTTP OpenTelemetry span export; generated API contract tests and Playwright E2E flows from pages/forms/tables; deploy config generation plus explicit --execute command runner; external plugin target loading; local theme packs and marketplace listing/install with version lockfile; GitHub Actions CI for compiler lint/tests, Rust core/wrapper tests, and generated app build matrix.
Still partial: full Rust file-content emitter parity.
Agents change the app with small patches, not full rewrites:
intentstack apply demo/patches/001-add-email-and-pricing.yaml --project demo --writeapply prints a semantic diff, re-validates the result, and refuses to write if the
patch would introduce errors. The bundled patch is one step that retitles the hero, adds
email to the Lead entity + lead form + dashboard table, inserts a pricing section and
a navbar item. Rebuilding regenerates both targets: the new email column and pricing
section appear in the Vite/daisyUI and Next/shadcn apps alike, and the SQLite migration
stays identical across them. The result is saved as demo/intent/app.patched.example.yaml.
Use node intentstack/src/index.js list_capabilities --json for the current patch op list.