# V0

> Vercel's v0 app builder — taking v0 output into a production repo, and driving the v0 Platform API (v2, api.v0.dev/v2) from code with the `v0` npm SDK. Use when the user names v0, v0.dev, v0.app, the v0 Platform API, a v0 chat/preview/deploy URL, `V0_API_KEY`, `@v0-sdk/*`, or is reviewing/merging code described as generated by v0. Scope boundary: this skill owns the v0-specific workflow — the import seam, the Platform API surface, and v0-vs-repo drift. It does not own the topics of the code v0 emits: shadcn/ui and registries → shadcn, App Router and Server Components → nextjs, render performance → react-best-practices, model routing → ai-gateway, repo/env provisioning → bootstrap. Do not claim a request merely because the project is Next.js, uses shadcn/ui, or is deployed on Vercel.

- Skill: `catcorner22/v0` (Agent Skill)
- Install (CLI): `npx skillmds@latest add catcorner22/v0`
- Raw SKILL.md: https://api.skillmd.com/api/skills/catcorner22/v0/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: CatCorner22 (https://skillmd.com/u/catcorner22)
- Updated: 2026-09-21
- Page: https://skillmd.com/skills/catcorner22/v0

---

# v0

Three distinct surfaces share the name. Do not conflate them.

| Surface | What it is | Entry point |
|---|---|---|
| v0 web app | The hosted builder: chats, previews, projects, GitHub sync, one-click deploy | `v0.app` |
| v0 Platform API | REST API that drives that same agent headlessly — v2, `https://api.v0.dev/v2`, bearer auth | `npm i v0` |
| v0 Model API | Separate OpenAI-compatible `/chat/completions` endpoint under `api.v0.dev/v1` | see *Models*, below |

## Getting v0 output into a repo

Four routes. Pick by how much you intend to keep.

| Route | Mechanism | Use when |
|---|---|---|
| shadcn registry | `npx shadcn@latest add "<v0 chat URL>"`, or a `v0` entry under `registries` in `components.json` then `@v0/<name>` | One screen or component. The default "Add to Codebase" path. |
| GitHub integration | v0 cuts a working branch off a base branch; you review and merge a PR | The chat is an ongoing contributor to the repo |
| Platform API files | `v0.chats.getFiles({ chatId })` → `{ files: [{ path, content, encoding }] }`, or `downloadFiles` for a ZIP | Scripted/bulk import, or you want the file set under your own diffing |
| Copy/paste | — | Throwaway spike only. It loses provenance; prefer any of the above. |

`@v0` is **not** a built-in shadcn namespace — it only resolves if `components.json` declares it. Registry mechanics, `components.json`, and namespace auth belong to **shadcn**; do not restate them here.

The Platform API also runs the seam backwards: `chats.createFromRepo` (GitHub URL + branch), `createFromFiles` (≤20 UTF-8 files), and `createFromZip` seed a chat *from your code*, so an iteration starts from what you actually shipped instead of from v0's last memory of it.

### Import review checklist

v0 optimizes for a working preview, not for your repo's invariants. Walk this before the first commit; everything here is routine in generated output and cheap to fix at import time, expensive later.

| Check | What you will find | Fix |
|---|---|---|
| Hardcoded data | Inline arrays of fake rows, `const user = { name: "Jane" }`, placeholder counts | Replace with the real fetch; keep the array as a fixture only if a test uses it |
| Client/server boundary | `"use client"` at the top of files that never touch state or an effect; data fetched in `useEffect` | Strip the directive where nothing needs it; move fetching to the server component. Boundary rules → **nextjs** |
| Loading / error / empty | Only the happy path exists | Add `loading.tsx` / `error.tsx` or `Suspense` + a real empty state |
| Accessibility | Icon-only buttons with no accessible name, `div` click handlers, unlabeled inputs, decorative-only focus rings, contrast from ad-hoc colors | Name every control, use real `button`/`label`, keep the token-based focus ring |
| Dependencies | Packages added at whatever version resolved during generation; occasionally a package the repo already solves another way | Reconcile against the existing lockfile before installing; delete duplicates rather than adding a second date/icon/chart library |
| Theme drift | Literal hex/`bg-slate-900` instead of `bg-background` / `text-muted-foreground` / `border-border` | Re-map onto the project's tokens |
| `components/ui/**` overwrite | The add command silently replaces primitives you have already customized | `--dry-run` first, then `--diff`; never `--overwrite` blind |
| Secrets & env | Keys inlined, or `NEXT_PUBLIC_` on something that must stay server-side | Move to server env; add the name (never the value) to `.env.example` |
| Images / fonts | Remote placeholder image hosts, a second font family | Point at your own assets; drop the extra font |

Render-performance findings (waterfalls, needless re-renders, bundle weight) are **react-best-practices**' territory — run it after the checklist, don't duplicate it.

### Keeping generated code maintainable

- Land the import as its own commit, unmodified, then fix in a second commit. The two-commit shape is what makes "what did v0 actually write" answerable later.
- Treat generated files as normal owned source the moment they merge. There is no supported re-sync of an edited file back from a chat; `chats.updateFiles` pushes edits *into* the chat, it does not pull.
- Re-generating? Feed the current repo back in with `createFromRepo` / `createFromFiles` first. Prompting a stale chat produces a diff against code you no longer have.
- Keep one chat per surface. A chat that has accumulated five unrelated screens re-emits all five.

## Platform API (v2)

