{"slug": "how-a-spec-becomes-a-full-stack-app-the-three-layer-model", "title": "How a Spec Becomes a Full-Stack App: The Three-Layer Model", "summary": "Remy, a product agent developed by MindStudio, compiles annotated markdown specifications into full-stack applications through a three-layer model consisting of a spec, a backend contract, and interfaces. The spec, written in MindStudio-Flavored Markdown and stored in `src/app.md`, serves as the source of truth, while the backend contract in `dist/methods/` is compiled TypeScript code derived from that spec. Eight interface types—including web, API, Discord, and Telegram—project the same backend contract, enabling a single `git push` to parse the spec, generate code, build interfaces, apply schema changes, and deploy the application.", "body_md": "# How a Spec Becomes a Full-Stack App: The Three-Layer Model\n\nThe canonical architectural diagram of Remy explained: how annotated prose compiles into methods, tables, and roles, then projects onto eight interfaces.\n\n## At a Glance\n\n**Three layers:** Spec (annotated prose) → Backend contract (methods, tables, roles) → Interfaces (web, API, Discord, Telegram, cron, webhook, email, MCP, agent)**The spec is source:** Lives in`src/app.md`\n\n, written in MSFM (MindStudio-Flavored Markdown). The application’s intent, domain knowledge, and rules.**The backend is compiled output:** Lives in`dist/methods/`\n\n, TypeScript methods and table definitions generated from the spec. In the same way`.js`\n\nis a compiled derivation of`.ts`\n\n, the backend code is a compiled derivation of the spec.**Interfaces are projections:** Eight ways to interact with the same backend contract. One method powers all of them.**Two SDKs enforce the contract:**`@mindstudio-ai/agent`\n\n(backend) and`@mindstudio-ai/interface`\n\n(frontend). Type-safe, sandboxed, managed.**Deploy is a compile step:**`git push`\n\n→ parse spec → generate code → build interfaces → apply schema changes → go live.\n\nRemy is a product agent that compiles annotated markdown into a full-stack app — backend, database, frontend, auth, tests, and deployment — in a single step. The three-layer model is how that compilation works.\n\n## What Are the Three Layers?\n\nEvery Remy app has the same structure:\n\n**Layer 1: The Spec.** A natural language document describing what the app does. Written in MSFM (MindStudio-Flavored Markdown), it captures the domain, the rules, the workflows. This is the source of truth. An AI agent reads the spec and generates the code, or you write the code directly. Either way, the spec is the application; the code is a derivation.\n\n**Layer 2: The Backend Contract.** Methods, tables, and roles. Methods are TypeScript functions that implement the logic. Tables define the data model. Roles define who can do what. This lives in `dist/`\n\n. In the same way `.js`\n\nis a compiled derivation of `.ts`\n\n, the backend code is a compiled derivation of the spec.\n\n**Layer 3: Interfaces.** Ways for users to interact with the contract. A web app, a REST API, a Discord bot, a Telegram bot, a cron job, a webhook, an email trigger, an MCP tool server, a conversational agent. The same methods power all of them. Interfaces can be as complex and polished as you want, but they’re always safe, because the backend contract is where anything real happens. The interface can’t break business logic or corrupt data.\n\nThe directory structure makes this visible:\n\n```\nmy-app/\n  mindstudio.json          ← the manifest (declares everything)\n  src/\n    app.md                 ← Layer 1: the spec (the application)\n    references/            ← supporting material\n  dist/\n    methods/               ← Layer 2: backend contract (compiled from spec)\n      src/*.ts               methods\n      src/tables/*.ts        table definitions\n      .scenarios/            seed scripts for testing\n    interfaces/            ← Layer 3: projections of the contract\n      web/                   React SPA\n      api/                   REST API config\n      discord/               bot config\n      ...\n```\n\nThe `src/`\n\ndirectory is authored source. Natural language specs, brand guidelines, reference materials. No code. The `dist/`\n\ndirectory is compiled output. TypeScript methods, React frontends, JSON configs. Generated from `src/`\n\nby an AI agent (or written directly).\n\n## How Does Layer 1 Work? (The Spec as Source)\n\nThe spec is the most important file in your project. It lives in `src/app.md`\n\nand describes what the app does: the data model, the business rules, the workflows, the edge cases.\n\nHere’s a fragment from a vendor approval app:\n\n```\n---\nname: Procure-to-Pay (P2P)\ndescription: Procure-to-Pay process for all domestic (U.S.) spend.\nversion: 1\n---\n\n# Procure-to-Pay\n\nWhen requesting a new vendor, there are three areas of review:\ngovernance, legal, and accounting, with approvals flowing in that order.\n\n~~~\nThe spec says \"three areas\" but lists four names. From the process flowchart, it is three sequential stages:\n\n  1. Governance, Risk & Compliance (GRC), one combined stage\n  2. Legal\n  3. Accounts Payable (AP)\n\nThese are sequential. Each stage must complete before the next is notified. If any stage rejects, the entire request is rejected.\n~~~\n\nAll invoices can be sent to the [Accounts Payable]{The AP team in\nthis context refers to the internal accounts payable department, not\na vendor's AP. Only users with the \"ap\" or \"admin\" role can process\ninvoices.} team for processing against the PO.\n```\n\nThe spec is written in **MSFM (MindStudio-Flavored Markdown)**, which extends standard Markdown with two primitives:\n\n**Block annotations**(fenced with`~~~`\n\n) attach to the content immediately above them. They clarify ambiguities, pin down edge cases, specify data representations.**Inline annotations**(`[text]{content}`\n\n) attach to a specific word or phrase. Good for definitions, units, and clarifications.\n\nAnnotations are just more context. They’re not typed or structured. They can be a word, a paragraph, or a code snippet. Each annotation makes compilation more deterministic.\n\nA spec with good annotations compiles the same way every time. When you want to change the app’s behavior, update the spec and the agent regenerates the code.\n\n## Other agents ship a demo. Remy ships an app.\n\nReal backend. Real database. Real auth. Real plumbing. Remy has it all.\n\nYou can also write code directly in `dist/`\n\nwithout a spec. That works too. But the spec is what makes the project maintainable over time. Code shows *what* the app does; the spec captures *why*.\n\n## What Is the Backend Contract? (Layer 2: Methods, Tables, Roles)\n\nThe backend contract is the core of the app: the methods and data model. It lives in `dist/methods/`\n\n.\n\n### Methods\n\nA method is a named async function that runs on the platform. It’s the universal unit of backend logic. Every interface (web, API, Discord, cron, webhook) is just a different way to invoke a method.\n\nOne file per method, one named export:\n\n``` js\n// dist/methods/src/submitVendorRequest.ts\n\nimport { db, auth } from '@mindstudio-ai/agent';\nimport { Vendors } from './tables/vendors';\n\nexport async function submitVendorRequest(input: {\n  name: string;\n  contactEmail: string;\n  taxId: string;\n}) {\n  auth.requireRole('requester');\n\n  const vendor = await Vendors.push({\n    name: input.name,\n    contactEmail: input.contactEmail,\n    taxId: input.taxId,\n    status: 'pending',\n    requestedBy: auth.userId,\n  });\n\n  return { vendorId: vendor.id, status: vendor.status };\n}\n```\n\nMethods receive a single `input`\n\nparameter (an object) and return an object. Both must be JSON-serializable. Methods run in isolated sandboxes with npm packages pre-installed. No servers to manage.\n\nThe `@mindstudio-ai/agent`\n\nSDK provides `db`\n\nand `auth`\n\nnamespaces that just work, plus access to 200+ AI models, 1,000+ integrations, and platform actions like file uploads and web scraping.\n\n### Tables\n\nEach table is a TypeScript file with a typed interface and a `defineTable<T>()`\n\ncall:\n\n``` js\nimport { db } from '@mindstudio-ai/agent';\n\ninterface Vendor {\n  name: string;\n  contactEmail: string;\n  status: 'pending' | 'approved' | 'rejected';\n  taxId: string;\n  paymentTerms?: string;\n}\n\nexport const Vendors = db.defineTable<Vendor>('vendors');\n```\n\nOne file per table, one export per file. The export name is what you reference in `mindstudio.json`\n\nand import in methods.\n\nThe platform provides managed SQL databases with typed schemas. No connection strings, no migrations to run manually. Push a schema change and the platform diffs it, clones the database, applies DDL, and promotes atomically. In development, reset to live data or truncate to empty tables with a single command.\n\nEvery table gets system columns automatically (`id`\n\n, `created_at`\n\n, `updated_at`\n\n, `last_updated_by`\n\n). You don’t define them; they’re added by the platform and maintained by SQLite triggers.\n\n### Roles\n\nRoles are declared in `mindstudio.json`\n\n:\n\n```\n{\n  \"roles\": [\n    { \"id\": \"requester\", \"name\": \"Requester\", \"description\": \"Can submit vendor requests and purchase orders.\" },\n    { \"id\": \"approver\", \"name\": \"Approver\", \"description\": \"Reviews and approves purchase orders.\" },\n    { \"id\": \"admin\", \"name\": \"Administrator\", \"description\": \"Full access to all app functions.\" },\n    { \"id\": \"ap\", \"name\": \"Accounts Payable\", \"description\": \"Processes invoices and payments.\" }\n  ]\n}\n```\n\nRoles are synced to the platform on deploy. Users are assigned to roles in the editor. In your methods, call `auth.requireRole('admin')`\n\nand the platform handles sessions, tokens, and user resolution.\n\nThe backend contract is what the platform builds and runs. It’s real TypeScript, real SQL, real npm packages. You own the output. No vendor lock-in at the code layer.\n\n## How Do Interfaces Work? (Layer 3: Eight Ways to Invoke the Same Methods)\n\nInterfaces are how users interact with your app. The same backend methods power all of them. A web frontend, a Discord bot, and a cron job can all invoke the same backend logic.\n\n| Interface | What it does |\n|---|---|\nWeb | React/Vite SPA hosted on CDN |\nAPI | REST endpoint with API key auth |\nDiscord | Slash commands that invoke methods |\nTelegram | Bot commands + message handling |\nCron | Scheduled method execution |\nWebhook | Inbound HTTP → method invocation |\nEmail | Inbound email → method invocation |\nMCP | AI tool server (methods as tools) |\nAgent | Conversational interface with LLM orchestration |\n\nYour methods don’t know or care which interface invoked them. The same `submitVendorRequest`\n\nmethod works whether it’s called from a React form, a Discord slash command, or a Stripe webhook.\n\nInterfaces can be as complex and polished as you want, but they’re always safe, because the backend is where anything real happens. The interface can’t break business logic or corrupt data.\n\n### Web Interface\n\nA full web application. The scaffold starts as Vite + React, but any framework with a build step works.\n\nThe frontend SDK provides typed RPC to backend methods:\n\n``` js\nimport { createClient } from '@mindstudio-ai/interface';\n\nconst api = createClient<{\n  submitVendor(input: { name: string }): Promise<{ vendorId: string }>;\n  listVendors(): Promise<{ vendors: Vendor[] }>;\n}>();\n\nconst { vendorId } = await api.submitVendor({ name: 'Acme' });\nconst { vendors } = await api.listVendors();\n```\n\nOn `git push`\n\n, the platform runs `npm install && npm run build`\n\nin the web directory and hosts the output on CDN. Zero configuration in your code. The platform injects connection details automatically.\n\n### API Interface\n\nExposes selected methods as REST endpoints with clean URLs and HTTP methods — for external consumers (other services, mobile apps, integrations).\n\nRoutes are declared in a spec file (`src/interfaces/api.md`\n\n) and compiled into structured config (`dist/interfaces/api/api.json`\n\n) the platform reads for routing and OpenAPI generation.\n\nExample:\n\n```\ncurl -X POST https://{app-subdomain}.mindstudio.ai/_/api/vendors \\\n  -H \"Authorization: Bearer sk_...\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{ \"name\": \"Acme\", \"contactEmail\": \"billing@acme.com\" }'\n```\n\n### Bot Interfaces (Discord, Telegram)\n\nSlash commands and message handling that invoke methods. Commands are synced to the platform on deploy. Same backend logic, different modality.\n\n### Scheduled and Event-Driven Interfaces (Cron, Webhook, Email)\n\nCron jobs run on a schedule. Webhooks accept inbound HTTP. Email triggers invoke methods when mail arrives at a registered address. All three are just different ways to invoke the same backend methods.\n\n### AI Interfaces (MCP, Agent)\n\nMCP exposes methods as tools for external AI agents (Claude Desktop, Cursor, etc.). The agent interface IS the agent — it has its own personality, system prompt, and model config, and orchestrates tool calls against the app’s methods internally.\n\nFor a comparison of how different AI models approach agentic coding workflows, see [Qwen 3.6 Plus vs Claude Opus 4.6 on agentic coding](/blog/qwen-3-6-plus-vs-claude-opus-4-6-agentic-coding).\n\n## How Do the Layers Connect? (The Two SDKs)\n\nThe backend contract is enforced by two SDKs:\n\n### Backend: `@mindstudio-ai/agent`\n\nUsed inside methods. Provides database access, auth, and platform capabilities:\n\n``` js\nimport { db, auth } from '@mindstudio-ai/agent';\nimport { Vendors } from './tables/vendors';\n\nexport async function approveVendor(input: { vendorId: string }) {\n  auth.requireRole('admin');\n\n  const vendor = await Vendors.update(input.vendorId, {\n    status: 'approved',\n  });\n\n  return { vendor };\n}\n```\n\n### Frontend: `@mindstudio-ai/interface`\n\nUsed in web interfaces. Typed RPC to backend methods:\n\n``` js\nimport { createClient } from '@mindstudio-ai/interface';\n\nconst api = createClient<{\n  approveVendor(input: { vendorId: string }): Promise<{ vendor: Vendor }>;\n}>();\n\nconst { vendor } = await api.approveVendor({ vendorId: '...' });\n```\n\nThe SDKs are the contract. Methods use `@mindstudio-ai/agent`\n\nto access the database and auth. Interfaces use `@mindstudio-ai/interface`\n\nto invoke methods. The platform handles the rest: sandboxed execution, database management, auth sessions, deployment.\n\n## Remy doesn't write the code. It manages the agents who do.\n\nRemy runs the project. The specialists do the work. You work with the PM, not the implementers.\n\nFor a deeper look at how AI models are evolving to support this kind of architecture, see [Gemma 4 vs Qwen 3.5 on open-weight agentic workflows](/blog/gemma-4-vs-qwen-3-5-open-weight-comparison).\n\n## How Does Compilation Work? (From Spec to Live App)\n\nWhen you push to git, the platform compiles the spec into a live app:\n\n**Parse manifest**— read`mindstudio.json`\n\nfrom the commit**Create release**— record in Postgres with status`building`\n\n**Mirror files**— copy repo files to S3 for instant editor access** Compile methods**— esbuild bundles each method into a single JS file, extracts npm package dependencies** Compile interfaces**— build the web interface (`npm install && npm run build`\n\n), generate configs for API/Discord/Telegram/cron/etc.**Parse table schemas**— TypeScript AST → column definitions, diff against live database** Compute pending effects**— roles diff, cron diff, bot command diffs, webhook/email diffs, table DDL** Apply**— create/update roles, sync bot commands, apply DDL to a staging database copy, swap the live pointer\n\nThe build log captures every step with timing. On failure, the error and context are captured. Failed releases never affect the live release.\n\nSchema changes are always applied to a clone, never to the live database directly. If the DDL fails, the live database is untouched and the release is marked `failed`\n\n.\n\nDatabases are keyed by release ID. Each release gets its own database copy. Rollback is safe because the previous release’s database still exists.\n\n## Why Does the Three-Layer Model Matter?\n\nThe three-layer model is what makes Remy a product agent, not a code generator.\n\n**The spec is the source of truth.** When AI models improve, you recompile the same spec into a better app. When requirements change, you update the spec and regenerate the code. The spec is what makes the project maintainable over time.\n\n**The backend contract is portable.** It’s real TypeScript, real SQL, real npm packages. You own the output. No vendor lock-in at the code layer. Migrating off the platform is a download and a re-pointing of your data-access layer; it’s not a months-long data extraction project.\n\n**Interfaces are projections.** The same backend methods power all of them. You can add a Discord bot, a cron job, or a webhook without touching the core logic. Interfaces can be as complex and polished as you want, but they’re always safe, because the backend is where anything real happens.\n\nThe three-layer model is the architectural reason Remy can ship a full-stack app from a spec. It’s not magic. It’s a compiler.\n\nFor more on how this compares to other AI coding approaches, see [Claude Code’s three-layer memory architecture](/blog/claude-code-source-leak-memory-architecture) and [Gemma 4 31B vs Qwen 3.5 for agentic workflows](/blog/gemma-4-31b-vs-qwen-3-5-comparison).\n\n## FAQ\n\n### What is MSFM?\n\nMSFM (MindStudio-Flavored Markdown) is the format for writing specs. It extends standard Markdown with block annotations (`~~~...~~~`\n\n) and inline annotations (`[text]{content}`\n\n) that attach precision to prose. A spec with good annotations compiles the same way every time.\n\n### Can I write code directly without a spec?\n\nYes. The `dist/`\n\ndirectory is real code. You can write methods, tables, and interfaces directly in TypeScript and React without ever touching `src/app.md`\n\n. The spec is optional. But the spec is what makes the project maintainable over time and what lets you regenerate the app when AI models improve.\n\n### What happens when I edit the compiled code?\n\nThe spec is the source of truth. If you regenerate from the spec, your hand-edits in `dist/`\n\nare overwritten. The right workflow is: update the spec to capture the change, then recompile. If you want to own the code permanently, stop regenerating from the spec and treat `dist/`\n\nas your codebase.\n\n### How does the database work?\n\nEach app gets its own serverless SQL database. The platform handles durability, sync, and schema migrations automatically.\n\n### Can I use an external database?\n\nRemy’s managed database is optimized for the spec-driven compilation workflow. If you need a different database architecture, use a different tool for that workload.\n\n### What’s the difference between a product agent and a coding agent?\n\nProduct agents and coding agents are different categories for different jobs. Coding agents edit existing codebases. Product agents compile specs into complete applications. They don’t compose in the same workflow.\n\n### How do I deploy a Remy app?\n\n`git push origin main`\n\n. The platform builds and deploys automatically. Push to a feature branch for a preview deployment. Rollback is a git revert.\n\n### What is Remy?\n\nRemy is a product agent that compiles annotated markdown into a full-stack app — backend, database, frontend, auth, tests, and deployment — in a single step. Built by Wooster Labs on the MindStudio platform substrate. See [goremy.ai](https://goremy.ai).\n\n## Start Building with the Three-Layer Model\n\nThe three-layer model is the architectural foundation of every Remy app. Spec → backend contract → interfaces. Annotated prose → TypeScript methods and tables → eight ways to interact with the same logic.\n\nIt’s not magic. It’s a compiler. And it’s how you ship a full-stack app from a conversation.", "url": "https://wpnews.pro/news/how-a-spec-becomes-a-full-stack-app-the-three-layer-model", "canonical_source": "https://www.mindstudio.ai/blog/remy-three-layer-model-spec-backend-interfaces/", "published_at": "2026-06-03 00:00:00+00:00", "updated_at": "2026-06-03 18:06:01.227875+00:00", "lang": "en", "topics": ["ai-products", "ai-tools", "ai-agents", "ai-infrastructure"], "entities": ["Remy", "MindStudio"], "alternates": {"html": "https://wpnews.pro/news/how-a-spec-becomes-a-full-stack-app-the-three-layer-model", "markdown": "https://wpnews.pro/news/how-a-spec-becomes-a-full-stack-app-the-three-layer-model.md", "text": "https://wpnews.pro/news/how-a-spec-becomes-a-full-stack-app-the-three-layer-model.txt", "jsonld": "https://wpnews.pro/news/how-a-spec-becomes-a-full-stack-app-the-three-layer-model.jsonld"}}