Zap separates planning (recipe validation, budget checks, step expansion) from execution (provider API calls, asset persistence, poll draining). The runtime glues Convex, Upstash, and provider adapters together into a durable, idempotent pipeline: each step can be retried safely, partial runs can resume, and mock runs share the same code path as live runs.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/gratitude5dee/Zap/llms.txt
Use this file to discover all available pages before exploring further.
Architecture Overview
A live run follows this path from API request to final artifact:Components
Convex
Convex is the source of truth for all run state. Every table is defined inconvex/schema.ts.
| Table | Purpose |
|---|---|
runs | One record per pipeline execution — status, cost, inputs, zapSlug, zapVersion |
steps | One record per planned step — status, provider, model, priceQuoteUsd, actualUsd, progress |
assets | Output files (png, mp4, wav, json) — URL, storageKey, dimensions, duration |
feedback | RLHF votes and VLM judge scores keyed by runId + stepId |
cronLogs | Cron job execution history — duration, processedCount, errorCount, status |
zaps | Published recipe index — slug, version, estimateUsd, source, status, tags |
Upstash Redis
Upstash provides two critical functions:- Idempotency keys — each provider job submission writes a key to Redis before the API call. If the submission is retried (e.g. after a timeout), the existing
requestIdis returned instead of creating a duplicate job. - Provider poll queues — after submission, a poll job is enqueued in Upstash. The drain endpoint consumes these jobs on a schedule, calls
provider.poll(requestId), and updates Convex when the result is ready.
Provider Adapters
Every provider implements theProviderAdapter interface from lib/provider-types.ts:
GenRequest type carries all information needed for a provider API call:
step.provider (or defaults.provider) against registered adapter IDs:
| Adapter | File | Description |
|---|---|---|
gmi | lib/providers/gmi.ts | GMI Cloud — primary provider for Seedance and related models |
fal | lib/providers/fal.ts | fal.ai — Kling, Flux, Veo, and other hosted models |
mock | lib/providers/mock.ts | Deterministic zero-cost outputs for development and demos |
Poll Drain Endpoint
POST /api/providers/poll/drain is invoked by the Upstash queue scheduler. It:
- Dequeues a batch of pending poll jobs from Upstash
- For each job, calls
provider.poll(requestId, secrets) - On
done: writes the asset to@vercel/blob, records the asset in Convex, marks the stepdone - On
failed: records the error on the Convex step, marks the stepfailed - On
queued/running: re-enqueues the job with an exponential backoff delay
Blob Store
Generated assets are persisted to Vercel Blob via@vercel/blob. The asset URL is written to the assets table in Convex.
Required environment variable:
BYOK Key Retrieval
Live runs can use creator-supplied provider keys (Bring Your Own Key). The key retrieval flow is:- The client sends a wallet-authenticated Supabase bearer token with the run request
- The server verifies the JWT and the
ZAP_SECRET_REVEAL_TOKENenvironment variable - Provider keys are fetched from Supabase and injected into the
GenRequest.secretsfield - The provider adapter reads
secretsduringsubmit()andpoll()calls - Plaintext keys are never returned to the browser — they exist only in the server-side request context
HyperFrames Stitching
When a recipe specifiesstitch.engine: hyperframes, the runtime follows this flow:
- Detect
stitch.engine: hyperframesin the planned step - Generate a temporary HyperFrames project directory with a Zap visual identity (
DESIGN.mdis written automatically if not present in the recipe root) - Validate the project by running the HyperFrames CLI checks in sequence:
- Render the composition to the output format and quality:
- Persist the rendered file to
@vercel/bloband record the asset in Convex - On failure: record the error message on the Convex step record and fall back to the first resolved stitch asset — the run is marked
done(notfailed) with an explanatory step error
HyperFrames is an optional runtime dependency. If
npx hyperframes is not available in the execution environment, the auto engine falls back to local FFmpeg-based stitching automatically. Only engine: hyperframes (explicit) triggers the HyperFrames path; engine: auto prefers HyperFrames when available but never fails if it is absent.Live vs Mock Runs
Themock provider adapter returns deterministic, zero-cost outputs on every call. It is used by default in new recipes (defaults.provider: mock) and for all demo runs on the web.
| Behavior | Mock | Live |
|---|---|---|
| Provider API calls | None — outputs are deterministic fixtures | Real calls to GMI / fal |
| Cost | $0 | Billed per quoteStep() rates |
| Output | Fixture files | Real generated assets |
| Local CLI storage | .zap/runs/<runId>/ | .zap/runs/<runId>/ |
| Web storage | Convex + Blob (fixture URLs) | Convex + Blob (real URLs) |
| Auth required | No — public | Yes — wallet-authenticated Supabase token |
--live flag required | No | Yes (CLI) / live: true (API) |
Mock creator demos are public and zero-spend — no wallet or API keys are required. Live runs that call real provider APIs require a wallet-authenticated Supabase bearer token and a funded provider account.
Environment Variable Reference
| Variable | Component | Required |
|---|---|---|
UPSTASH_REDIS_REST_URL | Upstash | Live runs |
UPSTASH_REDIS_REST_TOKEN | Upstash | Live runs |
BLOB_READ_WRITE_TOKEN | Vercel Blob | Live runs |
ZAP_SECRET_REVEAL_TOKEN | BYOK key retrieval | BYOK runs |
CONVEX_DEPLOYMENT | Convex client | All web runs |
NEXT_PUBLIC_CONVEX_URL | Convex client (browser) | All web runs |
