app-builder
The app-builder skill creates single-user visual tools such as dashboards, trackers, calculators, data visualizations, and simple landing pages that users build for personal use. Use it when a user requests a "visualize this" tool, chart, or custom artifact for themselves. It should not be used for complex, multi-user, or products intended for deployment or sharing with others.
git clone --depth 1 https://github.com/vellum-ai/vellum-assistant /tmp/app-builder && cp -r /tmp/app-builder/assistant/src/config/bundled-skills/app-builder ~/.claude/skills/app-builderSKILL.md
You build small, personal visual tools — dashboards, trackers, calculators, data visualizations, simple landing pages, and slide decks. These are quick, single-user tools the user wants **for themselves**, not products they ship to other people.
Load `frontend-design` first (`skill_load("frontend-design")`), then move fast: think, plan in one pass, pick a striking visual direction following that skill, and build it immediately. Don't ask permission to be creative — pick the colors, the layout, the atmosphere, the micro-interactions. Every tool gets its own identity: a plant tracker feels earthy and green, a finance dashboard precise and navy. They should feel designed, not generated.
**Design quality is delegated to the `frontend-design` skill. You MUST call `skill_load("frontend-design")` before building anything, every time, and follow it completely.** That skill owns the aesthetics (typography, color, motion); this skill owns the technical infrastructure (sandbox, data, widgets, lifecycle). Skipping the load gives generic, templated UI, which is a failed build.
---
## Scope — what belongs here, what doesn't
**Build here** (the default — lean toward it): a tool the user wants for themselves. A dashboard, tracker, calculator, data viz, slide deck, or a simple landing page they'll use on their own. Personal and self-contained.
**Does NOT belong here:** anything complex, multi-user, or meant to be **published, deployed, handed off, or shipped to other people**. Sandbox apps are single-user, run only in this preview, and can't be exported or deployed. They're the wrong home for a real product.
When a request is for a shippable/complex app, don't build in the sandbox. Instead:
1. **Explain the approach** in a sentence: a real product belongs in a project folder they own — version-controlled, deployable, shareable — and you'll build it *with* them as a coding agent, not inside a preview.
2. **Establish a project folder** (propose a path, or use one they name).
3. **Hand off to a coding agent:** `skill_load("acp")` → `acp_spawn({ task: "<what to build>", cwd: "<folder>" })` (agent defaults to `claude`), then follow the `acp` skill.
Triage on intent, not artifact type. A simple landing page is a personal build by default — it only becomes a handoff when the user signals they want to publish or share it. When the signal is weak, lean personal and just build. If you genuinely can't tell, ask exactly **one** short question.
**Editing an existing sandbox app? Skip scope entirely** — that's iteration. Resolve the app (see below), open it, and go to *Iteration*.
### Resolving an app the user mentions
`app_open` takes an `app_id`, not a name:
1. If the `app_id` is already in your context, use it.
2. Otherwise `app_list(query: "<what they said>")` returns matches with `app_id` + `name`. `app_list()` with no query lists everything.
3. One match → open it. Multiple → list them and ask which. None → say so, show what exists, offer to build it.
---
## Filesystem layout
Apps live under `/workspace/data/apps/`:
```
/workspace/data/apps/
<slug>.json # App metadata
<slug>/
src/ # Source files (TSX) — what you write
dist/ # Compiled output — auto-generated by app_refresh
records/ # Data records (one JSON file per record)
<slug>.preview # Preview image (auto-generated)
```
Metadata fields: `id`, `name`, `description`, `icon`, `schemaJson`, `createdAt`, `updatedAt`, `formatVersion`, `dirName`. Records: `{ "id", "appId", "data": {...}, "createdAt", "updatedAt" }` — the system auto-adds everything but `data`.
All new apps use `formatVersion: 2` (multi-file TSX). No root-level `index.html` or `pages/` — those are legacy.
⚠️ Correct source path is `/workspace/data/apps/<slug>/src/`. Never `/workspace/apps/`.
---
## Responsive & design system
Every app works phone (~360px) to desktop (~1400px+). The `<turn_context>` block carries an `interface:` field: `ios` → mobile-first (design narrow first, body 17px); `macos`/`web` → desktop-first (multi-column, body 14px); absent → desktop-first unless the request implies phone use ("for my iPhone").
**Universal baseline — every build, regardless of interface:**
- Viewport meta: `width=device-width, initial-scale=1, viewport-fit=cover`. Never `user-scalable=no` (blocks accessibility zoom).
- Pad the root with `env(safe-area-inset-*)` so content clears the notch: `padding-top: max(var(--v-spacing-lg), env(safe-area-inset-top))`, mirrored for the other sides.
- Full-height containers use `100dvh`, not `100vh`.
- Form controls (`input`/`textarea`/`select`) must be `font-size: 16px`+ or iOS Safari zooms on focus. Add `inputmode` (`numeric`/`decimal`/`email`/`tel`/`url`).
- Interactive elements ≥44×44pt (`.v-button` already complies; custom controls set `min-height: 44px`). Gate hover behind `@media (hover: hover)`.
- Fluid widths only — `%`, `fr`, `minmax`, `clamp()`, never fixed `px` on containers. Size chart containers in `vw`/`%`. At narrow widths, collapse tables into stacked label-value cards.
**Mobile-first extras (`interface: ios`):** body `--v-font-size-lg` (17px); one column by default, multi-column only above `@media (min-width: 720px)`; bottom-anchor the primary action (`position: sticky; bottom: env(safe-area-inset-bottom)`); bottom sheets instead of side modals.
Full detail when reachable: `{baseDir}/references/RESPONSIVE.md`.
A design-system CSS and widget library are **auto-injected** (inside a `@layer`, so your own styles always win). Use the `--v-*` variables and `.v-*` classes below — they switch light/dark automatically, no manual dark-mode CSS needed. **Always use `window.vellum.widgets.*` chart functions** instead of hand-coded SVG/CSS charts.
**Design tokens** (use these, don't invent hex values):
| Category | Tokens |
| --- | --- |
| Backgrounds | `--v-bg`, `--v-surface`, `--v-surface-border` |
| Text | `--v-text`, `--v-text-secondary`, `--v-text-muted` |
| Acc>
>
>
>
Check Vellum Assistant architecture and package boundaries. Use when editing imports, moving code, adding endpoints, touching assistant/gateway/client/skill boundaries, or reviewing architecture-sensitive changes.
Review Vellum Assistant code changes for correctness, repo-specific quality rules, security risks, and missing validation. Use when reviewing diffs, preparing a PR, finishing implementation work, or when the user asks for a code review, quality pass, or pre-merge check in this repository.
Guide Vellum Assistant feature flag changes and rollout hygiene. Use when adding, editing, reviewing, or documenting assistant feature flags, rollout-gated behavior, or platform flag follow-up work.
Validate Vellum Assistant database and workspace migrations. Use when adding, editing, reviewing, or testing migrations, release-note migrations, persisted schemas, workspace file formats, or data backfills.