Documentation

Build, launch and ship apps with AI.

shipped turns a sentence into a hosted web app, pairs it with its own pump.fun coin, and gives every app a tiny cloud backend. These docs cover how the AI builder works, the window.shipped SDK, and the public API.

Get started

Quickstart

From idea to a live, coin-paired app. No code, no API keys, no deploy step.

  1. 1

    Describe the app

    Open the studio and type what you want. Attach a screenshot if you have a look in mind. Pick a model, or keep the default.

  2. 2

    Pair its coin

    The AI suggests a name, ticker, description and icon. Edit anything, connect your wallet and sign once. You are the creator on pump.fun.

  3. 3

    Watch it build

    As soon as the coin lands on chain, the build starts streaming into the live preview. It is hosted at its own URL the moment it finishes.

  4. 4

    Keep shipping

    Ask for changes in plain English. Every version is saved; restore, compare or remix any of them.

Open the studio

Get started

Writing great prompts

Models build what you describe. Say what it does, how it feels, and what should be shared between visitors.

A strong first prompt
A tiny space shooter.
- Arrow keys or drag to move, auto-fire
- Enemies speed up every 20 seconds
- Neon on black, chunky pixel font
- Global leaderboard: ask for a name once, show the top 10
Instead ofTry
"a game""a one-button jumping game, gets faster, global top 10"
"make it better""bigger tap targets, a pause button, smoother death animation"
"fix it"Click Fix with AI. It sends the real runtime errors from the preview.
"add a database""save every visitor’s guestbook entry and show the latest 20"
Mention leaderboard, guestbook, counter or holders and the model reaches for the built-in SDK automatically.

The AI builder

How a build runs

Every prompt goes through the same six steps. Nothing reaches your app URL until the model has produced a complete document.

  1. 01Your promptText, plus an optional screenshot and your last 6 prompts.
  2. 02Builder briefStrict output rules, a quality bar and the shipped SDK reference.
  3. 03AI GatewayVercel AI Gateway routes the request to the model you picked.
  4. 04Model streamsHTML arrives token by token. Cut off? It continues, up to 3 passes.
  5. 05Checked + savedOnly a complete document is saved as a new version. Never half a page.
  6. 06Live at its URLHosted sandboxed at /p/id, which is also the coin’s website.

The AI builder

Models

5 models from four labs through Vercel AI Gateway, plus 7 more through OpenRouter. Switch models per prompt from the studio composer.

  • Kimi K2.7 CodeMoonshot AI
    Default

    The default. Strongest at long, complete files: games, tools with real logic, careful layouts.

    moonshotai/kimi-k2.7-codespeedReads screenshots
  • Google DeepMind
    Gemini 2.5 FlashGoogle DeepMind

    Bold, playful visuals and reading screenshots. Great for "make it look like this".

    google/gemini-2.5-flashspeedReads screenshots
  • GPT-4.1 miniOpenAI

    Balanced and dependable. Clean structure, good at following detailed specs.

    openai/gpt-4.1-minispeed
  • Z.ai
    GLM 4.7 FlashZ.ai

    Quick drafts and small edits when you want to iterate fast.

    zai/glm-4.7-flashspeed
  • GPT-OSS 120BOpenAI

    Open-weight and the fastest of the set. Good for simple apps and rapid tweaks.

    openai/gpt-oss-120bspeed
Via OpenRouterListed under OpenRouter in the model picker
Live
  • Claude Sonnet 5.5anthropic/claude-sonnet-5.5
  • Claude Opus 5.5anthropic/claude-opus-5.5
  • GPT-5.6 Solopenai/gpt-5.6-sol
  • Gemini 3.8 Flashgoogle/gemini-3.8-flash
  • Grok 4.7x-ai/grok-4.7
  • DeepSeek V4.1 Flashdeepseek/deepseek-v4.1-flash
  • North Mini CodeFreecohere/north-mini-code:free
Attach a screenshot to a model that cannot read images and shipped hands that turn to a vision model automatically. If one vision model rejects the image, the other gets one retry.

The AI builder

The builder brief

Each request starts with the same system instructions. They set the output format, a quality bar, and teach the model the SDK.

lib/builder/prompt.ts (excerpt)
You are the app builder inside "shipped". You turn a user's idea
into ONE complete, working, beautiful web app delivered as a single
self-contained HTML file.

Output rules (strict):
- Reply with ONLY the HTML document, starting with <!doctype html>.
- Everything lives in this one file: markup, <style> and <script>.
- You MAY load Tailwind, Google Fonts, and libraries from jsdelivr/unpkg.
- Never use external images. Draw with CSS, inline SVG or canvas.
- The app MUST work immediately with no setup, no API keys.

