Host your own

gamecn-registry build produces a regular static site. Any HTTP host that serves files works.

Build

npx gamecn-registry build \
  --src registry \
  --out dist \
  --name your-registry-name \
  --homepage https://your-registry.example.com \
  --base-url https://your-registry.example.com

--base-url is the deployed URL of your registry. It's stamped into every emitted manifest as the prefix for binary asset URLs:

{
  "files": [
    {
      "url": "https://your-registry.example.com/assets/abc123...",
      "integrity": "sha256-..."
    }
  ]
}

If you forget --base-url, the builder emits relative paths (/assets/abc123...) which work for local testing but break under any non-root deploy.

Output structure

dist/
  registry.json           # index of all items
  r/
    <item-name>.json      # full manifests (text inlined, binaries by URL)
  assets/
    <sha256>              # content-addressed binary assets
  previews/
    <item-name>.png       # preview thumbnails (if you ship them)
  schema/
    *.json                # JSON Schema files (if you pass --schema-dir)

Cloudflare Pages

# build
npx gamecn-registry build --src registry --out dist --base-url https://your-registry.pages.dev

# deploy
npx wrangler pages deploy dist

Free tier handles >75k requests/day, more than enough for any registry under 100 items.

Vercel

npx vercel deploy dist --prod

Same shape. The static site has no server functions, so deploy is instant.

CDN cache headers

Two distinct caching strategies based on content type:

Path Header Reason
registry.json, r/*.json Cache-Control: public, max-age=300, stale-while-revalidate=86400 Manifests change with each item version bump; ETags handle revalidation.
assets/* Cache-Control: public, max-age=31536000, immutable Content-addressed by sha256 — the bytes will never change.

Cloudflare Pages and Vercel both let you set these via configuration files (_headers and vercel.json respectively).

DNS / custom domains

Once deployed, point your domain at the host's URL. Then:

  1. Update --base-url to the new domain
  2. Rebuild
  3. Redeploy

Users referencing your registry by domain don't need to update anything; the manifest URLs change but their gamecn.json#registries config keeps pointing at the same {name} template.

Hosting @main

If you're forking the official registry to ship your own version, the recommended pattern is to:

  1. Pick a clear namespace (@your-org, not @main).
  2. Document it in your registry's README.
  3. Tell consumers to add it to gamecn.json:
    {
      "registries": {
        "@your-org": "https://your-registry.example.com/r/{name}.json"
      }
    }

This avoids confusion with the official @main and gives users a clear mental model.

Going live without a domain

For early-stage registries, a GitHub repo with the build output committed to a dist/ branch (or via GitHub Pages) works fine. Users can install directly:

gamecn add gh:your-org/your-registry/dist/r/foo.json#v1.0.0

Tag your releases so consumers can pin versions reliably.