flisk-build
Turn a plain request such as "build me a small online shop", "a SaaS with login and billing", "an AI agent with MCP tools and a database" or "a blog with an admin API" into Flisk steps (`flisk project
SKILL.md.claude/skills/flisk-build/SKILL.md
GitHubBuild an app with Flisk
The user describes an app. Map each part of it to a Flisk resource, let Flisk write the containers, routing and database wiring, write only the app code, and finish with the working URLs.
First: does this app need Docker?
Pick the path before anything else.
- No Docker (prefer it for a simple app): every part can be started with one command and none needs a database, one gateway URL, or the container it deploys. Examples: an API and a website, a static site and a webhook receiver, an agent that calls an external model API. Follow "Simple app without Docker" below and skip the Workflow.
- Docker + Tilt: the app stores data in Postgres, needs Redis or another image, or the user asks for the same container they deploy. Follow the Workflow.
A database or cache can run in Docker next to command services: give it an image (no command, no dockerfile) and flisk up starts it with docker run (a mixed run, docs/run-without-docker.md). Any other mix, such as a service built from a Dockerfile next to a command service, is refused with MIXED_RUNTIME.
Simple app without Docker
- Write each part as a folder with its own code and a
service.jsonthat names the command that starts it:{ "schemaVersion": 1, "appName": "api", "appType": "backend", "command": "node server.js", "port": 4000, "healthCheckPath": "/health" }. The command runs from that folder withPORTset. Add"dependsOn": ["api"]to a part that calls another, and pass URLs through"env": { "API_URL": "http://localhost:4000" }. Use the runtime's own watch mode for reload (node --watch server.js,uvicorn main:app --reload --port $PORT). - Run
flisk doctor. It checks only that each command's program is installed and the ports anddependsOnare valid. - Run
flisk up --jsonin the background (&) and wait for its one JSON line:"ok":true,"runtime":"native"andurlswith each service'shttp://localhost:<port>. Noflisk projectorflisk resourcestep is needed; the firstflisk upwrites.flisk/project.json. - Request every URL (
curl -fsS <url>); each must answer. On a failure readflisk logs --service <name> --tail 100, fix the code, and runflisk up --jsonagain (it restarts a crashed service on its own). - Tell the user what was built, one line per part with its URL, and that
flisk downstops it. Guide: docs/run-without-docker.md.
Workflow
- Check the machine. Run
flisk doctor. If it reports an error, fix what it names (or tell the user what to start, for example Docker) and run it again. Do not continue past an unresolved error. - Plan the parts. Split the request into resources and pick one stack name for all of them (short, kebab-case, from the app:
shop,saas,ai,blog). Use the table below. Tell the user the plan in one or two lines. - Create the project in an empty folder:
flisk project --yes. If the request matches a starter app (restaurant, SaaS, store, agent stack, user management), clone that instead: see the flisk-recipe-starters skill. In a folder that already has.flisk/project.json, skip this step. - Add each part with
flisk resource <name> --type <type> --stack <stack> --yes. Add--feature drizzle(or--feature prisma) to a backend that stores data. Add--framework <id>or--language <id>only when the user names one. - Write the app code inside each resource's
src/. Keep the generated/healthroute. Do not write Dockerfiles, Compose files, Tiltfiles or proxy config, and do not edit.autogenerated/: changeservice.jsoninstead and Flisk regenerates. - Preview, then start:
flisk up <stack> --dry-runshows the services and URLs. Then runflisk up <stack> --jsonin the background (&) and wait for its one JSON line:"ok":truemeans the stack is ready. A cold first build can take a few minutes. - Check every URL. Get them with
flisk networks --stack <stack> --raw(or--json) and request each health URL (curl -fsS <url>). Every one must answer 200. For a backend with a database, also request<base>/health/db. - When something fails, run
flisk doctor, thenflisk logs -s <resource> --tail 100for the failing resource. Fix the source (app code orservice.json), and the running stack reloads. If a build failed, runflisk up <stack> --jsonagain. Follow the flisk-troubleshoot skill for messages you do not recognise. Stop after three failed attempts at the same error and tell the user what you saw. If Docker saysall predefined address pools have been fully subnetted, old projects still hold their networks: runflisk doctor --fixhere andflisk down --prune-networksin projects the user no longer runs (ask first), then start again. - Tell the user, in plain words: what was built, one line per part with its URL, how to try it (an example
curlor "open this in your browser"), and thatflisk downstops everything.
From request to resources
| The user asks for | Resource | Command |
|---|---|---|
| A website, storefront, dashboard, admin page | frontend |
flisk resource web --type frontend --stack <stack> --yes |
| An API (orders, posts, users, billing) | backend |
flisk resource orders-api --type backend --stack <stack> --yes |
| Something that stores data, "a database" | backend with a database feature |
flisk resource notes-api --type backend --stack <stack> --feature drizzle --yes |
| Background jobs, emails, imports | worker |
flisk resource jobs --type worker --stack <stack> --yes |
| An AI agent, chatbot, assistant | agent |
flisk resource assistant --type agent --stack <stack> --yes |
| Tools for an agent, an MCP server | mcp |
flisk resource tools-mcp --type mcp --stack <stack> --yes |
| An admin panel or back office next to the main site | a second frontend |
flisk resource admin --type frontend --stack <stack> --yes |
| Several APIs ("3 APIs") | one backend each |
flisk resource catalog-api ..., flisk resource orders-api ... (keep it to three or fewer) |
| A cache, Redis | bring-your-own |
flisk resource cache --type bring-your-own --image redis:7 --no-proxy --stack <stack> --yes |
| Chat, live updates, websockets | backend |
an ordinary backend; write the websocket route in its code |
| An existing image (Mailpit, a vendor's server) | bring-your-own |
flisk resource mail --type bring-your-own --image <image> --stack <stack> --yes |
| A third-party API (payments, a shop platform) | backend that holds the key |
list the key's name under secrets.required in its service.json, put the value in the project .env, and call the vendor only from that backend |
| Python or Go | backend with a language |
flisk resource api --type backend --language python --stack <stack> --yes (or go) |
| A frontend framework by name (Vue, Svelte, Solid...) | frontend with a framework |
flisk resource web --type frontend --framework vue --stack <stack> --yes (list them: flisk resource --type frontend --frameworks) |
Web3 apps (a local chain node and contracts) are not covered: no Flisk recipe has run a chain node end to end. Say so instead of improvising one.
Every stack gets the shared Postgres database: you do not add one. A backend created with --feature prisma gets a DATABASE_URL, a Prisma schema, and a <name>-migrator resource that applies migrations before the API starts. A backend created with --feature drizzle gets a DATABASE_URL, a Drizzle client in src/db.ts and a /health/db check, but no migrator.
Name APIs <thing>-api. Flisk drops the -api suffix in the route, so orders-api is served at /api/orders. Backends are served on api.<project>.localhost and frontends on app.<project>.localhost, where <project> is the project name (by default the folder name) and the port is the one flisk up picked. Read the real URLs from flisk networks; do not build them by hand.
Tables
The Flisk convention is a separate migrator that creates and changes tables before the APIs start. --feature prisma scaffolds one for you (<name>-migrator); for other tools see one-shot jobs. For a quick prototype, creating tables with CREATE TABLE IF NOT EXISTS when the API starts also works; say which one you used.
Recipes
Ready-made plans for common requests: flisk-recipe-starters (clone a working starter app), flisk-recipe-shop, flisk-recipe-saas, flisk-recipe-ai-agent and flisk-recipe-blog. More prompts by category (spreadsheets, recruiting, product management, internal tools) are in docs/recipes/build-with-your-agent.md.
Guardrails
- Use only the flags in
flisk <command> --help. Do not guess flags. - Report a URL as working only after it answered 200. If one never did, say so and say what the logs showed.
- Ask before running
flisk up -f: it stops a Tilt process that is already running. - Ask before adding services the user did not ask for. One frontend and one API is enough for "a small" app.
- Flisk runs the app on this machine. It does not deploy it.