/build-app
Use when building a new Butterbase app from scratch, creating a full-stack application, or when the user asks to set up a complete backend with database, auth, and deployment
$ npx -y skills add butterbase-ai/butterbase-skills --skill build-app --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/build-app
Context preview
The summary Claude sees to decide when to auto-load this skill.
Use when building a new Butterbase app from scratch, creating a full-stack application, or when the user asks to set up a complete backend with database, auth, and deployment
SKILL.md
build-app.SKILL.mdname: build-app
description: Use when building a new Butterbase app from scratch, creating a full-stack application, or when the user asks to set up a complete backend with database, auth, and deployment
> **Prefer `/butterbase-skills:journey`** — for a fully guided multi-stage build with preflight, planning, deployment verification, and (optionally) hackathon submission. This one-shot skill remains for users who want the legacy linear setup.
Build a Complete Butterbase App
This skill walks through all seven phases of building a production-ready Butterbase application — from provisioning a backend to deploying a live frontend. Follow each phase in order; later phases depend on artifacts (app_id, schema, RLS policies) produced by earlier ones.
> **Convention:** every JSON body below is the argument object for the tool named in its **Tool:** header. When the header reads `manage_schema` with `action: "apply"`, include `"action": "apply"` alongside the other fields when you make the call.
---
Phase 1: Create the App
Use `init_app` to provision an isolated backend with its own database and auto-generated REST API.
**Tool:** `init_app`
{
"name": "my-blog"
}**Returns:**
{
"app_id": "app_abc123",
"api_base": "https://api.butterbase.ai/v1/app_abc123"
}**Important:** Save `app_id` and `api_base` — every subsequent tool call requires `app_id`.
Optional: Generate a Service API Key
If the user needs programmatic access (CI/CD pipelines, server-to-server calls, admin scripts), generate a service key now.
**Tool:** `manage_auth_config` with `action: "generate_service_key"`
{
"name": "Production Deploy Key"
}> ⚠️ The full key (`bb_sk_...`) is shown **only once**. Store it securely — it cannot be retrieved again.
---
Phase 2: Design & Apply Schema
Work with the user to understand their data model before writing any SQL. Ask:
- What are the primary entities (users, posts, products, orders)?
- Which tables are user-owned vs. shared/public?
- What relationships exist between tables (foreign keys)?
- Are there any boolean flags for public visibility (e.g. `published`, `is_public`)?
Preview First with dry_run_schema
Always preview schema changes before applying them.
**Tool:** `manage_schema` with `action: "dry_run"`
{
"app_id": "app_abc123",
"schema": {
"tables": {
"posts": {
"columns": {
"id": { "type": "uuid", "primaryKey": true, "default": "gen_random_uuid()" },
"author_id": { "type": "uuid", "nullable": false },
"title": { "type": "text", "nullable": false }
}
}
}
}
}Review the generated SQL — make sure it matches intent before applying.
Apply the Schema
**Tool:** `manage_schema` with `action: "apply"`
Below is a complete example for a **blog app** with posts and comments:
{
"app_id": "app_abc123",
"schema": {
"tables": {
"posts": {
"columns": {
"id": { "type": "uuid", "primaryKey": true, "default": "gen_random_uuid()" },
"author_id": { "type": "uuid", "nullable": false },
"title": { "type": "text", "nullable": false },
"body": { "type": "text" },
"published": { "type": "boolean", "default": "false" },
"created_at": { "type": "timestamptz", "default": "now()" }
}
},
"comments": {
"columns": {
"id": { "type": "uuid", "primaryKey": true, "default": "gen_random_uuid()" },
"post_id": { "type": "uuid", "nullable": false, "references": "posts.id" },
"author_id": { "type": "uuid", "nullable": false },
"body": { "type": "text", "nullable": false },
"created_at": { "type": "timestamptz", "default": "now()" }
}
}
}
}
}Verify the Schema Was Applied
**Tool:** `manage_schema` with `action: "get"`
{
"app_id": "app_abc123"
}Confirm every table and column is present before moving to Phase 3.
Schema Tips
- Always include `id` as UUID with `gen_random_uuid()` default
- Always include `created_at` with `now()` default
- Use `author_id` / `user_id` UUID columns on user-owned tables — RLS will reference these
- Use `references: "table.column"` for foreign keys (cascades must be set carefully)
- `manage_schema` action `apply` is idempotent — safe to call again if schema is unchanged
---
Phase 3: Secure Data with RLS
Row-Level Security (RLS) ensures users can only access their own data. This phase is **not optional** for any table that holds user-generated content.
Enable User Isolation
Call `create_user_isolation_policy` for each user-owned table. This single call: 1. Enables RLS on the table 2. Creates a policy so users only see their own rows 3. Installs a BEFORE INSERT trigger to auto-populate the user column 4. Creates a service bypass policy for admin access
**Tool:** `manage_rls` with `action: "create_user_isolation"`
{
"app_id": "app_abc123",
"table_name": "posts",
"user_column": "author_id"
}Allow Public Reads (Optional)
For tables where some rows should be publicly visible (e.g. published blog posts), add `public_read_column`. This creates extra SELECT policies for both authenticated and anonymous users.
{
"app_id": "app_abc123",
"table_name": "posts",
"user_column": "author_id",
"public_read_column": "published"
}Repeat for every user-owned table. For the blog example:
{
"app_id": "app_abc123",
"table_name": "comments",
"user_column": "author_id"
}Test RLS Isolation
After applying policies, verify they work correctly by simulating user requests.
**Test SELECT as a specific user** — should only see that user's rows:
**Tool:** `select_rows`
{
"app_id": "app_abc123",
"table": "posts",
"as_role": "user",
"as_user": "11111111-1111-1111-1111-111111111111"
}**Test SELECT as anonymous** — should only see publ
Read more
name: build-app description: Use when building a new Butterbase app from scratch, creating a full-stack application, or when the user asks to set up a complete backend with database, auth, and deployment
> **Prefer `/butterbase-skills:journey`** — for a fully guided multi-stage build with preflight, planning, deployment verification, and (optionally) hackathon submission. This one-shot skill remains for users who want the legacy linear setup.
Build a Complete Butterbase App
This skill walks through all seven phases of building a production-ready Butterbase application — from provisioning a backend to deploying a live frontend. Follow each phase in order; later phases depend on artifacts (app_id, schema, RLS policies) produced by earlier ones.
> **Convention:** every JSON body below is the argument object for the tool named in its **Tool:** header. When the header reads `manage_schema` with `action: "apply"`, include `"action": "apply"` alongside the other fields when you make the call.
---
Phase 1: Create the App
Use `init_app` to provision an isolated backend with its own database and auto-generated REST API.
**Tool:** `init_app`
{
"name": "my-blog"
}**Returns:**
{
"app_id": "app_abc123",
"api_base": "https://api.butterbase.ai/v1/app_abc123"
}**Important:** Save `app_id` and `api_base` — every subsequent tool call requires `app_id`.
Optional: Generate a Service API Key
If the user needs programmatic access (CI/CD pipelines, server-to-server calls, admin scripts), generate a service key now.
**Tool:** `manage_auth_config` with `action: "generate_service_key"`
{
"name": "Production Deploy Key"
}> ⚠️ The full key (`bb_sk_...`) is shown **only once**. Store it securely — it cannot be retrieved again.
---
Phase 2: Design & Apply Schema
Work with the user to understand their data model before writing any SQL. Ask:
- What are the primary entities (users, posts, products, orders)?
- Which tables are user-owned vs. shared/public?
- What relationships exist between tables (foreign keys)?
- Are there any boolean flags for public visibility (e.g. `published`, `is_public`)?
Preview First with dry_run_schema
Always preview schema changes before applying them.
**Tool:** `manage_schema` with `action: "dry_run"`
{
"app_id": "app_abc123",
"schema": {
"tables": {
"posts": {
"columns": {
"id": { "type": "uuid", "primaryKey": true, "default": "gen_random_uuid()" },
"author_id": { "type": "uuid", "nullable": false },
"title": { "type": "text", "nullable": false }
}
}
}
}
}Review the generated SQL — make sure it matches intent before applying.
Apply the Schema
**Tool:** `manage_schema` with `action: "apply"`
Below is a complete example for a **blog app** with posts and comments:
{
"app_id": "app_abc123",
"schema": {
"tables": {
"posts": {
"columns": {
"id": { "type": "uuid", "primaryKey": true, "default": "gen_random_uuid()" },
"author_id": { "type": "uuid", "nullable": false },
"title": { "type": "text", "nullable": false },
"body": { "type": "text" },
"published": { "type": "boolean", "default": "false" },
"created_at": { "type": "timestamptz", "default": "now()" }
}
},
"comments": {
"columns": {
"id": { "type": "uuid", "primaryKey": true, "default": "gen_random_uuid()" },
"post_id": { "type": "uuid", "nullable": false, "references": "posts.id" },
"author_id": { "type": "uuid", "nullable": false },
"body": { "type": "text", "nullable": false },
"created_at": { "type": "timestamptz", "default": "now()" }
}
}
}
}
}Verify the Schema Was Applied
**Tool:** `manage_schema` with `action: "get"`
{
"app_id": "app_abc123"
}Confirm every table and column is present before moving to Phase 3.
Schema Tips
- Always include `id` as UUID with `gen_random_uuid()` default
- Always include `created_at` with `now()` default
- Use `author_id` / `user_id` UUID columns on user-owned tables — RLS will reference these
- Use `references: "table.column"` for foreign keys (cascades must be set carefully)
- `manage_schema` action `apply` is idempotent — safe to call again if schema is unchanged
---
Phase 3: Secure Data with RLS
Row-Level Security (RLS) ensures users can only access their own data. This phase is **not optional** for any table that holds user-generated content.
Enable User Isolation
Call `create_user_isolation_policy` for each user-owned table. This single call: 1. Enables RLS on the table 2. Creates a policy so users only see their own rows 3. Installs a BEFORE INSERT trigger to auto-populate the user column 4. Creates a service bypass policy for admin access
**Tool:** `manage_rls` with `action: "create_user_isolation"`
{
"app_id": "app_abc123",
"table_name": "posts",
"user_column": "author_id"
}Allow Public Reads (Optional)
For tables where some rows should be publicly visible (e.g. published blog posts), add `public_read_column`. This creates extra SELECT policies for both authenticated and anonymous users.
{
"app_id": "app_abc123",
"table_name": "posts",
"user_column": "author_id",
"public_read_column": "published"
}Repeat for every user-owned table. For the blog example:
{
"app_id": "app_abc123",
"table_name": "comments",
"user_column": "author_id"
}Test RLS Isolation
After applying policies, verify they work correctly by simulating user requests.
**Test SELECT as a specific user** — should only see that user's rows:
**Tool:** `select_rows`
{
"app_id": "app_abc123",
"table": "posts",
"as_role": "user",
"as_user": "11111111-1111-1111-1111-111111111111"
}**Test SELECT as anonymous** — should only see publ
Claude Code plugin for Butterbase — the AI-Native Backend-as-a-Service. This plugin gives Claude deep knowledge of Butterbase's 42+ MCP tools, guides you through common workflows, and auto-configures the MCP server connection.
Repo: butterbase-ai/butterbase-skills
Other skills on butterbase-skills.
- /agents
Use when designing, deploying, or debugging a Butterbase Agent (declarative LLM/tool graph), registering an MCP server for tool use, or wiring access controls and rate limits. Agents are first-class app resources defined by a `graph_spec` and invoked over
Open skill - /ai
Use when calling the app's AI gateway from agent tools — chat completions, embeddings, listing models, configuring defaults or BYOK, reading token/cost usage
Open skill - /auth-setup
Use when configuring OAuth providers (Google/GitHub/Apple/X/etc.), setting up post-login auth hooks, tuning JWT lifetimes, or generating service API keys
Open skill - /contributing
Use when contributing to the Butterbase codebase, adding new MCP tools, creating API routes, writing migrations, or understanding the monorepo architecture
Open skill - /debug-rls
Use when users report access denied errors, see wrong data, RLS policies are not working, or when troubleshooting Row-Level Security issues in Butterbase
Open skill - /deploy-frontend
Use when deploying a frontend (React, Next.js, or static HTML) to a live URL on Butterbase, or when troubleshooting deployment issues like MIME type errors or blank pages
Open skill

