The starter template for AI startups. Auth, checkout and i18n included. Français
Core Concepts

Basic Usage

Pages and layouts

Each page is a small front-matter file in src/content/en/ or src/content/fr/ that points to a layout in src/_includes/layouts/. For example, src/content/en/pricing.njk:

---
layout: layouts/pricing.njk
permalink: /pricing/index.html
locale: en
title: Pricing
altLangUrl: /fr/tarifs/
altLangLocale: fr
---

The layout holds the markup and both language versions share it. altLangUrl links each page to its translation, which drives the language switcher and the hreflang tags.

Translations

Interface strings live in src/_data/i18n.js as flat keys, with one dictionary per language. Templates use the t filter:

<h1>{{ "pricing.page_title" | t(locale) }}</h1>

The browser app uses the same dictionary through t() in src/js/app.js. bun run i18n:check fails if a key, a blog post or a page is missing in either language.

Adding a page

  1. Create the layout, for example src/_includes/layouts/about.njk, extending layouts/base.njk.
  2. Add src/content/en/about.njk and src/content/fr/a-propos.njk with matching altLangUrl values.
  3. Add its strings to both dictionaries in i18n.js.
  4. Add it to src/_data/navigation.js if it belongs in the header.

Pages that shouldn't be indexed, like account and checkout pages, set noindex: true. They stay out of the sitemap but keep their canonical links.

Blog posts and guides

Blog posts are Markdown files in content/<lang>/blog/, and every post needs a translationKey shared with its translation. Guides live in content/<lang>/guides/ and are grouped in the sidebar by their section and order front matter.

The browser app

src/js/app.js is one small module. A single click handler dispatches data-action attributes, and render() updates the page from one state object. Page-specific code can live in src/js/pages/, registered in PAGE_MODULES and loaded as a separate chunk only on pages whose layout sets pageModule.

Launch offer: 20% off either licence with code LAUNCH20 at checkout.