Verified against `packages/v0-sdk/openapi.json` at `vercel/v0-sdk@276e1c2` (OpenAPI 3.1.2, `info.version` 2.0.0, server `https://api.v0.dev/v2`).

| Package | npm latest (2026-08-25) | Purpose |
|---|---|---|
| `v0` | 3.0.4 | The v2 SDK. `import { v0 } from 'v0'` |
| `v0-sdk` | 0.16.7 | The **v1** SDK — defaults to `https://api.v0.dev/v1`. Legacy name; new work uses `v0` |
| `@v0-sdk/react` | — | Hooks + AI SDK transport for a browser client calling *your* proxy routes |
| `@v0-sdk/ai-tools` | — | Every OpenAPI operation as an AI SDK tool (`v0Tools`, `v0ToolsByCategory`) |

Auth: the default client uses `V0_API_KEY`, and falls back to Vercel OIDC for server-side code deployed on Vercel. `createV0Client({ auth, baseUrl })` overrides both. Every call returns `{ data, error }` — check `error` rather than relying on a throw.

```ts
import { v0 } from 'v0'

const res = await v0.chats.create({ message: 'Build a pricing page' })
if (res.error) throw new Error(res.error.message)

const preview = await v0.chats.getPreview({ chatId: res.data.chat.id })
// preview.data is null while the preview is still starting — poll.

const { data } = await v0.chats.getFiles({ chatId: res.data.chat.id })
// data.files: { path: 'app/page.tsx', content: string, encoding: 'utf8' | 'base64' }[]
```

| Group | Operations |
|---|---|
| `chats` | `list` `create` `createFromFiles` `createFromZip` `createFromRepo` `createStream` `createAsync` `get` `update` `delete` `duplicate` `getPreview` `getFiles` `updateFiles` `downloadFiles` `getConnectStatus` `restoreMessage` `resume` `deploy` `createVercelProject` |
| `messages` | `list` `get` `send` `sendStream` `sendAsync` `resolve` `resolveStream` `resolveAsync` `stop` |
| `mcpServers`, `settings`, `usage`, `webhooks` | CRUD; `settings.{get,set}PreviewHosts`; `usage.{getSummary,listEvents,getActivity}` |

- Streaming: `createStream` / `sendStream` return a server result — `readV0Stream(result.toResponse())` yields `{ stream, final }`.
- `chats.deploy` returns a `deploymentId`; the build runs asynchronously on Vercel — track it with the Vercel API, not by polling v0. Deploy/CI mechanics → **deployments-cicd**, **vercel-cli**.
- Webhook events: `chat.created` `chat.updated` `chat.deleted` `message.created` `message.updated` `message.deleted` `message.finished`.
- `chats.create` accepts `skills` (≤3) drawn from skills.sh (`remote`), user/team `memory`, or `project` scope.
- **Never ship `V0_API_KEY` to a browser.** `@v0-sdk/react` is deliberately built around app-owned proxy routes that call the server-side SDK and re-expose only what you authorize.

## Models

`modelConfiguration.modelId` on chat/message creation, from the checked-in v2 spec: `v0-mini`, `v0-pro` (default), `v0-max`, `v0-max-fast`. Pair with `imageGenerations` (default `false`). The v1 SDK's typings also list `v0-auto`; it is absent from the v2 enum — read the enum in `openapi.json` for the version you install rather than hardcoding from here.

The **Model API** is a different product from the Platform API despite sharing the `api.v0.dev` host: an OpenAI-compatible `POST /v1/chat/completions` with `v0-1.x`-series model ids, supporting only `messages`, `model`, `stream`, `tools`, `tool_choice`. Reach for it when you want v0's frontend-tuned generation inside your own chat app; reach for the Platform API when you want chats, files, previews, and deploys. Routing either through AI Gateway (`vercel/…` provider prefix) is **ai-gateway**'s topic — resolve ids with `gateway.getAvailableModels()` before hardcoding.

## Verified vs not

Verified here by reading the artifact: the v2 OpenAPI document, SDK method surface, model enum, file/webhook schemas, auth model, and npm package lineage and dates. `@v0` being a configured — not built-in — shadcn namespace was verified against `shadcn@4.19.0`'s own error strings.

Not verified — `v0.app`, `v0.dev`, `vercel.com`, `ai-sdk.dev`, and `api.v0.dev` were all unreachable from this environment (egress policy), so the following come from secondary evidence and should be re-checked against the docs before you rely on them: the exact registry URL for the `@v0` namespace; the exact "Add to Codebase" command string; the GitHub integration's branch/PR mechanics; the Model API's current model ids and whether it is still offered; and which v0 models AI Gateway carries.

## References

- v0 docs — https://v0.app/docs · Platform API v2 — https://v0.app/docs/api/v2 · v1→v2 migration and AI models pages under the same tree
- `vercel/v0-sdk` — https://github.com/vercel/v0-sdk (read at `276e1c2`; `packages/v0-sdk/openapi.json` is the generated SDK's copy of the upstream v2 spec)
- npm: [`v0`](https://www.npmjs.com/package/v0) · [`v0-sdk`](https://www.npmjs.com/package/v0-sdk) · [`@v0-sdk/react`](https://www.npmjs.com/package/@v0-sdk/react)
- Model API request body — https://v0.dev/docs/v0-model-api#request-body (cited by third-party clients; not fetched)
- In-repo: `skills/vercel/shadcn` (registries, `components.json`, theming) · `skills/vercel/nextjs` · `skills/vercel/react-best-practices` · `skills/vercel/ai-gateway`

