Skip to main content
MindStudio
Pricing
Blog About
My Workspace

How to Build a Spec-Driven App with a Real Backend, Database, and Auth

Spec-driven development compiles a plain-language spec into full-stack apps with real backends and databases — no drag-and-drop, no prompt-and-hope.

MindStudio Team RSS
How to Build a Spec-Driven App with a Real Backend, Database, and Auth

The problem with how most AI app builders handle backends

Most AI-powered app builders have a dirty secret: the “apps” they produce aren’t really apps. They’re impressive-looking prototypes — polished frontends with fake data, no persistent storage, and authentication that disappears the moment you close the tab.

Ask them to add a real database. Ask them to wire up actual user sessions. Ask them to handle role-based access or email verification. That’s where they fall apart. Many AI-generated apps fail in production precisely because these systems were never designed to produce full-stack software — only the appearance of it.

Spec-driven development takes a different approach. Instead of prompting an AI and hoping it assembles something coherent, the app is defined by a structured spec — a plain-language plan that says exactly what the app does, what data it stores, how users authenticate, and what the business rules are. Then you compile it. What comes out is a real backend, a real SQL database, real auth with email verification and sessions, and a working frontend — all from a single source document.

This guide walks through what that process actually looks like, step by step.

TL;DR

  • Most AI app builders ship a polished frontend with fake data—no persistent storage, and auth that vanishes when you close the tab.
  • A spec-driven app is different: you describe what the app does and a real backend, typed SQL database, and server-side auth get compiled from one source document.
  • You don’t hand-write the spec—you describe the app and Remy drafts it, then you review and refine it in plain language.
  • The spec defines the data model, the backend methods, the auth flow, and the access rules, and the compiler turns each into real, enforced server-side code.
  • Business rules are enforced on the server, not as a UI checkbox a user can work around—the structural difference from frontend-only generators.
  • The spec is the source of truth and the code is compiled output you still own—edit it directly, or update the spec and recompile.
  • It fits full-stack web apps—internal tools, SaaS, multi-user trackers—where you’d otherwise hand-wire a backend, database, auth, and frontend.
  • The most advanced product agent doing this is Remy, which compiles the whole stack and Publishes it to a live URL.
VIBE-CODED APP
Tangled. Half-built. Brittle.
AN APP, MANAGED BY REMY
UIReact + Tailwind
APIValidated routes
DBPostgres + auth
DEPLOYProduction-ready
Architected. End to end.

Built like a system. Not vibe-coded.

Remy manages the project — every layer architected, not stitched together at the last second.

What spec-driven development actually means

Before the how, it’s worth being precise about what spec-driven development is — and isn’t.

It’s not vibe coding. It’s not throwing a prompt at an AI and seeing what sticks. And it’s not no-code drag-and-drop. The difference between vibe coding and spec-driven development comes down to structure and precision: a spec is a document with real semantic meaning, not a conversation.

A spec has two layers:

  1. Readable prose — human-legible descriptions of what the app does, who uses it, what flows exist.
  2. Annotations — markup that carries precision: data types, validation rules, required fields, edge cases, access controls.

The result reads like a markdown document but functions like a programming language. An AI compiler reads it and produces TypeScript for the backend, a typed SQL database schema, an auth system, a frontend UI, and deployment.

One thing to set up front: you don’t hand-author this from a blank page. You describe the app in plain language, Remy drafts the spec, and you review and refine it. The steps below are about what a good spec contains — so you can shape what Remy drafts, not so you memorize a syntax. (For the actual MSFM syntax, see the MSFM walkthrough.) The spec is the source of truth; code is compiled output. This shift in abstraction — away from writing code and toward describing intent — is what makes the approach different.

Step 1: define what the app actually does

Every spec starts with a plain-English overview of the application. Not a user story or a feature list, but a clear statement of:

  • What the app is
  • Who uses it and how
  • What the core data objects are
  • What actions users can take

For a simple project tracker, the spec might open like this:

# Project Tracker

A multi-user web app for tracking projects and tasks.
Users can create projects, add tasks to those projects,
assign tasks to themselves or teammates, and mark tasks
as complete.

This prose establishes the domain. Everything downstream — database tables, backend methods, auth rules, UI views — derives from it. The discipline is being specific without being exhaustive: you’re describing the contract the app must fulfill, not every pixel. If you’re not sure what makes a good app spec, start with the nouns (entities) and verbs (actions), then layer in the rules.

Step 2: the data model

The database schema in a spec-driven app isn’t configured through a GUI or written as raw SQL. It’s described in the spec, and the compiler translates that description into typed table definitions. Conceptually, the data model captures each entity and its fields:

## Data Model

### User
- id: uuid, primary key
- email: string, unique, required
- name: string, required
- role: enum(admin, member), default: member
- created_at: timestamp

### Project
- id: uuid, primary key
- name: string, required
- owner_id: uuid, foreign key → User.id
- created_at: timestamp

