Skip to content

~2 min read

Get started·

tiny-vercel is two deployables and one shared protocol package, all in one repository:

Path What it is Where it runs
apps/web Next.js 16 App Router — every page, all 65 app/api/* routes, the agent tools Vercel
apps/worker Cloudflare Worker — D1 (SQL), KV, Vectorize, R2, a Durable Object for voice, a 1-minute cron Cloudflare
packages/contracts TypeScript wire protocol: SSE events, device relay envelopes, notification payloads, x402 quotes both
examples/echo-device the smallest endpoint device (telemetry / chat / snapshot behind a bearer) + an enroll script your laptop
scripts/ bootstrap-cloudflare.mjs creates the worker's storage under one prefix; teardown-cloudflare.mjs removes exactly that your laptop

Pick the path that matches what you want right now.

What you need·

  • A Cloudflare account — the free plan covers D1, KV, Vectorize, R2 and Workers.
  • A Vercel account and a GitHub account (GitHub is the first-login identity provider; passkeys come after).
  • An OpenAI API key. It is the default chat model and the embedding model (text-embedding-3-small). Chat can move to Bedrock, Gemini, Vercel AI Gateway or a user's own key later; embeddings stay on OpenAI.
  • Node 22 and npm on your machine.

What runs where·

flowchart LR
  B[Browser / PWA] -->|HTTPS + SSE| W[apps/web on Vercel]
  D1[Dial-in device<br/>tiny-vercel CLI, phone, e-ink] -->|heartbeat · relay mailbox| W
  W -->|X-Internal-Key| K[apps/worker on Cloudflare]
  K --> S[(D1 · KV · Vectorize · R2 · DO)]
  K -->|bearer, https only| D2[Dial-out device<br/>robot arm, printer, echo]

The app never talks to storage directly: every internal call goes to the worker with INTERNAL_API_KEY, and the worker refuses anything else. Set the same value on both sides or every call is a 401.