3U

Dev & Publish

Run a theme locally in preview mode, then publish it for review.

Local Development

Run the theme with its own dev server. Because the review sandbox renders your theme where the ThreeU API is unreachable, every theme needs a preview (demo) mode: when there is no public token / real brand, hand <ThemeProvider> a demo brand and a demo storefront client. The data hooks call useStorefront(), which throws without a client — a plain "no data" fallback is not enough.

Dev
Shell
# .env.local
VITE_THREEU_PREVIEW=true

# terminal
npm run dev

Preview Mode Skeleton

A duck-typed demo client only needs the methods the hooks call — catalog.list/get/getBySlug, collections.list, delivery.methods/quote, payments.methods, coupons.validate, leads.create, bookings.create, content.faqs/blogPost, and top-level checkout(). createMockFetch from threeu-sdk/testing can back a real ThreeuStorefront instead.

ThemeRoot.jsx
TSX
import { ThemeProvider } from "threeu-sdk/theme";
import { demoBrand, demoStorefront } from "./demo";

const preview = import.meta.env.VITE_THREEU_PREVIEW === "true";

export function ThemeRoot({ children }) {
  return preview
    ? <ThemeProvider brand={demoBrand} storefront={demoStorefront} preview>{children}</ThemeProvider>
    : <ThemeProvider brand={brand} storefront={storefront}>{children}</ThemeProvider>;
}

Publishing

Publishing uploads a bundle and creates a submission that ThreeU reviews. It does not make the theme live.

Publish
Shell
npm run build                                   # → preview-dist/index.html
TOKEN=$(grep '^THREEU_DEVELOPER_TOKEN=' .env.threeu | cut -d= -f2-)
export THREEU_DEVELOPER_TOKEN="$TOKEN"
npx threeu publish --dry-run                     # validate + bundle, no upload
npx threeu publish

What the CLI Does

  1. Detects the project from threeu.json (kind, key, name, version, manifest).
  2. Bundles a tar.gz — excludes node_modules, dist, .git, .env* and other generated/sensitive files; includes `preview-dist/`. Cap: 50 MB after exclusions.
  3. POST /api/developer/publish/init — checks the account is active, the key is not owned by another developer, and your per-account project limit; returns a presigned upload URL (15 min).
  4. Uploads the bundle to ThreeU's private bucket.
  5. POST /api/developer/publish/{id}/complete — verifies the object and size, sets the submission to uploaded, queues review.

Submission lifecycle: pending_uploaduploadedapproved | rejected. Approved themes are then integrated into the storefront by ThreeU (see [Publishing Themes](/docs/themes-publishing)).

Verify a Submission

Find your submission by kind + project_key; status uploaded means it is in the review queue. Each publish creates a new submission — to fix a failed check, correct the project and publish again.

List submissions
Shell
curl -s -H "Authorization: Bearer $TOKEN" https://api.threeu.app/api/developer/submissions

Token Safety

  • Name the secret file `.env.threeu`, not .threeu.env — the bundler excludes .env*, so a file starting with .threeu would be uploaded with your token.
  • The token contains a |. Do not source the env file (the shell reads | as a pipe); read it with grep … | cut -d= -f2- as above.
  • After a dry run, prove the bundle is clean: tar tzf <bundle> | grep -iE '\.env|token' must print nothing.
  • Validate the token before publishing: GET https://api.threeu.app/api/developer/me with the bearer token → 200. Sandbox uses a separate database — a production token returns 401 there.

Never commit the token

If a token ever lands in a bundle or a commit, rotate it in the Developer Console.