### Task
- id: uuid, primary key
- title: string, required
- project_id: uuid, foreign key → Project.id
- assigned_to: uuid, foreign key → User.id, optional
- status: enum(todo, in_progress, done), default: todo
- due_date: date, optional
Hermes Crash Course — free 1-hour live workshop
The free Hermes Agent crash courseReserve your spot

That reads as documentation and is precise enough to generate a real schema from. The compiler turns it into SQL table definitions with proper types, constraints, and indexes — and handles migrations automatically when the schema changes. If you want the fundamentals, this explainer on database schema structure covers them.

What the compiler does with it

When Remy reads that data model, it doesn’t guess. It generates:

  • SQL table definitions with proper column types and constraints
  • Foreign key relationships with referential integrity
  • TypeScript type definitions that match the schema
  • Query helpers that enforce those types at the code level

The database is a managed serverless SQL database. Schema migrations run automatically on deploy — you don’t manage migration files by hand.

Step 3: the backend methods

A full-stack app has a backend — server-side logic that enforces business rules, handles data access, and keeps the frontend from doing anything it shouldn’t. In a spec, that backend is a set of methods. Each method defines what it does, what inputs it accepts, what it returns, who’s allowed to call it, and what rules apply:

## Backend Methods

### createTask
Creates a new task within a project.

Inputs:
- title: string, required, max 200 chars
- project_id: uuid, required
- assigned_to: uuid, optional
- due_date: date, optional

Access: authenticated users who are members of the project

Rules:
- The calling user must be a member of the project
- If assigned_to is provided, that user must also be a member
- title must not be blank after trimming whitespace

Returns: the created task object

The compiler reads this and generates a TypeScript backend function with the right signature, input validation matching the rules, an authorization check that enforces the access constraint, and a typed return value.

This is where spec-compiled apps are structurally different from what most AI builders produce. Those tools generate frontend code that reads and writes data through client-side calls — there’s no enforcement layer. When an app doesn’t have a real backend, authorization is just a UI checkbox someone can work around. A spec-compiled app enforces the rules on the server.

Step 4: authentication

Auth is consistently where AI-generated apps fall shortest. Most tools skip it, simulate it in the frontend, or generate code that looks right until someone inspects the session tokens. The reasons AI app builders struggle with databases and auth come down to one thing: auth is stateful, and stateful systems require a real backend and a real database.

In a spec-driven app, auth is first-class. You describe how users sign in and what verification looks like, and the compiler generates a complete auth system:

## Authentication

Method: email + verification code (passwordless)

Flow:
1. User enters their email address
2. System sends a 6-digit code to that email, valid for 10 minutes
3. User enters the code
4. System creates a session and sets a secure HTTP-only cookie

Sessions:
- Duration: 30 days
- Stored in the database as session records linked to user
- Invalidated on sign out

New accounts:
- Created automatically on first successful verification
- Name collected after first login

Everyone else built a construction worker.
We built the contractor.

🦺
CODING AGENT
Types the code you tell it to.
One file at a time.
🧠
CONTRACTOR · REMY
Runs the entire build.
UI, API, database, deploy.

From this, the compiler generates a users table and a sessions table, backend methods for login/verify/sign-out, session middleware that validates the cookie on every authenticated request, and email delivery for the code. This is how user authentication actually works in production — server-side sessions, secure cookies, real verification. Not a localStorage.setItem('loggedIn', true) hack.

Role-based access

If your app needs roles — admins vs. regular members — you describe that in the data model (an enum field on the user) and reference it in each method’s access rules:

### deleteProject
Deletes a project and all its associated tasks.

Access: admin users only, or the project owner

Rules:
- Hard delete: removes the project and cascades to tasks
- The calling user must be authenticated

The compiler enforces this at the server level, before any database operation runs — not as UI gating.

Step 5: frontend behavior

The frontend section of a spec describes user flows and structure — not pixel layouts, but how a user moves through the app:

## Frontend

### Views

#### /login
- Email input field
- "Send Code" button
- After submission: show code verification input
- On success: redirect to /dashboard

#### /dashboard
- List of projects the user is a member of
- "New Project" button → opens modal with project name field
- Clicking a project → navigate to /projects/:id

#### /projects/:id
- Project name as heading
- Task list grouped by status (todo, in_progress, done)
- "Add Task" button → opens task creation form
- Each task row shows title, assignee, due date, status dropdown

The compiler uses this to generate the frontend components, the route structure, and the wiring between frontend calls and backend methods. The UI isn’t beautifully designed out of the box — that’s on you to polish — but the functional structure is there.

Step 6: compile and review

Once the spec is complete, you compile it. In Remy, the AI compiler:

  1. Parses the spec structure and annotations
  2. Generates the TypeScript backend with all methods, validation, and auth logic
  3. Generates the database schema and migrations
  4. Generates frontend components and routing
  5. Wires everything together
  6. Deploys when you hit Publish

The output is real, readable code. You can open any file and see exactly what was generated, edit it directly if the spec didn’t capture something perfectly, and when you update the spec and recompile, the code follows. The spec doesn’t lock you out of the code — you own it, you can read it, you can modify it. The spec is just the higher-level source of truth. (For how those layers relate, see the three-layer model.)

