System One
System One
DocumentationAPI referenceDeploySDK on GitHubSystem One
Decision primitives
Credits and billingData handlingDeploy on Cloudflare Workers

Deploy on Cloudflare Workers

Run the TinyShip-based application with D1, Better Auth, an upstream provider, and a separate static documentation Worker.

Architecture

LocationResponsibility
apps/tanstack-appMain website, console, playground, API routes, and scheduled cleanup.
libs/system-oneNative transport/observational validation, exact JSON identity, keys, provider adaptation, limits and usage.
libs/auth, libs/databaseExisting Better Auth sessions and shared D1 data model.
libs/credits, libs/paymentExisting credit balance, ledger, orders, and verified payment fulfillment.
configProduct limits, plans, and shared capability configuration.
apps/docs-appThis Fumadocs / Next.js static export, deployed independently.

Only the TanStack main app and docs app are maintained in this distribution. Shared business logic stays in TinyShip’s modules and the routes stay thin. There is no custom replacement language model or production mock inference. An unconfigured provider returns 503 provider_not_configured without a new charge.

Run locally

Use Node.js 22 or later and the project’s pinned pnpm 9.4.0. From the repository root:

npx --yes pnpm@9.4.0 install --frozen-lockfile
npx --yes pnpm@9.4.0 setup:local
npx --yes pnpm@9.4.0 db:migrate:local
npx --yes pnpm@9.4.0 dev

The main app runs at http://localhost:7001. setup:local creates a root .env and apps/tanstack-app/.dev.vars without overwriting existing files. It generates a local Better Auth secret. These files contain secrets and stay excluded from version control.

Add real upstream credentials to the local configuration when you are ready to call a provider. Keep root .env and Worker .dev.vars consistent when both are used. Local setup allows unverified sign-in for development; it does not grant the verified-email welcome bonus to an unverified account. Production should require email verification and a configured email delivery service.

Create and migrate production D1

Authenticate Wrangler with your Cloudflare account, then create the database:

npx --yes pnpm@9.4.0 --filter @system-one/web exec wrangler login
npx --yes pnpm@9.4.0 --filter @system-one/web exec wrangler d1 create system-one

In apps/tanstack-app/wrangler.jsonc, replace the placeholder database_id with the returned ID. Keep the binding name DB and the migrations directory ../../libs/database/drizzle-sqlite. Apply the entire migration sequence, including the existing TinyShip tables and 0006_system_one.sql:

npx --yes pnpm@9.4.0 db:migrate:remote

Migrate the intended remote database before serving the new application. Do not replace the shared auth, order, or credit tables with a separate decision-only database.

Configure the main Worker

Set these non-secret values in the main Worker’s Wrangler vars:

VariableValue
DB_DIALECTd1
APP_BASE_URLExact public main application origin, such as https://app.example.com.
BETTER_AUTH_URLThe same main application origin.
AUTH_REQUIRE_EMAIL_VERIFICATIONtrue for production.
EMAIL_PROVIDERresend by default; cloudflare is an optional existing email integration.
EMAIL_DEFAULT_FROMSender address on your configured email domain.
SYSTEM_ONE_PROVIDERtypesafe or openrouter.
SYSTEM_ONE_MODELDefault used only when a request omits model; otherwise jev-latest. Set a supported alias/version. Explicit TypeSafe request models take priority.
SYSTEM_ONE_RATE_LIMIT120 by default, shared per account.
SYSTEM_ONE_SIGNUP_CREDITS100 by default; 0 disables welcome credits.
SYSTEM_ONE_DOCS_URLPublic docs destination, such as https://docs.example.com/zh-CN/docs.

Do not deploy the example origin or placeholder database ID. Session-origin checks use APP_BASE_URL; cookies and email links need the corresponding Better Auth URL. Preserve the main Worker’s nodejs_compat setting and cleanup cron */15 * * * *.

Add credentials as Worker secrets, entering values at the prompt rather than placing them in the command:

npx --yes pnpm@9.4.0 --filter @system-one/web exec wrangler secret put BETTER_AUTH_SECRET
npx --yes pnpm@9.4.0 --filter @system-one/web exec wrangler secret put SYSTEM_ONE_UPSTREAM_API_KEY
npx --yes pnpm@9.4.0 --filter @system-one/web exec wrangler secret put RESEND_API_KEY

Use a new strong production auth secret, not the local development value. The email configuration shown uses TinyShip’s Resend integration. Additional enabled authentication providers need their corresponding existing TinyShip settings.

Select the upstream

ProviderDefault upstream base URLUpstream model
typesafehttps://api.typesafe.ai/v1jev-latest
openrouterhttps://openrouter.ai/api/alpha~typesafe/jev-latest

SYSTEM_ONE_UPSTREAM_URL is an optional HTTPS override without credentials, query or fragment. SYSTEM_ONE_UPSTREAM_API_KEY must match the selected service. Native TypeSafe uses bounded Fetch and X-System-One-Response-Mode: typesafe-native: explicit request model/text and successful response text/status/extensions are preserved after validation. Omitted model defaults are inserted into root JSON without rounding existing numbers. Nullable state is allowed but required as a field, instructions may be omitted/null, and Noul criteria may be null; the provider decides final acceptance.

OpenRouter is an explicit adapter inside the Worker. Matching jev-* request names map to ~typesafe/jev-* and the adapter builds /decisions. Responses retain provider usage/cost and metadata with openrouter-adapted, not TypeSafe byte fidelity; unsupported top-level request extensions are rejected. Clients still point at the platform /v1 without a direct-provider adapter. Native GET /v1/models requires a platform key and returns real TypeSafe { models }; OpenRouter returns 501 model_listing_not_supported.

