4.3 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
What this is
Frame 44 marketing site — an Eleventy (11ty v3) static site. Nunjucks templates, plain CSS, no client-side framework, no build tooling beyond Eleventy itself. Sells map-native interactive exhibit software to museums, historical societies, and heritage sites.
Commands
npm install
npm run serve # http://localhost:8080, live reload
npm run build # writes static output to _site/
There is no test suite (npm test is a stub) and no linter configured.
_site/ is pure static HTML/CSS/JS/SVG — no server-side runtime required. Deployment is self-hosted (copy _site/ to a web server document root); no Netlify/Cloudflare Pages config exists.
Architecture
Data-driven pricing. All pricing content lives in src/_data/*.json, never hardcoded in templates:
packages.json— the four core packages (Exhibit One, Gallery, Flagship, Multi-Site)historicalCollections.json— licensed historical data collectionsaitools.json— optional AI add-ons + the bundleextras.json— extras, prepay terms, hardware range, grant support note, worked-example inputs
Adding an object to packages.json or historicalCollections.json automatically surfaces it on the relevant pages (home pricing teaser, /pricing/, /collections/) — no template changes needed. The pricing page's worked examples are computed in templates from this JSON via the cad, prepay, and findByKey Nunjucks filters defined in eleventy.config.js, so they can't drift out of sync with the underlying prices.
Key filters/shortcodes in eleventy.config.js:
cad— formats a number as CAD currency (whole dollars)prepay— multi-year prepay pricing: 3yr = 2.5x annual, 5yr = 4x annualsum,findByKey— array helpers used in templatesyearshortcode — current year for footer copyright
i18n scaffolding (English-only today). UI strings live in src/_data/i18n/en.json, exposed to templates as i18n via src/_data/i18n.js (currently always returns en). The folder layout anticipates a /fr/ locale: adding French means creating src/_data/i18n/fr.json, switching i18n.js to select by data.lang, and duplicating page templates under src/fr/ with lang: fr front matter (they can extend/reuse the same layouts and macros). Product pricing data (packages.json etc.) only needs duplicating if names/descriptions require translation — see i18n.js for the pattern.
Logos vs. served images. src/assets/logos/ holds huge (8000×4500px) raw design-export PNGs (11 variants). eleventy.config.js passthrough copy deliberately excludes this folder — only src/assets/{css,js,images,fonts} ship to _site/. What's actually served (checked into src/assets/images/, cropped/resized from the raw sources) is logo-header.png (white+red, dark header), logo-footer.png (full-colour, light footer + JSON-LD), and the favicon set. If the brand mark changes, re-crop from src/assets/logos/ rather than hand-editing the served images.
Templates. src/_includes/layouts/base.njk is the shared layout; src/_includes/macros.njk holds shared Nunjucks macros; src/_includes/partials/ holds header/footer. Page routes are folders under src/ (about/, contact/, museums/, platform/, pricing/, collections/ via src/collections/index.njk) each with an index.njk.
Contact. The contact page uses a plain mailto: link (src/contact/index.njk) — there is no form backend.
Known placeholders / unconfirmed data (see site.json / extras.json flags)
contactEmailinsrc/_data/site.jsonis a placeholder (contactEmailConfirmed: false).- Hardware price range and installation timeline in
extras.jsonare unconfirmed (extras.hardware.confirmed/extras.timeline.confirmed). src/assets/css/style.cssreferences self-hosted webfonts (Schibsted Grotesk, Inter) at/assets/fonts/...that are not checked in; the site falls back to system fonts until real.woff2files are added.- Museum case-study copy in
src/_data/museums.json(Grootegast, Holten) and all entries insrc/_data/team.jsonare placeholders. - No
og:imageis set insrc/_includes/layouts/base.njk.
Treat these as real gaps, not stale notes — check the confirmed flags in the JSON before assuming a number is final.