feat(gallery): canonical templates.json catalog API (SoT -> build-time gen)
Emit public/templates.json from app/templates-data.ts (the single source of truth) via a prebuild step, so gallery.hanzo.ai/templates.json is the machine-readable template catalog consumed by hanzo.app. Each record keeps the raw SoT fields and adds absolute screenshotUrl/templateUrl/repo so consumers never encode the gallery's internal path scheme. - scripts/gen-templates-json.mjs: imports templates-data.ts (node 24 type-strip) - package.json: prebuild hook runs the generator before next build - Dockerfile: node:22 -> node:24 for stable TS type-stripping - public/templates.json: 72 templates, 71 with real screenshots Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
254b139c40
commit
43c689503a
+4
-1
@@ -3,7 +3,10 @@
|
||||
# Two stages: build the export, then re-serve it through the canonical static server.
|
||||
|
||||
# 1) Build the Next.js static export -> /app/out
|
||||
FROM node:22-bookworm-slim AS build
|
||||
# node:24 (LTS) has stable TypeScript type-stripping so the `prebuild` step can
|
||||
# `import` app/templates-data.ts directly to emit public/templates.json (the SoT
|
||||
# -> canonical catalog API). No flags needed.
|
||||
FROM node:24-bookworm-slim AS build
|
||||
WORKDIR /app
|
||||
COPY package.json package-lock.json ./
|
||||
RUN npm ci --no-audit --no-fund
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "next dev --turbopack",
|
||||
"gen-templates-json": "node scripts/gen-templates-json.mjs",
|
||||
"prebuild": "node scripts/gen-templates-json.mjs",
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "eslint",
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 284 KiB After Width: | Height: | Size: 236 KiB |
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,49 @@
|
||||
#!/usr/bin/env node
|
||||
// One source of truth -> canonical catalog API.
|
||||
// Reads app/templates-data.ts (the SoT) and emits public/templates.json so
|
||||
// gallery.hanzo.ai/templates.json is the machine-readable template catalog
|
||||
// consumed by hanzo.app. Run as a prebuild step (npm run build).
|
||||
//
|
||||
// Each emitted record keeps the raw SoT fields and adds absolute URLs so
|
||||
// consumers never have to know the gallery's internal path scheme:
|
||||
// screenshotUrl -> https://gallery.hanzo.ai/screenshots/<screenshot>.png
|
||||
// templateUrl -> https://gallery.hanzo.ai/templates/<slug>
|
||||
// repo -> https://github.com/hanzo-apps/<slug> (fork source)
|
||||
|
||||
import { readFileSync, writeFileSync, existsSync } from 'node:fs';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { dirname, join } from 'node:path';
|
||||
import { templates } from '../app/templates-data.ts';
|
||||
|
||||
const here = dirname(fileURLToPath(import.meta.url));
|
||||
const root = join(here, '..');
|
||||
const GALLERY_ORIGIN = process.env.GALLERY_ORIGIN || 'https://gallery.hanzo.ai';
|
||||
const screenshotsDir = join(root, 'public', 'screenshots');
|
||||
|
||||
const enriched = templates.map((t) => {
|
||||
const shotFile = `${t.screenshot}.png`;
|
||||
const hasShot = existsSync(join(screenshotsDir, shotFile));
|
||||
return {
|
||||
...t,
|
||||
screenshotUrl: `${GALLERY_ORIGIN}/screenshots/${shotFile}`,
|
||||
hasScreenshot: hasShot,
|
||||
templateUrl: `${GALLERY_ORIGIN}/templates/${t.slug}`,
|
||||
repo: `https://github.com/hanzo-apps/${t.slug}`,
|
||||
};
|
||||
});
|
||||
|
||||
const withShots = enriched.filter((t) => t.hasScreenshot).length;
|
||||
const payload = {
|
||||
version: 1,
|
||||
origin: GALLERY_ORIGIN,
|
||||
count: enriched.length,
|
||||
screenshots: withShots,
|
||||
generatedAt: new Date().toISOString(),
|
||||
templates: enriched,
|
||||
};
|
||||
|
||||
const out = join(root, 'public', 'templates.json');
|
||||
writeFileSync(out, JSON.stringify(payload, null, 2));
|
||||
console.log(
|
||||
`gen-templates-json: wrote ${enriched.length} templates (${withShots} with screenshots) -> public/templates.json`,
|
||||
);
|
||||
Reference in New Issue
Block a user