Built-in cloud SDK (already loaded as window.shipped):
- shipped.db.get / set / incr / list   shared by every visitor
- shipped.scores.submit / top          global leaderboards
- shipped.coin(wallet?)                live coin + holder check

On follow-up prompts the model also receives the current HTML and your last six prompts, so it edits the existing app instead of starting over. The result is always one self-contained file, which is what makes every app downloadable, remixable and safe to sandbox.

What comes back: one file (trimmed)
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>Star Dash</title>
  <script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="bg-black text-white">
  <canvas id="game" class="block h-dvh w-full"></canvas>
  <ol id="board" class="fixed right-4 top-4 font-mono text-sm"></ol>
  <script>
    async function gameOver(score) {
      if (!window.shipped) return
      const name = localStorage.getItem('pilot') || prompt('Pilot name?') || 'anon'
      localStorage.setItem('pilot', name)
      const { rank } = await shipped.scores.submit(name, score)
      const top = await shipped.scores.top({ limit: 10 })
      board.innerHTML = top
        .map((r) => `<li class="${r.me ? 'text-green-300' : ''}">#${r.rank} ${r.name} ${r.score}</li>`)
        .join('')
    }
    // ...game loop
  </script>
</body>
</html>

The AI builder

Streaming + continuation

Output streams into the preview as it is written. Long apps can exceed a single response, so the builder keeps going.

app/api/builds/[id]/generate/route.ts (simplified)
import { streamText } from 'ai'

const result = streamText({
  model: 'moonshotai/kimi-k2.7-code', // routed by Vercel AI Gateway
  instructions: BUILDER_INSTRUCTIONS,
  messages: buildMessages({ prompt, currentHtml, history, image }),
  maxOutputTokens: 24_000,
  abortSignal,
})

for await (const delta of result.textStream) {
  send(delta) // straight into the live studio preview
}

// Cut off mid-file? Ask the model to continue from where it stopped,
// overlap-join the two halves, and try again (max 3 passes).
if (!isComplete(extractHtml(text))) continueFrom(text)
BehaviourDetail
Max output24,000 tokens per pass
ContinuationUp to 3 passes, overlap-joined so repeated lines are trimmed
StopAbort any time. An aborted run is never saved
SaveOnly when the document is complete. Each save is a new version

The AI builder

Screenshots + fixes

Two inputs make the model much better than a text box alone.

Screenshot to app

Paste or drop an image into the composer. It is downscaled in your browser, sent with the prompt, and stored with that version so you can see what inspired it.

Fix with AI

The studio preview listens for runtime errors inside your app. When one appears, one click sends the exact messages back to the model with the current file.

App SDK

window.shipped

Every hosted app gets a tiny cloud backend with zero setup. No keys, no accounts, no imports. It is injected before your code runs.

Always guard it
// Hosted apps always have window.shipped. Guard anyway so the
// file still works if someone downloads it and opens it locally.
if (window.shipped) {
  try {
    await shipped.db.incr('plays')
  } catch (err) {
    console.warn('offline, skipping', err)
  }
}
Data is scoped to the app. Remixes start with a clean slate, and one app can never read another app's keys or scores.

App SDK

shipped.db

Key-value storage shared by every visitor.

shipped.db
// Shared by every visitor of this app
await shipped.db.set('motd', 'gm builders')
const motd = await shipped.db.get('motd')       // 'gm builders'

// Atomic counters
const visits = await shipped.db.incr('visits')  // 1, 2, 3...
await shipped.db.incr('likes', 5)

// Prefix scans for lists
await shipped.db.set('guestbook:' + Date.now(), { name: 'ava', text: 'love it' })
const entries = await shipped.db.list('guestbook:')
// [{ key, value, updatedAt }, ...]
MethodReturnsNotes
get(key)value | nullAny JSON value
set(key, value)valueUp to 8 KB of JSON
incr(key, n = 1)numberAtomic. Starts from 0
list(prefix){ key, value, updatedAt }[]Newest first

App SDK

shipped.scores

Global leaderboards. Each player keeps their best score per board.

shipped.scores
// Each player keeps only their best score
const { best, rank } = await shipped.scores.submit('ava', 4200)

const top = await shipped.scores.top({ limit: 10 })
// [{ rank: 1, name: 'ava', score: 4200, me: true }, ...]

// Lower is better? Use order: 'asc' (speedruns, reaction tests)
await shipped.scores.submit('ava', 9.81, { board: 'speedrun', order: 'asc' })
await shipped.scores.top({ board: 'speedrun', order: 'asc' })

App SDK

shipped.coin

Live market data for the app's coin, and an optional holder check for any wallet.

shipped.coin
const { coin } = await shipped.coin()
// { name, symbol, marketCapUsd, priceUsd, url } or null

