Skip to content

Local development

Terminal window
bun run dev

vite dev runs your theme in workerd via @cloudflare/vite-plugin — the same runtime that serves it in production, with hot reload. What works locally works deployed.

Your loaders talk to a real Storefront API. The scaffolder writes the connection into .dev.vars (gitignored); if you skipped that step, copy the example and fill it in:

Terminal window
cp .dev.vars.example .dev.vars

The variables that matter day to day:

Variable Purpose
STOREFRONT_API_ENDPOINT Your shop’s Storefront API URL
STOREFRONT_API_TOKEN A workspace API key for local reads
KOTAO_SHOP_ID / KOTAO_SITE_ID The shop / storefront site your data comes from

Write queries as #graphql documents (see app/graphql/queries.ts), then generate types from your Storefront API:

Terminal window
bun run codegen

This introspects $STOREFRONT_API_ENDPOINT (or a local SDL file via --schema) and emits app/graphql/storefrontapi.generated.d.ts.

Themes run as untrusted Workers in production. Keep these in mind — they are the things that work in a naive local setup but fail deployed:

  • No request.cf — geo data arrives as the typed context.geo instead.
  • No eval / new Function.
  • No shared cache or advancing wall clock within a request — don’t build logic on either.

kotao storefront dev reproduces these constraints locally when you want to verify against them.