Browse docs All docs
Docs / Launch a starter app and remix it live
Guidedeploymill://guides/starter-apps

Launch a starter app and remix it live

This is the fastest path from nothing to a working, deployed app, and the template for the "watch your agent build it" demo. You pick a curated starter, scaffold it in one call (its database is provisioned for you), then remix it live by editing the app and redeploying. When you're ready for a real app, the same loop grows it: add a secret the agent never sees, lock an admin route, attach a custom domain.

Audience: agents. These are tool calls in order, with what "done" looks like at each step. Everything here is drivable over POST /mcp. No dashboard required.

The curated starters

Four DB-backed starters exist specifically to be launched-and-remixed. Each is a real, useful app that runs inside the Explore (free) floor:

StackWhat it isGood for showing
kanbanTrello-style board (columns, cards, labels)the best live-edit demo
todoTo-do / task list (lists, due dates)the safest, fastest first deploy
link-in-bioLinktree-style public links pagesharing a *.deploymill.app link
event-rsvpEvent page + public RSVP + guest lista shareable, time-bound page

All four are Hono + Postgres. They declare a managed database in their manifest, so start_project provisions Postgres and injects DATABASE_URL before the first build. The app comes up working in a single call, with no follow-up reconcile_project.

Discover them at runtime. Don't hardcode the list:

list_templates()
// → includes { key: "kanban", … }, { key: "todo", … },
//   { key: "link-in-bio", … }, { key: "event-rsvp", … }

Step 1: Launch it

start_project({ name: "my-board", stack: "kanban" })
// Creates the repo, scaffolds the app, PROVISIONS managed Postgres + injects
// DATABASE_URL, deploys main, and attaches the prod domain — one call.
// → { ok: true, url: "https://my-board.deploymill.app", … }

Done when: list_deployments shows the latest deploy done and the url serves the seeded app (the board has its three columns and example cards). The build is the slow part (~1–3 min); if your client times out, the deploy keeps running server-side. Poll list_deployments or re-run start_project with the same name (it's idempotent).

The committed .deploymill/project.json already records the database, so the first reconcile_project is a no-op. Nothing else to wire.

Step 2: Remix it live

This is the loop the demo shows off: change the app, redeploy, watch it update.

  1. Read the contract first. The scaffold ships an AGENTS.md documenting the

    entrypoint, the schema, and the "make it yours" knobs. Read it before moving files. The Dockerfile, not convention, decides what ships.

  2. Edit the source. Use get_file / push_files to change src/index.js

    (the entrypoint: UI, schema, routes). To add a field, add an ALTER TABLE … ADD COLUMN IF NOT EXISTS … in the boot schema, add the input to the form, and render it.

  3. Redeploy. deploy({ applicationId }) builds the new source and

    health-gates it; a failed /healthz auto-rolls-back, so a broken edit can't take the app down.

  4. Verify. get_app (its health block) / load the url.

Repurpose freely: the kanban board becomes a CRM pipeline or content calendar by renaming columns; the todo list grows tags and priorities; link-in-bio gets new themes; event-rsvp gets a capacity cap. Each is a small, local edit. See the starter's AGENTS.md for the specific knobs.

The Explore (free) floor: design inside the box

The curated starters are built to run free, and a remix should stay inside the same envelope:

  • State lives only in managed Postgres. No volumes, no object storage, **no

    file/image uploads**. Images are pasted URLs stored as strings. The schema init + seed run on boot; there's no migration tooling.

  • No outbound calls / no third-party API keys. No email, Stripe, OpenAI, or

    webhooks on the free tier (egress is locked). A browser-side redirect is fine.

  • Subdomain only (*.deploymill.app). For link-in-bio and event-rsvp

    the shareable subdomain link is the point.

  • Keep /healthz fast and returning 200. Make it tolerate a not-yet-ready DB

    on first boot so a warming database never trips a false rollback.

If a remix needs something outside this box, it's a paid-tier capability. Make it an explicit upgrade prompt, not a half-built feature. Every gate returns a coded upgrade_required with an upgradeUrl.

Step 3: Grow it into a real app (Builder)

When a card is on file (the $10/mo Builder base), the whole envelope lifts at once: custom domains, the REST API, object storage, open egress, editable build recipe, arbitrary import. That's what turns a starter into a production app. The worked example is a waitlist that emails its signups:

  1. Start from a starter or a fresh app, give it a subscribers table, and a

    public form that inserts an email. (On the free event-rsvp starter you already have the collect-and-list half.)

  2. Add the email provider's API key (the agent never sees it). Use the

    secret hand-off: request_secret returns a one-time entry link the human opens to paste the key; bind_secret injects it into the app's env as, say, RESEND_API_KEY. The value never reaches the agent or any tool response. (See deploymill://guides/secrets.) This needs open egress (Builder).

  3. Write the send code against the injected env var, and deploy.
  4. Lock the admin page. Put the "view all signups + mass-email them" view on

    a route and protect it: set_app_protection gates it behind a password (see deploymill://guides/site-protection). The public form stays open; the admin route doesn't.

  5. (Optional) Schedule a digest. Declare a schedules entry and handle the

    tick in POST /_system/tick to send on a cadence (see deploymill://guides/schedules).

The two memorable beats, the agent wired up a credential it can't read and locked a production route, are the guardrails that make it safe to hand an agent prod. That's the demo worth walking a new user through.

Recovery & idempotency

  • start_project is idempotent on name: re-running reuses the repo/app and

    won't double-provision the database (a managed-DB record short-circuits it).

  • If a step fails it returns { ok: false, failedAt, partial }. Fix the cause

    (usually the Dockerfile/build, read get_logs) and re-run, or call the failed primitive directly.

  • Tear down with delete_app when the demo's done. Make teardown part of the

    script so it cleans up after itself.

  • deploymill://guides/project-config: the .deploymill/project.json contract

    (the database block, health, domains).

  • deploymill://guides/database/node: the Postgres client pattern (pooling,

    the /db health probe) if you go deeper than the starter's wiring.

  • deploymill://guides/secrets · deploymill://guides/site-protection ·

    deploymill://guides/schedules: the Step-3 guardrails.