Skip to main content
MindStudio
Pricing
Blog About
My Workspace
Remy spec-driven development product agent architecture

How a Spec Becomes a Full-Stack App: The Three-Layer Model

The architecture behind Remy: how annotated prose compiles into methods, tables, and roles, then projects onto eight interfaces from a single backend contract.

MindStudio Team RSS
How a Spec Becomes a Full-Stack App: The Three-Layer Model

This is a technical architecture deep-dive: how a spec compiles into a running app, with the code and SDKs underneath. If you just want the overview, start with what is a product agent? or what is spec-driven development?. This page is the machinery.

Every Remy app has the same shape: a spec compiles into a backend contract, and the backend contract projects onto interfaces. Three layers. This is the architectural reason a product agent can ship a full-stack app from a plain-language description, and it’s worth understanding even if you never write the code by hand, because it’s what makes the result maintainable instead of disposable.

TL;DR

  • Every Remy app has the same shape, three layers: the spec (annotated prose), the backend contract (methods, tables, roles), and the interfaces that project it.
  • The spec is the source of truth, a plain-language .md file written in MSFM that captures the domain, rules, and edge cases. It’s the application, and not documentation of it.
  • The backend is compiled output: real TypeScript methods, typed tables, and roles generated from the spec, the same way .js is compiled from .ts.
  • Interfaces are projections. Eight surfaces (web, API, Discord, Telegram, cron, webhook, email, MCP) all invoke the same methods, so they can’t drift from each other.
  • The layers are held together by two type-safe SDKs: one your methods use to reach the database and auth, one your frontend uses to call methods.
  • Because the backend is real, portable code you own, moving your app elsewhere is a download, not a months-long extraction.
  • Deploy is a compile step. Hit Publish and the platform generates the code, builds the interfaces, and promotes atomically. A failed build never touches the live app.
  • The spec stays the source, so a stronger model recompiles it into a better app. That’s what makes Remy a product agent rather than a code generator.
Learn Hermes. Free. 1 hour.
The free Hermes Agent crash courseReserve your spot

What are the three layers?

Layer 1: The spec. A natural language document describing what the app does. Written in MSFM, it captures the domain, the rules, the workflows. This is the source of truth. Remy drafts it from your description, and it’s what the code is generated from. The spec is the application; the code is a derivation.

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. In the same way .js is a compiled derivation of .ts, the backend code is a compiled derivation of the spec.

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. 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.

The directory structure makes this visible:

