# {{projectName}} / {{appName}}

A bilingual (en/de) changelog / release-notes site (template: **changelog**),
powered by [`@voltro/changelog`](https://www.npmjs.com/package/@voltro/changelog).
The chrome (nav, footer, empty state, page titles) is translated; release
entries are content and stay as authored. English lives at the bare path,
German under `/de` — each pre-rendered as its own crawlable URL.

## What's here

```
content/releases/*.mdx     ← one file per release (frontmatter + markdown)
src/lib/releases.ts        ← loads + sorts them via `loadReleases` (Vite raw glob)
src/lib/locale.ts          ← URL-prefix i18n helpers (SUPPORTED_LOCALES, withLocalePrefix, …)
src/locales/{en,de}.ts     ← typed, key-parity chrome catalogs
src/pages/index.tsx        ← the release list
src/pages/[slug].tsx       ← one page per release (code fences highlighted by `highlightRelease`)
src/pages/[locale]/**      ← per-locale mirrors (getStaticPaths → /de, /de/<slug>)
src/pages/layout.tsx       ← BlogLayout shell + URL <I18nProvider> + language switcher (headerRight)
scripts/generate-rss.mjs   ← writes public/rss.xml via `renderReleaseRss` (build step)
```

```bash
pnpm install
pnpm --filter @{{projectName}}/{{appName}} dev
# → http://localhost:{{port}}            the release list
# → http://localhost:{{port}}/v0-2-0     a single release
```

## Add a release

Drop a new file in `content/releases/`. Required frontmatter is `version`
+ `releasedAt`; everything else is optional:

```mdx
---
version: 0.3.0
releasedAt: 2026-07-01
slug: v0-3-0          # URL segment; defaults to a slugified version
title: My release
summary: One-line summary (shown in the list + RSS).
tags: [feature, fix]  # feature | fix | breaking | security | performance
---

## What changed

Markdown body — code fences get syntax-highlighted at build time.
```

Files missing `version`/`releasedAt` are skipped; the list is sorted
newest-first automatically.

## RSS feed

`pnpm build` runs `scripts/generate-rss.mjs` (which calls
`renderReleaseRss`) before the static build, emitting `public/rss.xml`
→ served at `/rss.xml`. Set `SITE_URL` so the feed's links are absolute:

```bash
SITE_URL=https://changelog.example.com pnpm build && pnpm start
```

## "What's new" badge in another app

The other half of `@voltro/changelog` lives on the browser-only
`/web` subpath: `useChangelogBadge` polls this site's `rss.xml` and tells
a PRODUCT app's nav when there's an unread release. Add it to that app
(not this one):

```tsx
import { useChangelogBadge } from '@voltro/changelog/web'

const { hasUnread, latest, markRead } = useChangelogBadge({
  url: 'https://changelog.example.com/rss.xml',
})
// render a dot when `hasUnread`; call `markRead()` when the user opens it.
```
