Index: CHANGELOG.md
===================================================================
--- CHANGELOG.md	(revision 90259da618fae54c487ea9a4998162d68c8cb3a0)
+++ CHANGELOG.md	(revision 90259da618fae54c487ea9a4998162d68c8cb3a0)
@@ -0,0 +1,42 @@
+# Wijzigingen — Klonkt
+
+Alle noemenswaardige wijzigingen aan Klonkt. Nieuwste bovenaan.
+Versies volgen [SemVer](https://semver.org/lang/nl/) (`1.0.0-beta.N` tijdens de beta).
+
+> **Twee losse versienummers — niet verwarren:**
+> - **App-versie** (deze changelog + footer, `package.json`) = cosmetisch; bump elke release.
+> - **Federatie-proto** (`KLONKT_PROTO` in `CircleFederation.js`, nu **2**) = bepaalt of
+>   Klonkt-sites in elkaars **cirkel** kunnen federeren (zit in de getekende grondslag).
+>   Een app-versie-bump verandert de proto **niet** en breekt cirkels dus niet. Bump de
+>   proto **alleen** bij federatie-/security-wijzigingen, en rol die dan in **lockstep**
+>   uit naar álle instances (incl. de democirkels) zodat ze blijven samenwerken.
+
+## [Unreleased]
+
+_Nog niets in voorbereiding._
+
+## [1.0.0-beta.2] — 2026-06-19
+
+Eerste release waarbij we de versie actief bijhouden (zichtbaar in de footer →
+klik erop voor deze pagina). Federatie-proto: **2** (ongewijzigd).
+
+### Toegevoegd
+- Release-tracking: versienummer in de footer linkt naar deze wijzigingen-pagina.
+- Acht premium-functies (Patreon-gegate): nieuwsbrief/mailinglijst, download-voor-email,
+  release-planning + fan-only previews, EPK/perskit, pro-statistieken, link-in-bio +
+  klikstats, inbedbare speler, en show-agenda + notify-me.
+- Nieuwsbrief-aanmeldveld in de footer (aan/uit in Beheer → Instellingen).
+- SMTP-instellingen instelbaar in Beheer → Instellingen (geen `.env`-edit meer nodig),
+  met testmail-knop.
+
+### Gewijzigd
+- Beheer → Instellingen: Hub- en Cirkel-config staan nu direct onder de Modus-kaart;
+  forms netter (gestapelde labels, full-width inputs).
+- EPK/perskit toont de top 10 meest beluisterde nummers.
+- Nettere 404-pagina (mobielvriendelijk) en duidelijkere login-foutmeldingen.
+
+### Opgelost
+- Site-brede audiospeler kreeg geen tracks (verkeerde kolom in de query).
+- Knoptekst werd onleesbaar bij hover (zelfde kleur als de knop).
+- Datumkiezers volgen nu het thema.
+- htmx-navigatie werkt de adresbalk weer bij; geen dubbele kop bij terug/vooruit.
Index: package.json
===================================================================
--- package.json	(revision 323abb039d2022685763cdf42da6aff00685cda6)
+++ package.json	(revision 90259da618fae54c487ea9a4998162d68c8cb3a0)
@@ -1,5 +1,5 @@
 {
   "name": "klonkt",
-  "version": "1.0.0-beta.1",
+  "version": "1.0.0-beta.2",
   "description": "Klonkt — zelf-gehost multi-site muziek- & blogplatform met community, realtime en (later) E2EE DMs. Node + SQLite + htmx.",
   "type": "module",
Index: src/routes/changelog.js
===================================================================
--- src/routes/changelog.js	(revision 90259da618fae54c487ea9a4998162d68c8cb3a0)
+++ src/routes/changelog.js	(revision 90259da618fae54c487ea9a4998162d68c8cb3a0)
@@ -0,0 +1,39 @@
+/**
+ * Publieke wijzigingen-/release-pagina.
+ *
+ * GET /changelog  -> rendert CHANGELOG.md (de bron van waarheid voor releases).
+ *
+ * De app-versie (footer, package.json) is bewust losgekoppeld van de
+ * cirkel-federatie-proto (KLONKT_PROTO): een versie-bump is cosmetisch en raakt
+ * de federatie niet. We tonen de proto hier expliciet zodat per release zichtbaar
+ * is met welke federatie-versie deze instance praat (cirkels = lockstep per proto).
+ */
+
+import express from 'express';
+import fs from 'fs';
+import path from 'path';
+import { fileURLToPath } from 'url';
+import { renderPage } from '../middleware/render.js';
+import { MarkdownService } from '../services/MarkdownService.js';
+import { KLONKT_PROTO } from '../services/CircleFederation.js';
+
+const router = express.Router();
+const __dirname = path.dirname(fileURLToPath(import.meta.url));
+const CHANGELOG_PATH = path.join(__dirname, '..', '..', 'CHANGELOG.md');
+
+router.get('/changelog', (req, res) => {
+  let html;
+  try {
+    html = MarkdownService.render(fs.readFileSync(CHANGELOG_PATH, 'utf8'));
+  } catch {
+    html = '<p>Geen wijzigingenoverzicht beschikbaar.</p>';
+  }
+  renderPage(req, res, 'pages/changelog', {
+    pageTitle: 'Wijzigingen',
+    bodyClass: 'on-changelog',
+    changelogHtml: html,
+    proto: KLONKT_PROTO,
+  });
+});
+
+export default router;
Index: src/server.js
===================================================================
--- src/server.js	(revision 323abb039d2022685763cdf42da6aff00685cda6)
+++ src/server.js	(revision 90259da618fae54c487ea9a4998162d68c8cb3a0)
@@ -61,4 +61,5 @@
 import showsRoutes from './routes/shows.js';
 import adminShowsRoutes from './routes/admin-shows.js';
+import changelogRoutes from './routes/changelog.js';
 
 if (!process.env.SESSION_SECRET) {
@@ -283,4 +284,5 @@
 app.use('/', embedRoutes); // /embed inbedbare audiospeler (premium)
 app.use('/', showsRoutes); // /shows agenda + notify-me (premium)
+app.use('/', changelogRoutes); // /changelog publieke release-/wijzigingen-pagina
 app.use('/', postsRoutes);
 
Index: src/views/pages/changelog.ejs
===================================================================
--- src/views/pages/changelog.ejs	(revision 90259da618fae54c487ea9a4998162d68c8cb3a0)
+++ src/views/pages/changelog.ejs	(revision 90259da618fae54c487ea9a4998162d68c8cb3a0)
@@ -0,0 +1,40 @@
+<div class="container changelog-page">
+  <p><a href="<%= (typeof siteUrlBase !== 'undefined' && siteUrlBase) ? siteUrlBase : '' %>/" class="btn">&larr; Terug</a></p>
+  <h1>Wijzigingen</h1>
+  <p class="cl-meta">
+    App-versie <strong>v<%= appVersion %></strong>
+    <span class="cl-sep">·</span>
+    Federatie-proto <strong><%= proto %></strong>
+    <% if (typeof user !== 'undefined' && user && user.role === 'god') { %>
+      <span class="cl-sep">·</span> <a href="/admin/updates">Updates beheren</a>
+    <% } %>
+  </p>
+  <div class="changelog-body"><%- changelogHtml %></div>
+</div>
+
+<style>
+.changelog-page { max-width: 760px; margin: 3rem auto; padding: 0 1rem; }
+.changelog-page h1 { font-family: var(--font-display, serif); font-size: 2rem; margin: 0 0 0.4rem; }
+.cl-meta { color: var(--ink-muted); font-size: 0.9rem; margin: 0 0 1.75rem; }
+.cl-meta a { color: var(--accent); }
+.cl-sep { opacity: 0.5; margin: 0 0.2rem; }
+.changelog-body { color: var(--ink); line-height: 1.65; }
+.changelog-body h2 {
+  font-family: var(--font-display, serif); font-size: 1.3rem;
+  margin: 2rem 0 0.5rem; padding-top: 1.25rem; border-top: 1px solid var(--rule);
+}
+.changelog-body h2:first-of-type { border-top: none; padding-top: 0; margin-top: 1rem; }
+.changelog-body h3 { font-size: 1rem; margin: 1.1rem 0 0.4rem; color: var(--ink-soft, var(--ink-muted)); }
+.changelog-body ul { margin: 0.3rem 0 0.9rem; padding-left: 1.3rem; }
+.changelog-body li { margin: 0.25rem 0; }
+.changelog-body blockquote {
+  margin: 1rem 0; padding: 0.6rem 0.9rem;
+  border-left: 3px solid var(--accent); background: var(--paper-2);
+  border-radius: 0 8px 8px 0; font-size: 0.9rem; color: var(--ink-muted);
+}
+.changelog-body code {
+  background: var(--paper-2); padding: 0.05rem 0.35rem;
+  border-radius: 4px; font-size: 0.88em;
+}
+.changelog-body a { color: var(--accent); }
+</style>
Index: src/views/partials/footer.ejs
===================================================================
--- src/views/partials/footer.ejs	(revision 323abb039d2022685763cdf42da6aff00685cda6)
+++ src/views/partials/footer.ejs	(revision 90259da618fae54c487ea9a4998162d68c8cb3a0)
@@ -20,5 +20,5 @@
     </button>
     <div class="footer-meta">
-      <span>Klonkt Beta<%= (typeof appVersion !== 'undefined' && appVersion) ? ' v' + appVersion : '' %></span>
+      <a class="footer-version" href="<%= (typeof siteUrlBase !== 'undefined' && siteUrlBase) ? siteUrlBase : '' %>/changelog" title="Bekijk wat er per release veranderd is">Klonkt Beta<%= (typeof appVersion !== 'undefined' && appVersion) ? ' v' + appVersion : '' %></a>
       <%# Mobile-only theme toggle. On desktop the topnav has its own toggle
           so we hide this one to avoid two visible toggles at once. The same
@@ -101,4 +101,6 @@
   display: inline-flex; align-items: center; gap: 0.75rem;
 }
+.footer-version { color: inherit; text-decoration: none; }
+.footer-version:hover { color: var(--accent); text-decoration: underline; }
 .pcms-main { min-height: 50vh; }
 
