Skip to content
Back to skills

New Game Scaffold

ASecurity

Starts a new game by script - contracts/games.json entry, catalog keys, a white-label app when multi-package - and proves it complete. Use when adding or starting a new game or checking one is complete. Not for rules (game-rules-engine).

  • 3 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added October 18, 2026
developmenttypescriptgoreactnodetestinggit

Security analysis

A92/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro scans all 19 files and shows the line behind each finding

Scanned October 18, 2026

npx -y skills add zakariaf/ReactNative-Skills --skill new-game-scaffold --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of New Game Scaffold?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for New Game Scaffold
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/zakariaf-new-game-scaffold/badge)](https://www.skillsdirectory.com/skills/zakariaf-new-game-scaffold)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: new-game-scaffold
description: Starts a new game by script - contracts/games.json entry, catalog keys, a white-label app when multi-package - and proves it complete. Use when adding or starting a new game or checking one is complete. Not for rules (game-rules-engine).
---

# New game scaffold

Turns "the next game is chosen" into a declared, named, translated starting point written by a script,
then walks the game through the build order of the games skills and proves, with a second script, that
the finished game has every part, agrees with its declaration and (when it is its own white-label app)
carries no placeholder a store would see. The game lives in `src/games/<game-id>/` of the one Expo
app; when multi-package, one game can also be one app in `apps/<game-id>/`.

## Rules that must hold

1. **Start every game with `scaffold-game.mjs`, never by copying another game's folder.** Why: a copied
   game keeps the other game's ids, catalog keys, saved-run namespace and settings in corners; the
   script fills every id form from one id and never overwrites a file.
2. **The game id is kebab-case, starts with a letter, and never changes after release; every
   identifier derives from it by one rule** (folder, `identity.id`, catalog namespace `<id>.`, saved
   runs, `<Pascal>` types, `<CONST>_` constants). Why: the id is inside every saved run on every
   device, and a leading digit is not a valid Android package part.
3. **The game's design notes are data in `contracts/games.json`, and the code must agree with them:**
   class, pan mode, levels and pack layout, daily, endless, hints, continue, every way of losing. Hints
   and continue have no default; a daily-only or endless-only game declares `levels: null` (its
   `contracts/levels.json` entry has `packCount` 0). Why: a declaration that promises a hint or a
   continue the rules lack ships a dead button; the complete check loads the module and compares it
   with the entry, and holds `contracts/levels.json` (level-generation-and-solvers) to the same pack
   layout.
4. **Every catalog of the app carries the game's keys:** `<id>.name`, one `<id>.lose.<reason>` per
   declared way of losing and every `<id>.*` key the game's code names, the same keys in every locale,
   no empty text; approved copy (`contracts/copy-source.json`) wins and retired keys are gone. Why: a
   missing key is a broken screen in one language, found by a player.
5. **Never overwrite.** `--write` writes nothing when any value conflicts; a game or app that exists is
   completed with `--add-missing`, which adds absent files, keys and entries and never changes a value.
   Why: an existing game holds decisions nobody wants silently reset.
6. **No template placeholder is left** (`__GAME_ID__`, `__GAME_PASCAL__`, `__GAME_CAMEL__`,
   `__GAME_CONST__`, any `__UPPER_SNAKE__`) in the game folder or its app, nor in the game's sims,
   board golden and E2E flows; generated native folders, build output and Pods are never scanned. Why: a placeholder compiles in a string and ships.
7. **Build the parts in the documented order, each with its own skill, and finish with
   `check-game-scaffold.mjs . --game <id> --stage complete`.** It never skips: every part, the
   evidence (sims, a pixel golden, an E2E flow), the hosted binding `<id>-hosted.ts` registered as
   `createGameHost(<CONST>_HOSTED, ...)` in `<gamesDir>/game-registry.ts`, the declared ways of losing
   and, for a white-label app, its real root and entry (polyfills, then `expo-router/entry`) instead of
   the placeholder entry. Why: nobody reads every file of a game; the gate proves nothing is missing and names the
   skill for each missing part.
8. **The game module loads headless** (pure TypeScript through `<id>-game.ts`). Why: bots, solvers,
   goldens and this check run it in Node; a React Native import in its graph breaks all of them.
9. **`npm run new-game` and the skill write identical bytes** (`scripts/games/new-game.ts` forwards to
   the installed generator); a declared `new-game` script runs a file that exists. Why: two generators
   drift.
10. **When multi-package, every white-label app lists the same dependency set at the same versions.**
    Why: native modules autolink per app and `expo install --check` sees only the app's own list; a
    drift crashes at launch or compiles two copies of one native module.
11. **When multi-package, an app's config is one composer statement, its per-app values live in
    `app-settings.ts` (read only by `app.config.ts`, never `null`), its native folders are ignored
    anchored, its Metro cache is keyed on `EXPO_PUBLIC_*`, and its fonts are byte-for-byte copies.**
    Why: native settings come only from the composer and plugins; `null` reached the device as `{}`;
    an unkeyed cache shipped development transforms in a production export (verified on SDK 57).
12. **When multi-package, store ids derive from one prefix and account-bound values stay documented
    placeholders until a human supplies them;** the complete stage fails `ship-placeholder` on each by
    name, and no option turns one into a pass. Why: a placeholder bundle id, privacy link or sample ad
    id in a store build is a rejected review or ads nobody is paid for.

## Workflow

1. **Design notes first.** Read [references/new-game-checklist.md](references/new-game-checklist.md)
   ("Before code"). Agree with the developer: the id ([references/ids-and-names.md](references/ids-and-names.md)),
   the name, class, pan mode, levels and packs, daily, endless, hints, continue, the ways of losing.
   Ask for hints and continue; never assume them.
2. **Plan the start:** `node ${CLAUDE_SKILL_DIR}/scripts/scaffold-game.mjs . --game <id> --name "<Name>"
   --hints none|solver --continue none|once [--levels 3x30] [--daily] [--endless] [--pan-mode swipe]
   [--class realtime] [--lose-reason <slug>]...` Read the plan (compare
   [examples/lights-out/scaffold-plan.txt](examples/lights-out/scaffold-plan.txt)). A `conflict` means
   the game exists: use `--add-missing`. When multi-package and the game is its own app, add `--app`
   after reading [references/white-label-apps.md](references/white-label-apps.md); a `deps-lockstep`
   failure is fixed first with dependency-management.
3. **Write it:** the same command with `--write` (white-label: then `npm install`). Once per repo,
   copy `templates/scripts/games/` and add `"new-game": "node scripts/games/new-game.ts"` to
   `package.json`.
4. **Check the start:** `node ${CLAUDE_SKILL_DIR}/scripts/check-game-scaffold.mjs . --game <id>` until
   `RESULT: PASS`; for a white-label app also `npx expo config --json` in `apps/<id>` per variant,
   `npx tsc --noEmit -p apps/<id>` and `npx eslint --max-warnings 0 apps/<id>`. Commit on its own.
5. **Build the game in order** (the table in the checklist): kit and rules (game-rules-engine, using
   the placeholder table the scaffold printed), real-time sim (realtime-game-loop), bot sims
   (game-balance-and-bots), levels (level-generation-and-solvers), canvas surface and golden
   (skia-canvas-rendering), intent function (canvas-gestures-and-hit-testing), the module, texts
   (i18n-strings-and-catalogs), the hosted binding and its registry factory (game-session-host),
   how-to-play, sounds and haptics (optional), for a white-label app its icon and splash
   (icons-app-icon-and-splash) and root (app-startup-and-bootstrap), the E2E flow on a named iOS
   simulator and a named Android emulator (e2e-maestro), screen parity (design-visual-parity). Each
   step test-first with its own check.
6. **Prove it complete:** `node ${CLAUDE_SKILL_DIR}/scripts/check-game-scaffold.mjs . --game <id> --stage complete`;
   fix every line ([references/checker.md](references/checker.md)) and rerun until `RESULT: PASS`,
   then `npm run verify`. A white-label app before the human steps ends with exactly its
   `ship-placeholder` lines: that is the finished state before those steps, never a pass.
7. **Report and hand over:** what a player can now do, the open human steps with the placeholder each
   replaces (one message shaped like [examples/developer-request.md](examples/developer-request.md)),
   the non-blocking ones (play-test, native review), what could not be verified without a device.
   Uploads and store-console changes are outward-facing: stop and ask first.

## Definition of done

- [ ] The game was started by `scaffold-game.mjs` with its real hints and continue, and its entry in
      `contracts/games.json` says what the rules do.
- [ ] `check-game-scaffold.mjs . --game <id>` passed before any game code was written.
- [ ] Every part exists and was built test-first by its skill; `npm run verify` is green.
- [ ] White-label: the app type-checks, lints and `npx expo config --json` works for every variant;
      the open placeholders are listed in the report as human steps.
- [ ] `node ${CLAUDE_SKILL_DIR}/scripts/check-game-scaffold.mjs . --game <id> --stage complete` prints `RESULT: PASS`
      (white-label before the human steps: only `ship-placeholder` lines, reported as open steps).

The scaffold stage may print `SKIP src/i18n/catalogs [catalog-missing-key] not yet created
(i18n-strings-and-catalogs creates it)` in an app without catalogs; an app with no game prints
`NOT APPLICABLE: the app has no game (...)`. The complete stage never skips.

## Anti-patterns

- **`cp -R src/games/<other> src/games/<new>` and search-and-replace.** Old ids, keys and tuning
  survive; scaffold, then copy the rules template with the printed placeholder table.
- **Declaring `hints: solver` or `continue: once` "for later".** The complete check fails the mismatch;
  declare what the rules do today and change both together.
- **Renaming a game id after release.** Every saved run and statistic is keyed on it; keep the id and
  change only the display name.
- **Moving files aside so `--write` works.** Use `--add-missing`; it lists what it keeps.
- **A lose reason only in code** (`'<id>.lose.board-full'` with no declaration and no catalog text).
  Declare it, then add its text to every catalog.
- **Importing a screen, a store or `react-native` into `<id>-game.ts`.** The module stops loading
  headless; the session host attaches the surface.
- **Treating the scaffold stage as done.** It proves the start only; the game is done at
  `--stage complete`.
- **White-label: installing a package in one app only, editing `ios/` or `android/`, importing
  `app-settings.ts` from app code, or writing `null` into it.** Install in every app; change the
  composer or a plugin; read `expo.extra` through the typed reader; leave the key out.
- **White-label: inventing a real-looking ad id or privacy link "for now", or calling the
  `ship-placeholder` lines a pass.** Keep the documented placeholders; report them as open steps.

## Files in this skill

| File | What it is | Read/run when |
|---|---|---|
| [references/new-game-checklist.md](references/new-game-checklist.md) | Design notes, step 0, the build order with skills and proofs, proving completion, human steps, release | Workflow steps 1, 5 and 6 |
| [references/ids-and-names.md](references/ids-and-names.md) | The id and its four forms, identifiers inside and outside the game, store ids | Step 1 |
| [references/white-label-apps.md](references/white-label-apps.md) | When multi-package: the apps block, every skeleton file and why, lockstep, store ids and placeholders | Step 2 with `--app`, or when an app rule fails |
| [references/checker.md](references/checker.md) | Both scripts: options, config keys, every rule with its fix, SKIP and NOT APPLICABLE, troubleshooting | Steps 4 and 6 |
| `templates/contracts/games.json` | The declaration file with no game yet; the generator starts a new one from it | Step 3 (the generator writes it) |
| `templates/contracts/games.schema.json` | The declaration's JSON schema, every field explained | When editing an entry by hand |
| `templates/scripts/games/` | `new-game.ts` (the npm script), `find-generator.ts` and its test | Step 3, once per repo |
| [examples/lights-out/scaffold-plan.txt](examples/lights-out/scaffold-plan.txt) | A real dry run for Lights Out (levels, a daily, one way of losing) | Step 2 |
| [examples/lights-out/games.json](examples/lights-out/games.json) | The declaration that run writes | Step 2 |
| [examples/white-label/games.json](examples/white-label/games.json) | A white-label declaration: the apps block and a real-time game with an endless run | Step 2 with `--app` |
| [examples/white-label/app-settings.ts](examples/white-label/app-settings.ts) | The settings file the generator writes for that app, placeholders included | Step 2 with `--app` |
| [examples/developer-request.md](examples/developer-request.md) | The one message asking for the human-only steps, each with its default | Steps 1 and 7 |
| `scripts/scaffold-game.mjs` | Generator: plan (default), `--write`, `--add-missing`, `--app`; never changes an existing value | Steps 2 and 3 |
| `scripts/check-game-scaffold.mjs` | Checker: `--stage scaffold` (default) and `--stage complete` | Steps 4 and 6, and at the end |
| `scripts/lib/` | `games-contract.mjs` (id, layout, declaration), `game-catalogs.mjs`, `json-text.mjs`, `scaffold-plan.mjs`, `app-skeleton.mjs` (the white-label renderer), `game-checks.mjs`, `app-checks.mjs`; `app-modules.mjs` and `ship-placeholders.mjs` are synced (do not edit here) | When changing a script |
| `scripts/selftest.mjs` | Proves both scripts on the fixtures, building each base with the generator itself | After changing a script or a template |
| `scripts/check-lib.mjs` | Shared script library, synced (do not edit here) | Never by hand |
| `assets/shared.json` | Declares the synced files | When adding a shared file |
| `tests/bases/` | `app/` (a small app), `monorepo/` (white-label: an existing app, shared fonts, the apps block), `complete-game/` (loadable stand-ins of every part of a finished game) | When a base changes |
| `tests/fixtures/` | `scaffold-game/`, `scaffold-game-app/`, `check-game-scaffold/`, `check-game-complete/`, `check-game-app/`, `check-game-app-complete/`: good, pass-*, bad-* (one per rule) and error-* cases; `check-example-lights-out/` and `check-example-white-label/` hold the examples to the checker | When adding a rule or changing an example |

## Related skills

- `game-rules-engine` - the kit, the rules, the bot and the module the scaffold's id names.
- `level-generation-and-solvers` - solvers, packs and the daily level the declaration announces.
- `game-balance-and-bots` - the bot simulations the complete stage requires.
- `realtime-game-loop` - the `sim/` and the `<id>-realtime.ts` spec of a real-time game.
- `skia-canvas-rendering` and `canvas-gestures-and-hit-testing` - the surface, its golden and the intent function.
- `game-session-host` - the hosted binding `<id>-hosted.ts` and its factory in `game-registry.ts`.
- `i18n-strings-and-catalogs` - writing and translating the game's texts; the approved copy.
- `e2e-maestro` - the game's flow on iOS and Android.
- `dependency-management` - lockstep installs across white-label apps.
- `app-variants-and-environment` - the single app's identity, variants and Metro cache key.
- `app-startup-and-bootstrap` - a white-label app's root layout, which replaces the placeholder entry.
- `icons-app-icon-and-splash`, `audio-and-haptics-feedback`, `design-visual-parity` - per-app icon and splash, game feedback, screen parity.
- `privacy-and-store-declarations` - audits, the privacy answers, age rating and app-ads.txt.
- `ios-release-testflight`, `android-release-play`, `eas-build-and-submit` - shipping once the human steps are done.

Files in this skill

  • SKILL.md15.3 KB
  • assets/shared.json249 B
  • examples/developer-request.md2.5 KB
  • examples/lights-out/games.json637 B
  • examples/lights-out/scaffold-plan.txt1.5 KB
  • examples/white-label/app-settings.ts1.3 KB
  • examples/white-label/games.json840 B
  • references/checker.md12.2 KB
  • references/ids-and-names.md5.3 KB
  • references/new-game-checklist.md10.8 KB
  • references/white-label-apps.md10.4 KB
  • scripts/check-game-scaffold.mjs10.2 KB
  • scripts/lib/app-checks.mjs16.5 KB
  • scripts/lib/app-modules.mjs8.7 KB
  • scripts/lib/app-skeleton.mjs9 KB
  • scripts/lib/game-catalogs.mjs4 KB
  • scripts/lib/game-checks.mjs30.9 KB
  • scripts/lib/games-contract.mjs13.2 KB
  • scripts/lib/json-text.mjs1.8 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.