Repository navigation
EN Create Build And Release
Français · Type: how-to · Audience: author · Context: engine repository, created project · Status: ready · Applies from: 4.2.5
npm run build turns a game into a static folder, dist/, that any web host can serve: the game, its assets, its
service worker and its licences. A release build adds the gates a game must pass before people play it: provenance
locked, budgets, translations, voices, playtests and the exhaustive proof. This page says what each command checks, in
which folder it runs, and what to look at before you send the link.
A dist/ folder, checked file by file, ready to upload: an installable web app (PWA) that plays offline after the
first visit, whose every file is accounted for with its licence under dist/licenses/.
The same game builds in two places, with different commands:
Created project (quest-n-click create) |
Engine repository (games/<id>/) |
|
|---|---|---|
| Everyday build | npm run build |
npm run build |
| Release build | npm run release |
npm run verify:release after npm run build
|
| Release that may be sold | npm run release -- --commercial |
npm run verify:commercial |
| Exhaustive proof | inside npm run release
|
npm run prove:game |
| Sealed ending | not available (seal is not a quest-n-click command) |
npm run seal, npm run check:spoilers
|
Serve dist/
|
npm run preview (local only) |
npm run preview, or npm start (any interface, $PORT) |
The page applies from 4.2.5, when the command became quest-n-click (before, web-scumm). The created project and
its build and release commands exist since 3.9.0; npm start is a Node launcher since 4.1.8.
- Node 22.12 or later, the project installed (
npm installin a created project,npm ciin the engine repository). See Requirements. - Python 3 with the packages of
requirements.txt(Pillow first):npm run assetsturnsart/andaudio/intopublic/assets, and a created project'sbuildruns it every time. In a created project the file isnode_modules/quest-n-click/requirements.txt. - ffmpeg when the game has sounds, music or video to encode, and for a release when the game declares music in stems
(
validate --releasemeasures them with ffprobe). - A game that passes its checks: Checking your game. Building runs them again and stops on the first that fails.
- "In the created project": the folder
quest-n-click createmade, the one withgame/andpackage.json. - "In the engine repository": the clone of
wanoo/quest-n-click. The game built is the oneGAMEnames, else the onenpm run gameselected, elsepackage.json→config.game, elsedemo.
-
Prepare the assets when images or sounds changed.
# in the engine repository (public/assets is committed there: commit what this writes) npm run assetsIn a created project,
public/assetsis not committed (its.gitignorelists it) andnpm run buildrunsassetsitself.
-
Build.
# in the created project npm run buildIt runs, and stops at the first failure:
assets;verify(validate, solve, translations status, lint, playtests); the Vite build intodist/; then the check that every file ofdist/is accounted for.# in the engine repository npm run buildIt runs
check(types, the Node tests) thenbuild:game:verify:game(validate, solve, solve by chapter, variants, translations status, lint, playtests), the Vite build,verify:dist,check:spoilersandaudit:assets.
-
Run the release gates before a public release.
# in the created project npm run release # or: npm run release -- --commercial
releaserunsassets,verifyand the build, then:validate --release(the provenance lock, placeholders, ids),weight --release(what a phone downloads, against the game'sassetBudgets),i18n status,voices check --release,playtests --strict,solve --prove(every reachable state),solve-reality, and with--commercialvalidate --commercial --errors(no exception, no placeholder, no non-commercial licence); last, the check ofdist/.# in the engine repository npm run verify:release # or: npm run verify:commercial npm run prove:game
The template's art is a placeholder: a release refuses it until each file is replaced, reviewed and locked (
npx quest-n-click provenance --lockin a created project,npm run provenance -- --lockin the engine repository). See Asset provenance.
-
Seal the ending, only for a game with a sealed ending, in the engine repository: seal the real outcome, build, commit, then deploy. The whole procedure is in The sealed ending.
# in the engine repository, with games/<id>/private/ending.config.ts filled in npm run seal -- --outcome=<key> npm run build
-
Upload
dist/to a static host (next section), then play the live version.# in the engine repository: plays the deployed game to its ending, in a phone-sized browser node scripts/e2e.mjs https://<your-site>/
scripts/e2e.mjsis in the engine repository only; in a created project, play the live site by hand to the end.
npm run build type-checks (in the engine repository), tests, bundles and audits the output. The result is a PWA:
- the service worker caches the app shell (code, styles, the page, fonts used by the page, the icons) at install;
- images and sounds are cached on first use, and the engine warms in the background the current room, the rooms one exit away and their audio;
- by default (
GameDef.offline: 'full') it then fetches the rest of the game during idle time, so the whole game plays offline after the first visit; withoffline: 'nearby', rooms never visited nor warmed may still need the network. Rooms are never all downloaded up front before the game starts: that keeps the first visit light.
The pause menu tells the player whether the whole game is cached. The details are in Sub-path, cache and service worker.
Every build ends by removing from dist/assets the files that are not this game's and writing dist/licenses/:
the engine's LICENSE, LICENSE-ASSETS, CREDITS.md from the game's provenance, THIRD_PARTY_NOTICES.txt and
assets-manifest.json (each file's path, author, source, licence, SHA-256 and status). The check that follows
refuses any other file in dist/, and a locked file or a notice that is missing.
dist/ is static: any static host serves it.
-
GitHub Pages: a workflow builds with
BASE_PATH=/<repo>/and deploysdist/. For a created project, which has no workflow, copy the one in Publish on GitHub Pages. -
Clever Cloud: a Node application that builds on deploy and serves
dist/; see The static game on Clever Cloud. - Netlify, Cloudflare Pages, nginx, a bucket…: Other static hosts.
Under a sub-path (https://<user>.github.io/<repo>/), build with BASE_PATH=/<repo>/; at the root of a domain, no
BASE_PATH. Every path (scripts, styles, manifest, icons, service worker, the sealed ending's file) follows it:
# in the created project or the engine repository: the same build as Pages, locally
BASE_PATH=/my-repo/ npm run buildWhat goes wrong under a sub-path, with the cache or with a half-uploaded site: Sub-path, cache and service worker, incomplete deploys, going back.
In the engine repository, games/<id>/private/ (photos, raw sheets, the sealed ending's configuration) is never
sent: .gitignore excludes it, and nothing in it is copied into dist/. A created project's .gitignore lists only
node_modules, dist, .cache and public/assets: keep private files outside game/, or add them to it.
Limit ·
release-proof-not-witnessnpm run buildandnpm run verifyask the solver for a witness: one way to an ending. Only the release (npm run releasein a created project,npm run prove:gamein the engine repository) asks for the exhaustive proof, which fails on a softlock or a truncated search. What the solver proves says what each lets you conclude.
Limit ·
accessibility-machine-onlyThe CI checks accessibility as far as a machine can (axe-core on every screen, play by keyboard and by touch). That is not a WCAG conformance claim: a screen reader and real devices are passes a person makes.
- The command ends without error and
dist/holdsindex.html,sw.js,manifest.webmanifest,assets/,icons/,fonts/andlicenses/. -
npm run previewserves it onhttp://127.0.0.1:4173/: play it there before uploading. - After the upload, play the live site to the end on a real phone, in landscape; open the pause menu and wait for "complete" on its "Offline" row before you test offline.
- The last checks before you share the link (a real phone, someone else playing without help, the sealed ending) are in Checking your game.
| Symptom | Cause | Fix |
|---|---|---|
python3 not found, or No module named 'PIL'
|
The asset step needs Python 3 and Pillow |
pip install -r node_modules/quest-n-click/requirements.txt (created project) or pip install -r requirements.txt (engine repository) |
provenance.lock.json › missing: a release ships the files that were reviewed |
No lock yet | Review the assets, then lock them (step 3) |
A placeholder refused by validate --release
|
The template's art is still there | Replace it, or name it in releaseExceptions with a reason (refused by --commercial) |
audio.scores › ffprobe not found |
A release measures the stems | Install ffmpeg, then npx quest-n-click doctor
|
A file of dist/ not accounted for |
A stray file in public/, or an asset not this game's |
Remove it, or declare it (a data file the game names) |
A blank page once online, under /<repo>/
|
Built without BASE_PATH
|
Sub-path |
-
dist/: emptied and rewritten by each build (not committed). -
public/assets/and.cache/refs.json: written byassets(committed in the engine repository, not in a created project). -
games/<id>/data/(engine repository): the sealed ending's file, written byseal. - Nothing in
node_modules/quest-n-click: the engine is read, never written.
A build changes nothing you cannot rebuild: delete dist/ and run it again. To put an earlier version back online,
deploy the build of an earlier commit; what players' caches and saves do then is in
Going back.
-
cli/quest-n-click.mjs: whatbuildandreleaserun in a created project. -
package.json:build,build:game,verify:release,verify:commercial,prove:game,startin the engine repository;scripts/start.mjs. -
tools/dist.ts: whatdist/may hold;tools/validate.ts: the release and commercial gates. -
vite.config.ts: the build and the service worker. - npm scripts, The package.
Generated publication · publication générée — current documentation · documentation courante: quest'n'click 4.4.0 r1, documentation revision · révision de la documentation 8dc717c69acb62c4742b69c54a7e7dfb620f75d8.
Earlier versions and permalinks · versions précédentes et liens permanents: https://wanoo.github.io/quest-n-click/docs/
An edit made in this wiki is overwritten at the next publication · une modification faite dans ce wiki est écrasée à la publication suivante.
Edit the source · Modifier la source · Report an error · Signaler une erreur
Index (6)
Start (6)
Play (9)
Install (17)
- Requirements
- Install from the release archive
- Install from npm, once published
- Install from the repository to work on the engine
- doctor: checking your machine
- Image toolchain
- Audio toolchain: ffmpeg, fluidsynth, Furnace, uv
- Upgrade
- Upgrade notes: 4.4
- Upgrade notes: 4.3
- Upgrade notes: 4.2
- Upgrade notes: 4.1
- Upgrade notes: v3
- Upgrade notes: v2 to v3
- Coming from web-scumm
- Package reference
- Install troubleshooting
Create a game (55)
- Your first game
- Layout of a created project and of the engine repository
- The working loop
- Content principles and the identity contract
- Rooms
- Geometry: placement, walk zones, masks, layers, camera
- Something is visible but unreachable
- Reactions
- Game commands
- Conditions
- Flags, variables and events: which to use
- Custom code
- Characters
- Items and inventory
- World map
- Dialogues
- Scripts and events
- Moving characters: patrols and walks
- Exits
- Chapters and objectives
- State and saves: persistent or temporary, renaming an id, migrations
- Staging: wide rooms and animations
- The stage: lights, particles, floors
- Skin and fonts
- Title and credits
- Heroes: several characters and hero choice
- Built-in minigames
- A custom minigame
- Translations
- Music in stems
- Sound effects
- Voices: per language and per hero
- Images: prompts, cutting sheets, transparency, scale
- Asset provenance
- The storyboard, source of truth
- Puzzle design
- Classic mechanics
- Review pages
- DSL reference
- Checking your game
- What the solver proves
- Solver options
- Playtests
- Remix
- Speedrun for authors
- The sealed ending
- Production template
- Example games
- Working with an AI
- Build and release a game
- Publish on GitHub Pages
- The static game on Clever Cloud
- Other static hosts
- Sub-path, cache and service worker, incomplete deploys, going back
- Testing on a phone over the LAN
Local Studio (24)
- The local Studio: overview and launch
- Edit a room
- Placement and stage
- Preview, apply, undo
- Storyboard
- Assets and cutting
- Check: validator, solver, critical path, heat, health, coverage
- Before and after captures
- Semantic diff
- Play and replay a session
- Rule explainer
- Language and objectives
- Voices and the heroes × languages matrix
- Map
- Notes
- Remix in the Studio
- Music
- The Assistant: bring your own key
- Demo mode and studio-apply
- Local and LAN security
- Studio API
- Local MCP: setting up each client
- MCP tools
- Studio troubleshooting
Team Studio (21)
- What runs where
- Concepts: revision, transaction, span, lease, preview, build
- Starting as an invited dev
- Working together day to day
- Roles and actions: the full matrix
- Invitations
- Managing members
- Write refused on the hosted Studio: stale base revision (409)
- Write refused on the hosted Studio: span locked (423)
- Recovering after a lost lease, a disconnection or a stale preview
- Comments
- Map and semantic diff
- Publishing builds
- Remote MCP
- The game in Git
- Upgrading the engine of a hosted game
- Hosted assets
- The server's command line
- Health and metrics routes
- Trying it locally with compose.yml
- Known limits
Clever Cloud (23)
- Clever Cloud: overview, cost and prerequisites
- Apps and add-ons
- Domains and TLS
- Keycloak
- Generic OIDC and GitLab
- Configuration
- First deployment
- Backups
- RPO and RTO
- Restore the Studio on a fresh installation
- Redeploys
- Upgrading the server and checking state after a migration
- Limits of going back
- Monitoring
- Security
- Rotating keys
- Recovering admin access
- Changing domain or OIDC provider
- Worker, PostgreSQL or Cellar down
- Exporting the game and leaving the installation
- Retention
- Clever Cloud troubleshooting
- Costs and teardown
Reality Bridge and connectors (16)
- The Reality Bridge: what it is
- Quick start
- Guarantees
- Install and run the Bridge
- Backup and restore
- Several tenants
- Signals and the manifest
- The Bridge's command line
- Connectors overview
- Email connector
- Telnet connector
- SSH connector
- Open Badges connector
- The connector SDK
- Security: Biscuit and signatures
- Bridge and connector troubleshooting
Contribute (25)
- Welcome
- Developer setup
- The dev loop
- Before a pull request
- Conventions
- Writing documentation
- Architecture
- Code tour
- Import boundaries
- Which tests run when
- Mutation testing
- The coverage ratchet
- The quality baseline
- CI explained
- Field passes
- Benchmarks
- Releasing
- npm packages
- Decisions and ADRs
- Governance
- Bot pull requests
- Contributing with AI agents
- Security policy
- Code of conduct
- Licences and credits