Skip to content

Commit 968ea16

Browse files
authored
Merge pull request #49 from TMHSDigital/review-fixes
Fixes from the repo review (#1 to #47)
2 parents ed697b2 + 0446265 commit 968ea16

116 files changed

Lines changed: 1660 additions & 413 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.github/ISSUE_TEMPLATE/new-source.yml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ body:
3131
- characters
3232
- audio
3333
- animation
34+
- video
3435
- environment
3536
- shaders-vfx
3637
- fonts

‎.github/PULL_REQUEST_TEMPLATE.md‎

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@
22

33
- [ ] New catalog entry
44
- [ ] License / metadata correction
5+
- [ ] Starter stack
56
- [ ] Docs or site
67

78
## Checklist
89

9-
- [ ] Copied `catalog/TEMPLATE.md` (new entries)
10+
- [ ] Started from `node site/new-entry.mjs <category> <id>` or copied `catalog/TEMPLATE.md` (new entries)
1011
- [ ] `id` is unique across the whole catalog
11-
- [ ] Live license checked today; `active` entries have dated `## Evidence`
12-
- [ ] Bumped `expectedEntryCount` in `site/config.json`
13-
- [ ] `node site/validate.mjs` passes
12+
- [ ] Live license checked today; `## Evidence` has a dated line quoting it
13+
- [ ] Row added to the category `README.md`, with the same licence as the frontmatter
14+
- [ ] Ran `node site/sync-counts.mjs` after adding or removing entries
15+
- [ ] Stacks: followed `stacks/README.md`; no licence named in a stack's own words
16+
- [ ] `npm run check` passes (tests, `node site/validate.mjs`, `node site/build.mjs`)

‎.github/dependabot.yml‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
version: 2
2+
updates:
3+
- package-ecosystem: github-actions
4+
directory: /
5+
schedule:
6+
interval: monthly
7+
commit-message:
8+
prefix: ci

‎.github/workflows/ci.yml‎

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,27 @@
11
name: Validate catalog
22

3+
# No path filters: the build reads catalog/, stacks/, docs/, site/ and the
4+
# top-level Markdown files, and the whole run takes seconds.
35
on:
46
pull_request:
57
push:
68
branches: [main]
7-
paths:
8-
- "catalog/**"
9-
- "docs/**"
10-
- "site/**"
11-
- "README.md"
12-
- ".github/workflows/ci.yml"
9+
workflow_call:
10+
11+
permissions:
12+
contents: read
1313

1414
jobs:
1515
validate:
1616
runs-on: ubuntu-latest
1717
steps:
1818
- name: Checkout
19-
uses: actions/checkout@v4
19+
uses: actions/checkout@v7
2020

2121
- name: Setup Node
22-
uses: actions/setup-node@v4
22+
uses: actions/setup-node@v7
2323
with:
24-
node-version: "20"
24+
node-version-file: .nvmrc
2525

2626
- name: Test catalog checks
2727
run: node site/checks.test.mjs

‎.github/workflows/links.yml‎

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
name: Check source links
2+
3+
# Weekly: fetch every entry's url, and open or update one issue listing dead
4+
# links, sources that moved, and entries whose licence check is over a year
5+
# old. It never edits an entry: each one needs its licence re-read first.
6+
on:
7+
schedule:
8+
- cron: "41 7 * * 1"
9+
workflow_dispatch:
10+
11+
permissions:
12+
contents: read
13+
issues: write
14+
15+
jobs:
16+
links:
17+
runs-on: ubuntu-latest
18+
steps:
19+
- name: Checkout
20+
uses: actions/checkout@v7
21+
22+
- name: Setup Node
23+
uses: actions/setup-node@v7
24+
with:
25+
node-version-file: .nvmrc
26+
27+
- name: Check links
28+
id: check
29+
run: node site/check-links.mjs --report link-report.md
30+
31+
- name: Open or update the report issue
32+
if: steps.check.outputs.problems != '0'
33+
env:
34+
GH_TOKEN: ${{ github.token }}
35+
PROBLEMS: ${{ steps.check.outputs.problems }}
36+
run: |
37+
title="Link check: ${PROBLEMS} sources need a look"
38+
existing=$(gh issue list --state open --label correction --json number,title \
39+
--jq '[.[] | select(.title | startswith("Link check:"))][0].number // empty')
40+
if [ -n "$existing" ]; then
41+
gh issue edit "$existing" --title "$title" --body-file link-report.md
42+
else
43+
gh issue create --title "$title" --label correction --body-file link-report.md
44+
fi

‎.github/workflows/pages.yml‎

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,6 @@ name: Deploy GitHub Pages
33
on:
44
push:
55
branches: [main]
6-
paths:
7-
- "catalog/**"
8-
- "docs/**"
9-
- "site/**"
10-
- ".github/workflows/pages.yml"
116
workflow_dispatch:
127
# Weekly rebuild so the freshness ages never lag the calendar by more than
138
# about a week when nothing is pushed.
@@ -24,30 +19,27 @@ concurrency:
2419
cancel-in-progress: true
2520

2621
jobs:
22+
# The same tests, validation and page checks as a pull request runs.
23+
validate:
24+
uses: ./.github/workflows/ci.yml
25+
2726
build:
27+
needs: validate
2828
runs-on: ubuntu-latest
2929
steps:
3030
- name: Checkout
31-
uses: actions/checkout@v4
31+
uses: actions/checkout@v7
3232

3333
- name: Setup Node
34-
uses: actions/setup-node@v4
34+
uses: actions/setup-node@v7
3535
with:
36-
node-version: "20"
37-
38-
- name: Test catalog checks
39-
run: node site/checks.test.mjs
40-
- name: Test site build modules
41-
run: node site/lib/lib.test.mjs
42-
43-
- name: Validate catalog
44-
run: node site/validate.mjs
36+
node-version-file: .nvmrc
4537

4638
- name: Build site
4739
run: node site/build.mjs
4840

4941
- name: Upload Pages artifact
50-
uses: actions/upload-pages-artifact@v3
42+
uses: actions/upload-pages-artifact@v5
5143
with:
5244
path: site/dist
5345

@@ -60,4 +52,4 @@ jobs:
6052
steps:
6153
- name: Deploy to GitHub Pages
6254
id: deployment
63-
uses: actions/deploy-pages@v4
55+
uses: actions/deploy-pages@v5

‎.gitignore‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ Desktop.ini
1919
.vscode/
2020
.idea/
2121

22+
# Dependencies (the repo has none, but npx and editors may add them)
23+
node_modules/
24+
2225
# Logs / caches
2326
*.log
2427
__pycache__/

‎.nvmrc‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
24

‎CONTRIBUTING.md‎

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,20 +21,16 @@ Please follow the [Code of Conduct](CODE_OF_CONDUCT.md).
2121

2222
## Adding an entry
2323

24-
One new markdown file is enough — the website rebuilds from frontmatter on deploy.
25-
26-
1. Copy [`catalog/TEMPLATE.md`](catalog/TEMPLATE.md).
27-
2. Save it as `catalog/<category>/<id>.md` using a short kebab-case `id`.
28-
3. Fill every frontmatter field. Prefer primary URLs over mirror/aggregator pages.
29-
4. `id` must be unique across the **whole** catalog. A mixed kit already listed in another category is a duplicate, not a second entry.
30-
5. Verify the license on the live source page the day you submit.
31-
6. For `status: active`, include an `## Evidence` line with a short quote from that page.
32-
7. Bump `expectedEntryCount` in [`site/config.json`](site/config.json) by the number of files you added (or lowered if you removed some).
33-
8. Run `node site/validate.mjs` — it must exit 0.
34-
9. Run `node site/build.mjs`. It renders your entry's page and fails if the body uses markdown the site does not support (tables, code fences, blockquotes, images, raw HTML, `###` headings, numbered lists) or links to a file that does not exist.
35-
10. Optional 2D/UI fields: `grid_dimensions`, `camera_perspective`, `hardware_tags`, `attribution_string` (see [`TEMPLATE.md`](catalog/TEMPLATE.md)).
36-
11. Add a row to the matching category `README.md`. This is required: the validator fails an entry that is not listed there, and the row's licence cell must match your frontmatter.
37-
12. Optional: add the `id` to `site/config.json` → `featured` to pin it under Safe starting points.
24+
The website rebuilds from frontmatter on deploy. Node 22 or newer is all you need; there
25+
are no dependencies to install.
26+
27+
1. Run `node site/new-entry.mjs <category> <id>` (or `npm run new-entry -- <category> <id>`). It copies [`catalog/TEMPLATE.md`](catalog/TEMPLATE.md) to `catalog/<category>/<id>.md` with the id, category and today's date filled in, and refuses an id already used anywhere in the catalog. Use a short kebab-case `id`; a mixed kit already listed in another category is a duplicate, not a second entry.
28+
2. Verify the license on the live source page the day you submit, and fill every frontmatter field from it (rules below). Prefer primary URLs over mirror/aggregator pages.
29+
3. Write the body: a one-paragraph summary, `## Notes`, and `## Evidence` with a dated line quoting the source, such as `- Live page (2026-09-25): "Free for commercial use"`. Every Evidence section needs at least one date, and `verified` may not be newer than the newest one. The scaffold starts at `status: needs-review`; set `active` once the licence, the commercial stance and the credit requirement are all settled.
30+
4. Add a row to the matching category `README.md`. This is required: the validator fails an entry that is not listed there, and the row's licence cell must match your frontmatter.
31+
5. Run `node site/sync-counts.mjs` (`npm run counts`). It updates every place the repo restates the entry count: both category count tables, the README badge and "Browse N sources" line, and `expectedEntryCount` in [`site/config.json`](site/config.json).
32+
6. Run `npm run check`: the check tests, `node site/validate.mjs` and `node site/build.mjs`, all of which must pass. The build renders your entry's page and fails if the body uses markdown the site does not support (tables, code fences, blockquotes, images, raw HTML, `###` headings, numbered lists) or links to a file that does not exist.
33+
7. Optional: add the `id` to `site/config.json` → `featured` to pin it under Safe starting points.
3834

3935
To add a starter stack (one pick per need for a kind of game), follow [`stacks/README.md`](stacks/README.md).
4036

@@ -44,13 +40,15 @@ To add a starter stack (one pick per need for a kind of game), follow [`stacks/R
4440
- `license_spdx`: the SPDX identifier the vocabulary maps your `license` to. The validator rejects a missing one when a mapping exists, and an invented one when it does not.
4541
- `commercial`: `true` / `false` / `unknown` / `varies`. Use `varies` for aggregators where some files are commercial-ok and others are not. The site still shows these under Commercial OK, labeled **per-file review**, so they are not silently excluded and not silently treated as a blanket grant.
4642
- `attribution_required`: `true` / `false` / `unknown`. If the licence normally requires credit (CC-BY) but the publisher waives it, set `false` and add a `- Attribution waived:` line in Notes saying so.
47-
- `attribution_string`: optional copy-paste credit.
43+
- `attribution_string`: the copy-paste credit line. Required when `attribution_required` is `true`; optional otherwise.
4844
- `publisher`: optional. Name the **rights-holding publisher**, never the host. Set it whenever that publisher has more than one catalog entry, so the entries group; setting it on a publisher that currently has only one entry is also fine and saves a backfill later. Do not set it to a generic host or distributor (GitHub, Hugging Face, itch.io, OpenGameArt, the Internet Archive, Google Fonts) or to a distributor that does not hold the rights. Distinguish sibling organisations that are genuinely different rights holders: `blender.md` (the application, Blender Foundation) carries no `publisher`, while the asset bundles under `studio.blender.org` carry `Blender Studio`. Kenney, Quaternius, KayKit, LuizMelo, 0x72, Blender Studio, Material Maker, Alif Type, GGBotNet and 3dmodelscc0 are the largest groups in use today; treat that as illustrative, not as the permitted set.
49-
- `subcategories`: lower-case kebab-case (`base-meshes`, `field-recordings`). Reuse a value already in the catalog before inventing one, and do not add a variant of an existing value that differs only in plural or spelling. Where both forms were in use, the more common one was kept (`characters`, `environment`, `interior`, `tileset`, `vectors`).
45+
- `subcategories`: lower-case kebab-case (`base-meshes`, `field-recordings`). Reuse a value already in the catalog before inventing one, and do not add a variant of an existing value that differs only in plural or spelling. Where both forms were in use, the more common one was kept (`characters`, `environment`, `interior`, `tileset`, `vectors`, `pixel`, `impulse-responses`, `base-meshes`). Retired spellings are listed in [`site/value-aliases.json`](site/value-aliases.json), which the validator enforces (V19); add a line there when you merge two values.
5046
- `formats`: what you actually get, in one of four kinds. **File formats**, as commonly written: usually upper case (`PNG`, `FBX`, `JSON`, `VOX`), tool-specific ones as the tool writes them (`gdshader`, `tmx`, `ktx2`). **Engine or language targets**, as the product writes them (`glTF`, `Godot`, `Unity`, `Python`, `React`). **Delivery types** for software with no file format of its own, lower-case kebab-case (`godot-addon`, `blender-extension`, `npm`, `cli`, `library`, `desktop-app`, `mobile-app`, `middleware`, `model`). And `various` for an aggregator whose files come in too many formats to list. Platforms (`windows`, `macos`, `ios`) and descriptions (`heightfield`, `examples`) are `tags`, not formats. Reuse the spelling already in the catalog.
47+
- Frontmatter is one `key: value` per line; lists are `[a, b]` or indented `- item` lines. A key given twice is an error. Entry files may not contain emoji.
5148
- `grid_dimensions` / `camera_perspective` / `hardware_tags`: optional metadata for 2D and UI entries. `3d` and `characters` entries leave `camera_perspective` out: it describes a 2D camera, and those entries have none.
52-
- `verified`: ISO date (`YYYY-MM-DD`) of your last license check.
53-
- `status`: `active` | `needs-review` | `deprecated`. `active` means the licence, the commercial stance and the credit requirement are all settled: an `unknown` in `license`, `commercial` or `attribution_required` keeps an entry at `needs-review`. The validator enforces this (V14), and rejects `formats`, `subcategories` or `tags` values that differ only by case, punctuation or a trailing "s" from one already in use (V13).
49+
- `url`: an `https://` address (`http://` only where the source has no https). Other schemes are rejected.
50+
- `verified`: ISO date (`YYYY-MM-DD`) of your last license check. It must be a real date, no later than tomorrow in UTC, and no newer than the newest date in `## Evidence` (V8): a new `verified` date needs a new dated Evidence line from the same check. Dates inside URLs do not count as Evidence dates.
51+
- `status`: `active` | `needs-review` | `deprecated`. A `deprecated` entry needs a `- Deprecated:` line in its body giving the reason (V9). `active` means the licence, the commercial stance and the credit requirement are all settled: an `unknown` in `license`, `commercial` or `attribution_required` keeps an entry at `needs-review`. The validator enforces this (V14), and rejects `formats`, `subcategories` or `tags` values that differ only by case, punctuation or a trailing "s" from one already in use (V13).
5452

5553
## License verification checklist
5654

‎README.md‎

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -268,11 +268,14 @@ and follow the [Code of Conduct](CODE_OF_CONDUCT.md).
268268
<details>
269269
<summary>Run the checks and preview the site locally</summary>
270270

271+
Node 22 or newer; there is nothing to install.
272+
271273
```bash
272-
node site/checks.test.mjs # the checks, against known-bad fixtures
273-
node site/validate.mjs # the catalog, against the checks
274-
node site/build.mjs # builds the site into site/dist
275-
npx --yes serve site/dist # preview at http://localhost:3000
274+
npm run check # all of the below, in the order CI runs them
275+
npm test # the checks against known-bad fixtures, and the site modules' tests
276+
npm run validate # the catalog, against the checks (node site/validate.mjs)
277+
npm run build # builds the site into site/dist (node site/build.mjs)
278+
npm run serve # preview at http://localhost:3000
276279
```
277280

278281
</details>
@@ -297,14 +300,19 @@ npx --yes serve site/dist # preview at http://localhost:3000
297300
│ ├── godot-budget-stack.md research-index.md
298301
│ ├── review-ledger.md every review pass and what it changed
299302
│ └── images/readme/ publisher stills used in this README
303+
├── stacks/ starter stacks: one pick per need for a kind of game
300304
├── site/
301305
│ ├── validate.mjs catalog integrity checks
302306
│ ├── checks.mjs the checks, as pure functions
303307
│ ├── checks.test.mjs fixtures proving each check fails on bad input
308+
│ ├── new-entry.mjs starts an entry from the template
309+
│ ├── sync-counts.mjs rewrites every restated entry count
304310
│ ├── license-vocabulary.json the licence values the catalog accepts
305311
│ ├── spdx-allowed.json SPDX identifiers in use
306312
│ ├── build.mjs config.json static site generator and its settings
313+
│ ├── lib/ page renderers and shared helpers, with lib.test.mjs
307314
│ └── public/ page, styles and script
315+
├── package.json npm scripts only; no dependencies
308316
└── RESEARCH/README.md research archive index (drafts are gitignored)
309317
```
310318

0 commit comments

Comments
 (0)