Skip to content
Development
Skill

/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

From plugin
butterbase-skills
53239 skills33 commands1 MCP
Install
$ npx -y skills add butterbase-ai/butterbase-skills --skill build-app --agent claude-code

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

Read more
Ships withbutterbase-skills

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.

Get the whole plugin