The web front-end for GScan — the Ghost theme validator that powers https://gscan.ghost.org — running on Cloudflare Workers.
It is a thin presentation layer: it imports the published gscan library and
calls its filesystem-free checkBuffer() entry point so theme validation runs
entirely in memory, with no temp files (Workers have no filesystem).
POST / (multipart: theme=<zip>, version=v6)
→ request.formData() → file.arrayBuffer()
→ gscan.checkBuffer(buffer, {checkVersion}) // unzips in-memory via fflate
→ gscan.format(theme, {checkVersion})
→ render the result template
src/index.js— the Workerfetchhandler (routesGET /andPOST /).src/render.js— renders Handlebars templates into the layout.src/templates/— the page/partial templates (ported from the old Express app).public/— static assets (CSS, JS, favicons, logos), served by Wrangler.scripts/precompile.mjs— precompiles templates at build time (see below).
Cloudflare Workers disallow runtime code generation (eval / new Function),
which Handlebars.compile() relies on. So templates are precompiled to runtime
specs by scripts/precompile.mjs (run automatically via the build hook in
wrangler.jsonc), and the Worker uses the eval-free handlebars/runtime.
This app depends on a build of gscan that exposes the in-memory entry point
(gscan/lib/memory → checkFiles, checkBuffer, format, versions). That
currently lives on the decouple-web-app-phase1 branch.
- Local development uses a symlink to a sibling checkout:
"gscan": "file:../gscan"
- For deployment, pin to a commit on the branch (or, once published, a
normal semver range):
"gscan": "github:TryGhost/gscan#<commit-sha>"
npm install
npm run dev # wrangler dev — http://localhost:8787npm run build # wrangler deploy --dry-run (bundles, no deploy)
npm run deploy # wrangler deploy (requires a Cloudflare account/login)- Error reporting: the old Express app used
@sentry/node. If we want error reporting here, add@sentry/cloudflare(the Workers-compatible SDK). - Ghost version list: the old app fetched the live latest Ghost version via
npm show ghost version. This app uses the version list bundled with gscan (versions), which avoids a network/child-process call at request time. - Upload size: capped at 15MB in
src/index.js; Cloudflare also enforces a per-plan request body limit.