Skip to content

Commit 13a67e3

Browse files
TMHSDigitalclaude
andcommitted
site: social preview card, document data.json, perspective is 2D-only
The three maintainer decisions carried since the first review run, each taken at the recommended default. - og:image: docs/images/readme/og-card.png, a 1200x630 screenshot of the site's own first screen (57 KB; first-party, beside the other README stills the validator already allows). build.mjs copies it into dist and emits og:image with size and alt text, and switches twitter:card to summary_large_image with twitter:image. Without the file the build falls back to the old summary card. - data.json: kept, and documented in site/README.md as the catalog's public JSON, with its keys, entry fields and freshness caveat. - camera_perspective and grid_dimensions: 2D and UI entries only, stated in TEMPLATE and CONTRIBUTING. All 52 entries that set either field are already in 2d. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Wc67NX9MM964uaVGn4bpZJ
1 parent 89950d4 commit 13a67e3

6 files changed

Lines changed: 52 additions & 7 deletions

File tree

‎CONTRIBUTING.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ One new markdown file is enough — the website rebuilds from frontmatter on dep
4545
- `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 (GitHub, Hugging Face, itch.io) 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, Google Fonts, OpenGameArt, 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.
4646
- `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`).
4747
- `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.
48-
- `grid_dimensions` / `camera_perspective` / `hardware_tags`: optional 2D/UI metadata.
48+
- `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.
4949
- `verified`: ISO date (`YYYY-MM-DD`) of your last license check.
5050
- `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` or `subcategories` values that differ only by case, punctuation or a trailing "s" from one already in use (V13).
5151

‎catalog/TEMPLATE.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ status: active
1717
# license_spdx: CC0-1.0
1818
# attribution_string: "Credit line if attribution_required"
1919
# commercial: varies # aggregators only; not a blanket commercial grant
20-
# grid_dimensions: 16x16
21-
# camera_perspective: top_down # isometric_3_4 | side_scroller | 2d_flat
20+
# grid_dimensions: 16x16 # 2D and UI entries only
21+
# camera_perspective: top_down # isometric_3_4 | side_scroller | 2d_flat. 2D and UI entries only; 3D and characters leave it out
2222
# hardware_tags: [steam_deck, switch_2]
2323
---
2424

‎docs/images/readme/og-card.png‎

55.5 KB
Loading

‎site/README.md‎

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,31 @@ Static GitHub Pages UI for this catalog.
1313
| `site/config.json` → `categories` / `guides` | Labels and guide links |
1414
| `site/public/*` | Page chrome / design |
1515

16+
## Public JSON
17+
18+
Every deploy publishes the whole catalog as
19+
[`data.json`](https://tmhsdigital.github.io/Free-Game-Dev-Assets/data.json), for scripts
20+
and tools that want the metadata without scraping the page. The page itself loads
21+
`data.js`, the same payload assigned to `window.__CATALOG__`.
22+
23+
- Top-level keys: `generatedAt`, `site`, `categories`, `guides`, `featured`, `stats`,
24+
`entries`.
25+
- Each entry carries its frontmatter fields (`id`, `name`, `url`, `category`,
26+
`subcategories`, `license`, `license_spdx` where set, `commercial`,
27+
`attribution_required`, `attribution_string` where set, `formats`, `tags`, `verified`,
28+
`status`, `publisher` where set, and the optional 2D fields), plus `path` (the entry's
29+
file in this repo), `summary` (the first paragraph of its body), and two derived sort
30+
fields, `attributionClass` and `licenseRank`.
31+
- It is regenerated from `catalog/` on every push to `main`. Field names are stable;
32+
new optional fields may appear. The licence facts are only as current as each entry's
33+
`verified` date: re-check the source before you ship on one.
34+
35+
## Social preview
36+
37+
`docs/images/readme/og-card.png` is a 1200x630 screenshot of this site's first screen.
38+
`build.mjs` copies it into `dist` and emits the `og:image` and `twitter:image` tags.
39+
Retake it when the hero changes.
40+
1641
## Commands
1742

1843
```bash

‎site/build.mjs‎

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ const PUBLIC = path.join(__dirname, "public");
1414
const DIST = path.join(__dirname, "dist");
1515
const CONFIG_PATH = path.join(__dirname, "config.json");
1616
const VOCAB_PATH = path.join(__dirname, "license-vocabulary.json");
17+
// Social preview image: a first-party screenshot of this site, kept with the
18+
// other first-party stills (the validator allows binaries there) and copied
19+
// into dist at build time.
20+
const OG_CARD_NAME = "og-card.png";
21+
const OG_CARD_SRC = path.join(ROOT, "docs", "images", "readme", OG_CARD_NAME);
1722

1823
/** Sort rank for "license permissiveness": least owed first. */
1924
const ATTRIBUTION_RANK = { none: 0, notice: 1, required: 2, any: 3 };
@@ -325,10 +330,21 @@ function guideRowsHtml(guides, repo) {
325330
.join("\n");
326331
}
327332