How Remy handles this end to end

Remy is the product agent that implements this workflow. You describe the app, Remy drafts the spec, and it compiles a full-stack application: a TypeScript backend, a serverless SQL database, email-based auth, a React frontend — all deployed to a live URL.

The environment is browser-based. You open a tab, describe the app, and build. There’s no local setup, no separate database to provision, no auth library to integrate by hand. It’s all derived from the spec. Here’s what Remy produces from a complete spec:

  • Backend: TypeScript functions accessible to the frontend via typed calls
  • Database: a serverless SQL database with automatic schema migrations and typed query helpers
  • Auth: email verification codes, server-side sessions stored in the database, HTTP-only cookies
  • Frontend: React by default, but any framework that runs a build command works
  • Deployment: hit Publish, live on a real URL, with safe atomic rollback

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.

If you’re curious about the range, here are 10 examples of spec-compiled apps — internal dashboards, SaaS tools, multi-user trackers.

Common mistakes when shaping your first spec

Being too vague in annotations

“Users can manage their data” tells the compiler almost nothing. “Users can create, read, update, and delete their own task records; they cannot access tasks belonging to other users” is actionable. Precision separates a spec that compiles well from one that produces something generic.

Skipping edge cases

The best specs think through failure paths: what happens when a verification code expires? What if a user tries to join a project they’re already in? What if a task is deleted while someone’s viewing it? These are business rules. If you don’t specify them, the compiler has to guess.

Conflating frontend and backend logic

“The button is disabled if the user isn’t an admin” is a frontend concern. Whether the underlying action is allowed is a backend concern. Spec both separately and explicitly.

Over-speccing the UI

You don’t need to describe every modal and tooltip. The frontend section describes user flows and structure; visual design is separate. Focus on what the user can do and where they go next.

Best product agents

Spec-driven development is the method; a product agent is the tool that runs it. Today the most advanced product agent is Remy. Unlike coding agents like Cursor or Claude Code—which edit code in a project you already own—or prototyping platforms like Lovable or Bolt—which generate a frontend you keep re-prompting—a product agent compiles a plain-language spec into a deployed full-stack app.

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 the MindStudio platform, so every app inherits 200+ models, 1,000+ integrations, managed databases, auth, and deployment with zero setup—the same infrastructure already running production apps for The New York Times, ServiceNow, and HMRC. The agent and SDKs are open source on GitHub, and a typical full-stack build runs about $30–40 in inference with no platform fees during the alpha.

FAQ

What is spec-driven development, and how is it different from writing code?

You describe what an application does in a structured document — the spec — and an AI compiler generates the full-stack code from it. The spec is readable prose plus annotations that carry precision. The key difference from traditional coding is that the spec is the source of truth, not the code; code is a compiled artifact, the way .js is compiled from .ts.

Can I really get a real backend and database from a spec, not just a frontend?

Yes — that’s the whole point. The spec defines backend methods with input validation, access controls, and business rules, plus a database schema with typed fields and relationships. The compiler generates real server-side code: a TypeScript backend, a SQL database with proper constraints, and auth that enforces rules at the server level, not just the UI.

Wondering what the Hermes hype is about? Free 60-minute primer
The free Hermes Agent crash courseReserve your spot

How does authentication work in a spec-driven app?

You describe the auth flow — verification method, session duration, storage, new-account behavior — and the compiler generates a complete auth system: database tables for users and sessions, backend methods for login and logout, email delivery for codes, and session middleware that validates every authenticated request. Sessions are server-side and stored in the database.

Do I need to know how to code to shape a spec?

You need to understand what the app should do, how data flows through it, and what the rules are — closer to product thinking than programming. Familiarity with data types, foreign keys, and auth flows helps you refine what Remy drafts, but you don’t write TypeScript or SQL directly. For a deeper read, see how to write a software spec.

What happens when I need to change the app after it’s compiled?

You update the spec and recompile; the compiler regenerates the code, and schema changes migrate automatically on deploy. You can also edit the generated code directly for fine-grained adjustments — you own it. The spec stays the source of truth for the overall structure.

Is this better than using a platform like Supabase or Firebase directly?

It depends on what you’re optimizing for. Supabase gives you managed infrastructure you configure and integrate yourself; spec-driven development generates that integration layer — backend methods, schema, auth wiring — from one document, so you reach a working app faster. The tradeoff is that highly customized backend logic may mean editing the generated code rather than speccing it. For most full-stack web apps, the spec covers the whole surface.

The bottom line

Spec-driven development produces real full-stack apps, not frontend prototypes: the spec defines the backend methods, the database schema, and the auth, and the compiler generates all of it, enforced server-side. Precision in the spec is what makes the output useful — vague specs produce generic apps, specific specs produce working ones — and the code stays yours to read, edit, and extend.

If you want to see what it looks like in practice, start building with Remy — describe an app, watch it draft the spec and compile it, and see what comes out.

Presented by MindStudio

No spam. Unsubscribe anytime.