2026-07-16 16:36:46 -04:00
2026-07-16 16:36:46 -04:00
2026-07-16 16:36:46 -04:00
2026-07-16 16:36:46 -04:00
git
2026-07-15 21:32:46 -04:00
2026-07-16 16:36:46 -04:00
2026-07-16 16:36:46 -04:00
2026-07-16 16:36:46 -04:00
2026-07-16 16:36:46 -04:00
2026-07-16 16:36:46 -04:00

Frame 44 — Marketing Site

Eleventy (11ty v3) static site. Nunjucks templates, plain CSS, no client-side framework, no build tooling beyond Eleventy itself.

Build & run

npm install
npm run serve   # http://localhost:8080, live reload
npm run build   # writes static output to _site/

_site/ is pure static HTML/CSS/JS/SVG — no server-side runtime required.

Deploying (self-hosted)

Copy the contents of _site/ to your web server's document root after running npm run build. Any static file server works. Example nginx server block:

server {
    listen 80;
    server_name frame44.com www.frame44.com;
    root /var/www/frame44-landing-page/_site;
    index index.html;

    location / {
        try_files $uri $uri/index.html =404;
    }
}

No Netlify/Cloudflare Pages config is included — this build targets self-hosting. If that changes later, add netlify.toml or a Cloudflare Pages project pointing npm run build_site/.

The contact page uses a plain mailto: link (see src/contact/index.njk), so there's no form backend to wire up. When email delivery is set up (sendmail or otherwise), the address that link points to still needs to be a real, monitored inbox — see the TODO list below.

Logo & favicon

The real brand mark lives in src/assets/logos/ as huge (8000×4500px) design-export PNGs — 11 variants (colour/mono/white × horizontal/stacked lockups, plus two duplicate favicon-mark exports). That folder is not shipped: eleventy.config.js only passes through src/assets/{css,js,images,fonts}, deliberately excluding src/assets/logos, so those multi-megabyte source files never reach _site/.

What's actually served, all cropped/resized from those sources and checked into src/assets/images/:

  • logo-header.png — white + red horizontal lockup, for the dark header band
  • logo-footer.png — full-colour (black + red) horizontal lockup, for the light footer and the JSON-LD logo field (schema.org recommends a logo on a light/transparent background, not an inverted one)
  • favicon-16x16.png / favicon-32x32.png / apple-touch-icon.png, and src/favicon.ico (multi-size 16/32/48) — the square icon mark composited onto a solid --color-ink tile, since the source mark is white + red and needs a dark background to read

If the brand mark changes, re-crop from src/assets/logos/ (or a new export) rather than hand-editing the PNGs in src/assets/images/.

Where prices live

All pricing content is in src/_data/*.json — nothing is hardcoded in templates:

  • packages.json — the four core packages (Exhibit One, Gallery, Flagship, Multi-Site)
  • historicalCollections.json — licensed historical data collections
  • aitools.json — optional AI add-ons + the bundle
  • extras.json — extras, prepay terms, hardware range, grant support note, and the worked-example inputs

Changing a number in one of these files updates every page that shows it. The pricing page's "worked example" and the multi-year prepay example are computed in the template from these JSON values (via the cad, prepay, and findByKey Nunjucks filters in eleventy.config.js) — they are not separately typed-in numbers, so they can't drift out of sync with the package/collection/AI-tool prices.

Adding a package

Add an object to src/_data/packages.json:

{
  "key": "unique-key",
  "name": "Package Name",
  "badge": null,
  "buildPrice": 10000,
  "annualPrice": 3000,
  "summary": "One-line summary.",
  "features": ["Feature one", "Feature two"]
}

It will automatically appear in the home page pricing teaser and the /pricing/ packages grid.

Adding a historical collection

Add an object to src/_data/historicalCollections.json with key, name, price, priceType ("annual" or "one-time-per-project"), description, whatsInside, and suits. It will automatically appear on both /pricing/ and /collections/.

Planned /fr/ locale

The site builds English-only today, but the data/folder layout is already split so French can be added without restructuring:

  • UI strings (nav labels, buttons, footer copy) live in src/_data/i18n/en.json, exposed to templates as i18n via src/_data/i18n.js.
  • To add French: create src/_data/i18n/fr.json, then change i18n.js from always returning en to selecting by data.lang (the comment at the top of that file spells out the exact change).
  • Duplicate the page templates under src/fr/ (e.g. src/fr/index.njk, src/fr/pricing/index.njk) with front matter lang: fr and permalink: /fr/.... They can {% extends %}/reuse the same layout and macros — only the copy and lang differ.
  • Prices themselves (packages.json, historicalCollections.json, etc.) don't need duplicating unless product names/descriptions need translation — in that case, add locale-suffixed data files (e.g. packages.fr.json) and pick the right one the same way i18n.js does.

What's not real yet (TODO before launch)

  • Contact emailcontact@frame44.example is a placeholder (site.contactEmailConfirmed: false in src/_data/site.json). Flagged inline on the Contact page.
  • Hardware price range ($3,500$9,000/screen) — unconfirmed, flagged on the Pricing page (extras.hardware.confirmed: false).
  • Installation timeline (816 weeks) — unconfirmed, flagged on the Pricing page (extras.timeline.confirmed: false).
  • Self-hosted webfontssrc/assets/css/style.css references /assets/fonts/schibsted-grotesk/*.woff2 and /assets/fonts/inter/*.woff2, but no font files are checked in (this environment has no network access to fetch them). The site falls back to system fonts until real woff2 files are added at those paths.
  • Museum case-study copy — Grootegast and Holten summaries in src/_data/museums.json are <!-- TODO --> placeholders; real photos also needed at src/assets/images/placeholders/grootegast.svg / holten.svg (currently generated placeholder graphics).
  • Team bios — all three entries in src/_data/team.json are placeholders (name, role, bio, photo).
  • Open Graph share image — no og:image tag is set. Add a real image and an og:image meta tag in src/_includes/layouts/base.njk once one exists.
  • Lighthouse scores — not run in this environment (no browser available here). Run npm run build && npx serve _site and check Performance/Accessibility/Best Practices/SEO locally before launch, particularly once the real webfonts and images are in place (placeholders are lightweight SVG, so real photos may change the Performance number).
Description
No description provided
Readme 253 KiB
Languages
Nunjucks 63.1%
CSS 30.2%
JavaScript 6.7%