// Unlock extras for holders of this app's coin
const wallet = input.value.trim()
const { holder } = await shipped.coin(wallet)
if (holder?.holds) unlockGoldSkin()
The holder check reads public chain data for an address the visitor types. It does not prove they own that wallet, so use it for perks and cosmetics, not for anything valuable.

Reference

REST API

The SDK is a thin wrapper over public, CORS-enabled endpoints. Call them from anywhere.

GET/api/sdk/{appId}/kv?key={key}
Read one key. Use ?prefix= instead to list keys.
POST/api/sdk/{appId}/kv
Body { key, value } to write or { key, increment } to add.
GET/api/sdk/{appId}/scores?board=main&limit=10
Top scores. Add &order=asc for lowest-wins boards.
POST/api/sdk/{appId}/scores
Body { board, name, score, order? }. Returns your best and rank.
GET/api/sdk/{appId}/coin?wallet={address}
Coin market data, plus holder balance when a wallet is given.
# Read one key
curl "https://www.useshipped.app/api/sdk/bammv4mriq/kv?key=visits"

# List keys by prefix
curl "https://www.useshipped.app/api/sdk/bammv4mriq/kv?prefix=guestbook:"

# Write a value
curl -X POST "https://www.useshipped.app/api/sdk/bammv4mriq/kv" \
  -H "content-type: application/json" \
  -d '{"key":"motd","value":"gm"}'

# Increment a counter
curl -X POST "https://www.useshipped.app/api/sdk/bammv4mriq/kv" \
  -H "content-type: application/json" \
  -d '{"key":"visits","increment":1}'
curl "https://www.useshipped.app/api/sdk/bammv4mriq/scores?board=main&limit=10"

curl -X POST "https://www.useshipped.app/api/sdk/bammv4mriq/scores" \
  -H "content-type: application/json" \
  -d '{"board":"main","name":"ava","score":4200}'

Errors return a non-2xx status with { "error": "message" }. The app id is the last part of its studio URL, /build/{appId}.

Reference

Embeds

Drop a playable app with its live price and a Buy button into any website.

embed.html
<iframe
  src="https://www.useshipped.app/embed/7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU"
  width="420"
  height="560"
  style="border:0;border-radius:16px"
  loading="lazy"
  title="Play on shipped"
></iframe>

Copy a ready-made snippet from any coin page or from the Share menu in the studio.

Reference

Share cards

Every card in the card generator is a URL, so you can create images programmatically.

Download a card
curl -o card.png "https://www.useshipped.app/api/card?kind=milestone&value=10000&label=plays&format=square"
ParamValues
kindlaunch, milestone, shipped, quote, announce
formatwide (1600 x 900), square (1080 x 1080)
tonegreen, yellow
...fieldsEach kind has its own text fields. Build one in the generator and copy the link.
Open the card generator

Reference

Coins + launches

Any app can get its own real pump.fun coin on Solana mainnet, whenever you are ready. You sign; shipped verifies.

  1. 01

    Prepare

    The server pins your coin metadata (website = the app URL) and builds the create transaction with you as creator. An optional first buy goes in the same signature.

  2. 02

    Sign

    Your wallet signs everything in one approval. The mint key co-signs on the server.

  3. 03

    Verify

    Before relaying, the signed bytes are checked: you pay the fee, every signature is valid, and every instruction matches what was built. Anything modified is refused.

  4. 04

    Relay

    The transaction is sent and confirmed, the coin is linked to the app, and the first build starts.

Creator fees go to the wallet that signed the launch. shipped never takes custody of your coin or your SOL.

Reference

Security model

SurfaceProtection
Hosted appsServed with a CSP sandbox and an opaque origin, so an app cannot read shipped cookies or other apps.
EditingOnly the browser holding the private build key can prompt or restore. Everyone else can remix.
Launches + tradesSigned bytes are re-verified on the server before relay. Programs are allowlisted.
Comments, follows, ship logsSigned by your wallet with a timestamp, so nobody can post as you or replay old messages.
ModerationApps reported by 5 different people are hidden from the site and their URL.

Reference

Limits

LimitValue
Builds20 prompts per 10 minutes per visitor
Prompt length2,000 characters
SDK keys per app500
Key length64 characters: letters, numbers, . : - / _
Value size8 KB of JSON
SDK writes60 per minute per visitor per app
SDK reads240 per minute per visitor per app
Score submissions20 per minute per visitor per app
Leaderboard sizeTop 100 per request

Reference

Infrastructure

shipped is built on production infrastructure, end to end.

Ready to ship something?

Describe it in a sentence. You will have a live app, its own coin, and a backend before your coffee cools.