The Worker forwards state and questions to that provider. Review data handling before exposing a deployment to users. Upstream availability and measured performance must be verified in your own environment.

Compatibility upgrade

Contract typesafe-2026-09-18 separates Choice's 255-option maximum from Score's 10-level maximum; request size remains 65,536 bytes, questions 32 and depth 32. Client validation imports shared configuration. Duplicate JSON keys are rejected, exact numeric tokens distinguish idempotent requests, and aliases/versions are not restricted to a local latest-only list.

Migrate consumers from successful body billing/IDs to X-System-One-Credits, X-Request-Id, X-Upstream-Request-Id and X-Idempotency-Replayed. The gateway adds no default usage/warnings/rounding. Native Choice/Score distributions and confidence are required, as is Score legend. Project SDK 0.3.0 may normalize/default its own result; the official SDK 0.6.0 supplies an independent compatibility check.

Upstream JSON errors retain 4xx/5xx status and Retry-After, including 401/403 and 429/529; stable UI codes and source come from headers. Credential-bearing errors receive safe bodies, while unsafe successes, malformed or oversized responses and redirects are rejected. The shared upstream timeout is 20 seconds with no retries. Refund reconciliation failure is 503 with no charge header. Review errors before changing client recovery logic.

No schema migration is needed for replay storage. New versioned records retain text/status/allowed headers; unversioned records are read as legacy-cache, with old platform billing/request-id/replayed additions removed and their existing 24-hour expiry unchanged. Previously synthesized warnings/rounding cannot be reliably undone. Back up application data before routine deployment changes; do not clear the account or credit ledger to apply this contract.

Enable Stripe credit packs

Set STRIPE_SECRET_KEY and STRIPE_WEBHOOK_SECRET using wrangler secret put. Set STRIPE_PUBLIC_KEY to the corresponding publishable key in the payment configuration. Use a consistent Stripe mode for all keys and webhook endpoints.

Register the webhook URL https://YOUR_MAIN_ORIGIN/api/payment/webhook/stripe for checkout.session.completed and checkout.session.async_payment_succeeded. Use that endpoint’s signing secret. The handler validates the signed event and the server-owned credit order; browser redirects cannot grant credits.

config/plans.ts defines Starter, Builder, and Scale as one-time USD credit packs. The integration creates inline Stripe price data from those plans; it does not require invented Stripe price-ID environment variables. Test checkout and signed fulfillment in Stripe test mode before accepting live payments. This documentation does not imply that real Stripe purchases have been tested on your deployment.

Build, check, and deploy the main app

npx --yes pnpm@9.4.0 typecheck:tanstack
npx --yes pnpm@9.4.0 build:tanstack
npx --yes pnpm@9.4.0 deploy:check
npx --yes pnpm@9.4.0 deploy

deploy:check builds the Cloudflare target and performs a Wrangler dry run. deploy publishes the main Worker. Local production preview is available through pnpm preview. These commands do not prove real provider credentials, email delivery, payment fulfillment, or decision quality.

The final build reported 39,422.77 KiB uncompressed and 7,350.28 KiB gzip for the main Worker on September 18, 2026. Check Wrangler’s uncompressed Total Upload against your account’s enforced limits. The official Worker size rules, checked on that date, specify 64 MiB uncompressed for both Free and Paid, with no compressed limit. The gzip value alone does not establish whether a paid plan is required; CPU and other quotas still matter.

Those figures are a historical build measurement, not a measurement of the current compatibility changes.

After deployment, verify /health, /v1/models using a platform Bearer key, registration/email verification, key creation/revocation, both client paths, editable Playground models, usage, replay headers and signed payment fulfillment. Run offline native-contract/D1 tests before rollout; they compare actual fetch arguments and same-call response text. pnpm test:contract:live is a separately invoked, billable check, not part of building these docs. It compares one call's actual upstream text to the gateway response, not numerical equality between independent model evaluations. A real inference consumes provider usage and platform credits.

Deploy the documentation separately

The docs app exports all English and Chinese pages and a static search index to apps/docs-app/out. It uses system fonts and needs no runtime database or secrets. Set the public build-time SYSTEM_ONE_DOCS_URL to your documentation origin so canonical URLs and social metadata use the correct domain.

npx --yes pnpm@9.4.0 --filter @system-one/docs typecheck
npx --yes pnpm@9.4.0 build:docs
npx --yes pnpm@9.4.0 --filter @system-one/web exec wrangler deploy --config ../docs-app/wrangler.jsonc --dry-run
npx --yes pnpm@9.4.0 --filter @system-one/web exec wrangler deploy --config ../docs-app/wrangler.jsonc

The docs config names the Worker system-one-docs, serves the out directory as static assets, and uses the exported 404 page for unknown paths. Preview locally with:

npx --yes pnpm@9.4.0 --filter @system-one/web exec wrangler dev --config ../docs-app/wrangler.jsonc --port 3001

Do not run next start for this static export. A documentation-only preview does not provide /v1/systemone. Keep the main Worker’s SYSTEM_ONE_DOCS_URL pointing to the published documentation after assigning custom domains.

The repository operator guide is docs/deployment.md. Framework details: Cloudflare static assets, D1 migrations, and Next.js static export.

Data handling

Where requests go, what this service stores, and how retention works.

On this page

ArchitectureRun locallyCreate and migrate production D1Configure the main WorkerSelect the upstreamCompatibility upgradeEnable Stripe credit packsBuild, check, and deploy the main appDeploy the documentation separately