328-
function headMetaHtml(site, stats, generatedAt) {
333+
function headMetaHtml(site, stats, generatedAt, hasCard) {
329334
const url = site.siteUrl;
330335
const title = site.title;
331336
const desc = site.tagline;
337+
const card = `${url.replace(/\/+$/, "")}/${OG_CARD_NAME}`;
338+
const cardMeta = hasCard
339+
? [
340+
`<meta property="og:image" content="${esc(card)}" />`,
341+
`<meta property="og:image:width" content="1200" />`,
342+
`<meta property="og:image:height" content="630" />`,
343+
`<meta property="og:image:alt" content="${esc(`${title}: ${desc}`)}" />`,
344+
`<meta name="twitter:card" content="summary_large_image" />`,
345+
`<meta name="twitter:image" content="${esc(card)}" />`,
346+
]
347+
: [`<meta name="twitter:card" content="summary" />`];
332348
return [
333349
`<link rel="canonical" href="${esc(url)}" />`,
334350
`<meta name="theme-color" content="#1a4d3e" media="(prefers-color-scheme: light)" />`,
@@ -338,7 +354,7 @@ function headMetaHtml(site, stats, generatedAt) {
338354
`<meta property="og:title" content="${esc(title)}" />`,
339355
`<meta property="og:description" content="${esc(desc)}" />`,
340356
`<meta property="og:url" content="${esc(url)}" />`,
341-
`<meta name="twitter:card" content="summary" />`,
357+
...cardMeta,
342358
`<meta name="twitter:title" content="${esc(title)}" />`,
343359
`<meta name="twitter:description" content="${esc(desc)}" />`,
344360
`<meta name="generator" content="site/build.mjs ${esc(generatedAt)}" />`,
@@ -441,6 +457,10 @@ function main() {
441457

442458
if (fs.existsSync(DIST)) fs.rmSync(DIST, { recursive: true, force: true });
443459
copyDir(PUBLIC, DIST);
460+
const hasCard = fs.existsSync(OG_CARD_SRC);
461+
if (hasCard) fs.copyFileSync(OG_CARD_SRC, path.join(DIST, OG_CARD_NAME));
462+
// data.json is the public machine-readable catalog (see site/README.md);
463+
// the page itself loads data.js.
444464
fs.writeFileSync(path.join(DIST, "data.json"), JSON.stringify(payload, null, 2));
445465
fs.writeFileSync(
446466
path.join(DIST, "data.js"),
@@ -454,7 +474,7 @@ function main() {
454474
const stamp = payload.generatedAt.slice(0, 10);
455475
const visible = entries.filter((e) => e.status !== "deprecated");
456476
const substitutions = {
457-
HEAD_META: headMetaHtml(config.site, stats, payload.generatedAt),
477+
HEAD_META: headMetaHtml(config.site, stats, payload.generatedAt, hasCard),
458478
STARTER_ROWS: starterRowsHtml(featured),
459479
ENTRY_ROWS: groupedRowsHtml(visible, config.categories, repoUrl, now),
460480
CATEGORY_CHIPS: categoryChipsHtml(visible, config.categories),

‎site/validate.mjs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ const BINARY_EXT = new Set([
7474
".pak",
7575
]);
7676
const SKIP_WALK = new Set([".git", "node_modules", "dist", "RESEARCH"]);
77-
/** Generated output and README documentation stills — not third-party packs. */
77+
/** Generated output and first-party stills (README screenshots, the social card): not third-party packs. */
7878
const ALLOWED_BINARY_PREFIXES = ["site/dist/", "docs/images/readme/"];
7979
const EMOJI_RE = /\p{Extended_Pictographic}/u;
8080
const MD_LINK_RE = /!\[[^\]]*\]\(([^)]+)\)|\[[^\]]*\]\(([^)]+)\)/g;

0 commit comments

Comments
 (0)