ArcadeBloom is an outbound-link game directory — we introduce niche browser games, including AI games and link to each author's own site. We do not host third-party games. Every catalogue entry must have a verifiable source (author, play URL, licence). See CONTEXT.md and docs/adr/ for the positioning decisions.
src/is the Eleventy source.src/_data/holds the catalogue (games.js,tags.js,site.js);src/_includes/holds Nunjucks layout fragments;src/*.njkare page templates..eleventy.jsconfigures the build: Nunjucks templates, custom filters (whereEq,sortByDateDesc,paragraphs,toJSON, etc.), thepopulatedTagscollection, and clean-URL output.dist/is the build output (gitignored). Deploy this directory.scripts/holds the data pipeline:fetch-js13k.js+build-catalogue.js(js13k import),fetch-leereilly.js+merge-leereilly.js(open-source browser games),write-games-js.js(regenerategames.js), andvalidate-data.js(schema checks).docs/adr/records architectural decisions.CONTEXT.mdis the domain glossary. Both are authoritative — read them before non-trivial changes.- Legacy files (
games/,index.htmlat root,game-detail.html,js/,games-data.js,all-games.html, etc.) are retired and scheduled for deletion after the cutover. Do not edit them.
npm install— install dependencies.npm run serve— build CSS + Eleventy dev server with live reload.npm run build— runsvalidate:strictfirst, then clean + CSS + screenshots + Eleventy renders todist/.npm run build:css— compile Tailwind only (JIT scanssrc/**/*.njkpertailwind.config.js).npm run validate— audit mode: schema checks (slug uniqueness, category/tags in controlled vocab, required fields, no legacyplays/rating/gameUrl) plus advisory warnings. Must pass before commit.npm run validate:strict— strict mode: structural warnings (duplicate URLs, missing gameplay tags,licenceStatus/sourceKeypresence+consistency, id monotonicity) escalate to blocking errors. This is the gate bot-generated PRs are held to; the CI workflow (.github/workflows/ci.yml) runs it on every PR. Content-quality warnings (word count, placeholder wording) stay advisory in both modes.npm test— rebuild + run Playwright smoke tests againstdist/(served byhttp-server).
CSS is not loaded from the Tailwind CDN — it is compiled at build time into /css/styles.css (16KB minified). Editing styles means changing src/styles/styles.css (Tailwind directives + custom design tokens) and rebuilding; do not re-introduce <script src="cdn.tailwindcss.com"> (it causes FOUC and a production warning).
Local preview without Eleventy: serve dist/ after building — npx http-server dist -p 4173.
- Four-space indentation in HTML/JS; Tailwind utility classes grouped semantically (layout → color → effects).
- Kebab-case for slugs, file names, and tag references. A game's
slugequals its URL fragment (/game/<slug>/). - Metadata: titles in Title Case, descriptions in sentence case, tags from the controlled vocabulary only (never free-text).
id, slug, name, category, tagline, about, howToPlay, keyFeatures[],
screenshots[], sourceName, sourceUrl, licence, tags[], addedDate, releaseDate, featured
Removed vs legacy: plays, rating, image, gameUrl (fabricated data / self-hosting fields — per ADR-0001, never re-introduce).
- Append to
src/_data/games.js(or run the import scripts for bulk sources). - Fill every schema field.
category∈ the 6 insite.js;tags∈ the controlled vocab intags.js;sourceUrlis always an outbound link. Every game needs a uniquesourceKey(upstream identity, e.g.github:owner/repo). - Run
npm run validate— zero errors required. - For AI games, include
ai.types(ai-gameplayand/orai-assisted),ai.note,ai.sourceUrl(creator disclosure) andai.checkedDate. Do not infer AI use. No gameplay assessment or review-registry registration is required. - Run
npm run build— the detail page, sitemap, and tag pages regenerate automatically. - Thin-content guards: categories need ≥20 games to appear in the nav; tags need ≥8 games to generate a page.
directory-policy.js controls game robots, sitemap, RSS and Collections using attribution, official outbound URLs and concise non-placeholder descriptions (tagline >=5 words, about >=30, howToPlay >=10). directoryStatus: draft|unlisted is noindex; omitted means listed. Strict schema and duplicate validation remain required. Historical evidence, manifests and review registry are archival and grant no indexing entitlement. The AI landing page is noindex until eight content-qualified AI games exist. See ADR-0011, which supersedes ADR-0004/0006/0010 and amends ADR-0008.
npm run validate+npm testmust pass before commit. The smoke suite checks: no console errors, outbound CTAs carryrel="noopener nofollow", content visible without JS, no legacy iframe/fake-data artifacts, and SEO essentials (canonical, JSON-LD, sitemap, noindex on/search/).- Store Playwright HTML reports under
test-results/html-report/date-stamped when running full sweeps.
- Short imperative subject lines under 50 chars; prefer English unless the change is language-specific.
- PR body must list touched pages/games and explicitly call out any
games-data.js/games.jscatalogue changes for metadata review. - For UI changes, attach before/after screenshots.
- Target: Cloudflare Pages, deploying
dist/from themainbranch. - Build command:
npm run build. Output directory:dist. - Pages Functions under
functions/return 410 Gone for retired legacy URLs. Generateddist/_redirectshandles 301 mappings for moved pages and catalogue slugs. - Clean URLs work by default: Cloudflare Pages resolves
/game/<slug>/to/game/<slug>/index.html.
Issues live as GitHub issues; use the gh CLI. See docs/agents/issue-tracker.md.
Five canonical roles map 1:1 to GitHub labels. See docs/agents/triage-labels.md.
Single-context — CONTEXT.md and docs/adr/ at the repo root. See docs/agents/domain.md.