my-app/
  src/
    app.md                 ← Layer 1: the spec (the application)
    references/            ← supporting material
  dist/
    methods/               ← Layer 2: backend contract (compiled from spec)
      src/*.ts               methods
      src/tables/*.ts        table definitions
    interfaces/            ← Layer 3: projections of the contract
      web/                   React app
      api/                   REST API config
      discord/               bot config
      ...

The src/ directory is authored source: natural language specs, brand guidelines, reference materials, no code. The dist/ directory is compiled output (TypeScript methods, React frontends, configs) generated from src/.

Layer 1: the spec as source

The spec is the most important file in your project. It describes what the app does: the data model, the business rules, the workflows, the edge cases.

Here’s a fragment from a vendor approval app:

---
name: Procure-to-Pay (P2P)
description: Procure-to-Pay process for all domestic (U.S.) spend.
version: 1
---

# Procure-to-Pay

When requesting a new vendor, there are three areas of review:
governance, legal, and accounting, with approvals flowing in that order.

~~~
The spec says "three areas" but lists four names. From the process flowchart, it is three sequential stages:

  1. Governance, Risk & Compliance (GRC), one combined stage
  2. Legal
  3. Accounts Payable (AP)

These are sequential. Each stage must complete before the next is notified. If any stage rejects, the entire request is rejected.
~~~

All invoices can be sent to the [Accounts Payable]{The AP team in
this context refers to the internal accounts payable department, not
a vendor's AP. Only users with the "ap" or "admin" role can process
invoices.} team for processing against the PO.

Other agents ship a demo. Remy ships an app.

UI
React + Tailwind ✓ LIVE
API
REST · typed contracts ✓ LIVE
DATABASE
real SQL, not mocked ✓ LIVE
AUTH
roles · sessions · tokens ✓ LIVE
DEPLOY
git-backed, live URL ✓ LIVE

Real backend. Real database. Real auth. Real plumbing. Remy has it all.

The spec is written in MSFM (MindStudio-Flavored Markdown), which extends standard Markdown with two annotation primitives, block annotations (fenced with ~~~) and inline annotations ([text]{content}), that attach precision to prose. Each annotation makes compilation more deterministic; a spec with good annotations compiles the same way every time. (The full syntax is in the MSFM walkthrough.)

You don’t hand-write this. You describe the app and Remy drafts the spec, which you review and tweak in plain language. When you want to change the app’s behavior, update the spec and recompile. Code shows what the app does; the spec captures why.

Layer 2: the backend contract (methods, tables, roles)

The backend contract is the core of the app: the methods and the data model.

Methods

A 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 (the full pattern is in one method, eight interfaces).

One file per method, one named export:

import { db, auth } from '@mindstudio-ai/agent';
import { Vendors } from './tables/vendors';

export async function submitVendorRequest(input: {
  name: string;
  contactEmail: string;
  taxId: string;
}) {
  auth.requireRole('requester');

  const vendor = await Vendors.push({
    name: input.name,
    contactEmail: input.contactEmail,
    taxId: input.taxId,
    status: 'pending',
    requestedBy: auth.userId,
  });

  return { vendorId: vendor.id, status: vendor.status };
}

Methods receive a single input object and return an object, both JSON-serializable. They run in isolated runtimes with npm packages available; no servers to manage. The @mindstudio-ai/agent SDK provides db and auth namespaces that just work, plus access to 200+ AI models and 1,000+ integrations.

Tables

Each table is a TypeScript file with a typed interface and a table definition:

import { db } from '@mindstudio-ai/agent';

interface Vendor {
  name: string;
  contactEmail: string;
  status: 'pending' | 'approved' | 'rejected';
  taxId: string;
  paymentTerms?: string;
}

export const Vendors = db.defineTable<Vendor>('vendors');

The platform provides a managed serverless SQL database with typed schemas: no connection strings, no migrations to run by hand. Push a schema change and the platform diffs it, applies it to a clone, and promotes atomically. Every table gets system columns automatically (id, created_at, updated_at, last_updated_by); you don’t define them, the platform adds and maintains them.

Roles

Roles define who can do what, and they’re declared in the manifest:

{
  "roles": [
    { "id": "requester", "name": "Requester", "description": "Can submit vendor requests and purchase orders." },
    { "id": "approver", "name": "Approver", "description": "Reviews and approves purchase orders." },
    { "id": "admin", "name": "Administrator", "description": "Full access to all app functions." },
    { "id": "ap", "name": "Accounts Payable", "description": "Processes invoices and payments." }
  ]
}

In your methods, call auth.requireRole('admin') and the platform handles sessions, tokens, and user resolution. The backend contract is what the platform builds and runs: real TypeScript, real SQL, real npm packages. You own the output.

Layer 3: eight ways to invoke the same methods

Interfaces are how users interact with your app, and the same backend methods power all of them. A web frontend, a Discord bot, and a cron job can all invoke the same logic.

InterfaceWhat it does
WebReact app served from the CDN
APIREST endpoints with API-key auth
DiscordSlash commands that invoke methods
TelegramBot commands and message handling
CronScheduled method execution
WebhookInbound HTTP → method invocation
EmailInbound email → method invocation
MCPAI tool server (methods exposed as tools)
A free 1-hour Hermes workshop
The free Hermes Agent crash courseReserve your spot

Your methods don’t know or care which interface invoked them. The same submitVendorRequest works whether it’s called from a React form, a Discord slash command, or a Stripe webhook. The interface can be as polished as you want and still can’t break business logic, because the backend is where anything real happens.

Beyond exposing methods to external MCP clients (Claude, Cursor, any MCP client), an app can also host its own conversational agent: an LLM with its own personality and system prompt that orchestrates the app’s methods as tools internally. Same methods, invoked by an LLM instead of a form.

The web interface, briefly

The web interface is a React app. The frontend SDK provides typed RPC to backend methods:

import { createClient } from '@mindstudio-ai/interface';

const api = createClient<{
  submitVendor(input: { name: string }): Promise<{ vendorId: string }>;
  listVendors(): Promise<{ vendors: Vendor[] }>;
}>();

const { vendorId } = await api.submitVendor({ name: 'Acme' });
const { vendors } = await api.listVendors();

The API interface exposes selected methods as REST endpoints for external consumers; the bots, cron, webhook, and email interfaces are each a declarative config mapping a trigger to a method. None of them duplicate logic. They all reach the same contract.

How the layers connect: two SDKs

The backend contract is enforced by two type-safe SDKs:

  • @mindstudio-ai/agent — used inside methods. Provides database access, auth, and platform capabilities.
  • @mindstudio-ai/interface — used in web interfaces. Typed RPC to backend methods.
import { createClient } from '@mindstudio-ai/interface';

const api = createClient<{
  approveVendor(input: { vendorId: string }): Promise<{ vendor: Vendor }>;
}>();

const { vendor } = await api.approveVendor({ vendorId: '...' });

The SDKs are the contract. Methods use @mindstudio-ai/agent to reach the database and auth; interfaces use @mindstudio-ai/interface to invoke methods. The platform handles the rest: sandboxed execution, database management, auth sessions, deployment.

How compilation works: from spec to live app

When you hit Publish, the platform compiles the spec into a live app:

  1. Read the manifest and spec for this version of the app.
  2. Generate the backend — bundle each method and resolve its dependencies.
  3. Build the interfaces — compile the web app and generate the configs for the API, bots, cron, webhooks, and email.
  4. Diff the data model — compare the spec’s tables against the live schema to compute the pending changes.
  5. Apply changes to a clone — schema changes run against a copy of the database, never the live one. If anything fails, the live app is untouched and the release is marked failed.
  6. Promote atomically — once the build is verified, the live app flips to the new release in a single step.

Each release keeps its own database snapshot, so rollback is always safe: the previous release’s data is still there. A failed build never affects what’s live.

Why the three-layer model matters

The three-layer model is what makes Remy a product agent rather than a code generator.

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 keeps the project maintainable over time.

Remy doesn't write the code. It manages the agents who do.

R
Remy
Product Manager Agent
Leading
Design
Engineer
QA
Deploy

Remy runs the project. The specialists do the work. You work with the PM, not the implementers.

The backend contract is portable. It’s real TypeScript, real SQL, real npm packages, and you own the output. Moving off the platform is a download and a re-point of your data-access layer, not a months-long extraction project.

Interfaces are projections. The same backend methods power all of them, so you can add a Discord bot, a cron job, or a webhook without touching the core logic, and they can’t drift, because they’re the same method underneath.

It’s a compiler, not magic. And it’s how you ship a full-stack app from a conversation.

FAQ

What is MSFM?

MSFM (MindStudio-Flavored Markdown) is the format for writing specs. It extends standard Markdown with block annotations (~~~...~~~) and inline annotations ([text]{content}) that attach precision to prose, so a spec with good annotations compiles the same way every time. See the MSFM walkthrough.

Can I write code directly without a spec?

Yes. The compiled code is real TypeScript and React, so you can write methods, tables, and interfaces directly. The spec is what makes the project maintainable over time and what lets you recompile the app when models improve, but it’s not mandatory.

What happens when I edit the compiled code?

The spec is the source of truth, so regenerating from it overwrites hand-edits in the compiled code. The right loop is: update the spec to capture the change, then recompile. If you’d rather own the code outright, stop regenerating from the spec and treat the compiled output as your codebase.

How does the database work?

Each app gets its own serverless SQL database. The platform handles durability, sync, and schema migrations automatically, with safe atomic rollbacks.

What’s the difference between a product agent and a coding agent?

They’re different categories for different jobs. Coding agents edit existing codebases; product agents compile specs into complete applications.

How do I deploy a Remy app?

You hit Publish, and the platform builds and deploys to a live URL automatically. Rollback restores the previous release: code, schema, and data together.

Best product agents

The three-layer model is the architecture; Remy is the agent built on it, and today it’s the most advanced product agent there is. Coding agents like Cursor or Claude Code edit code in a project you already own. Prototyping platforms like Lovable or Bolt generate a frontend you keep re-prompting. A product agent compiles a plain-language spec into a deployed full-stack app. You describe an app, Remy drafts the spec, compiles the backend contract, projects it onto the interfaces you asked for, and Publishes to a live URL.

Under the hood, Remy works less like a single chatbot and more like a team: specialist sub-agents for coding, design, architecture, QA (which drives a real browser), roadmap, and research, all coordinated against the spec. It runs on a production platform hardened by years of real enterprise traffic, so every app inherits 200+ models, 1,000+ integrations, managed databases, auth, and deployment with zero setup. The agent and SDKs are open source on GitHub, and Remy is $99/month ($79 with annual billing) after a 7-day free trial, plus pass-through inference at provider rates with no markup, around $100 to build a typical full-stack app.

The bottom line

Spec → backend contract → interfaces. Annotated prose becomes TypeScript methods and tables, which project onto eight ways to reach the same logic. That’s the whole architecture, and it’s why a description can become a deployed, maintainable, portable app.

Start building with Remy.

For the layers in depth: what is spec-driven development?, the MSFM walkthrough, and one method, eight interfaces.

Presented by MindStudio

No spam. Unsubscribe anytime.