Index: src/routes/epk.js
===================================================================
--- src/routes/epk.js	(revision 255e3d35582549cc0de8fa12acbc354d08fcbfdb)
+++ src/routes/epk.js	(revision 255e3d35582549cc0de8fa12acbc354d08fcbfdb)
@@ -0,0 +1,59 @@
+/**
+ * EPK / perskit (premium) — een deelbare perspagina per Klonkt-site.
+ *
+ * GET /pers  (solo) of /user/:slug/pers (hub, via resolveSite + siteUrlBase)
+ *   -> nette, openbare perskit: hero (foto/titel/tagline), korte bio, topnummers,
+ *      recente posts en een contact-knop. Bedoeld om naar boekers/pers te sturen.
+ *
+ * Premium-gated: niet-premium instances hebben GEEN /pers (next() -> 404 via de
+ * catch-all). De PAGINA zelf is openbaar (geen login) zodat pers 'm kan bekijken;
+ * alleen het BESTAAN ervan is premium. Geen login-e-mail lekken: contact loopt via
+ * een expliciet ingesteld pers-adres (epk_contact, per site) of anders de site zelf.
+ */
+
+import express from 'express';
+import db from '../config/database.js';
+import { renderPage } from '../middleware/render.js';
+import { premiumUnlocked } from '../services/PatreonService.js';
+import { getSetting } from '../services/SettingsService.js';
+
+const router = express.Router();
+
+router.get('/pers', (req, res, next) => {
+  if (!premiumUnlocked()) return next();      // geen premium -> geen perskit
+  const site = res.locals.site;
+  if (!site) return next();
+
+  const tracks = db.prepare(
+    `SELECT title, artist, duration, cover_url
+       FROM audio_tracks
+      WHERE site_id = ?
+      ORDER BY position ASC, created_at ASC
+      LIMIT 6`
+  ).all(site.id);
+
+  const posts = db.prepare(
+    `SELECT slug, title, created_at
+       FROM posts
+      WHERE site_id = ? AND status = 'published'
+      ORDER BY created_at DESC
+      LIMIT 5`
+  ).all(site.id);
+
+  // Pers-contact: per-site instelling (epk_contact_<siteId>) als die er is, anders
+  // de globale epk_contact. NOOIT automatisch de login-mail tonen.
+  const contact = (getSetting('epk_contact_' + site.id, '') || getSetting('epk_contact', '') || '').trim();
+  // Korte pers-bio: per-site instelling, anders de tagline van de site.
+  const bio = (getSetting('epk_bio_' + site.id, '') || site.tagline || '').trim();
+
+  renderPage(req, res, 'pages/epk', {
+    pageTitle: (site.title || 'Perskit') + ' — Perskit',
+    bodyClass: 'on-epk',
+    epkTracks: tracks,
+    epkPosts: posts,
+    epkContact: contact,
+    epkBio: bio,
+  });
+});
+
+export default router;
Index: src/server.js
===================================================================
--- src/server.js	(revision 85d9fdadd52102cb2c42df4583431a47c1b11d2b)
+++ src/server.js	(revision 255e3d35582549cc0de8fa12acbc354d08fcbfdb)
@@ -52,4 +52,5 @@
 import adminStatsRoutes from './routes/admin-stats.js';
 import circleRoutes from './routes/circle.js';
+import epkRoutes from './routes/epk.js';
 
 if (!process.env.SESSION_SECRET) {
@@ -265,4 +266,5 @@
 app.use('/', hubRoutes); // hub-overview op '/' (solo: next() -> postsRoutes)
 app.use('/', circleRoutes); // /cirkel-feed (solo/hub: next() -> postsRoutes)
+app.use('/', epkRoutes); // /pers perskit (premium; niet-premium: next() -> 404)
 app.use('/', postsRoutes);
 
Index: src/views/pages/epk.ejs
===================================================================
--- src/views/pages/epk.ejs	(revision 255e3d35582549cc0de8fa12acbc354d08fcbfdb)
+++ src/views/pages/epk.ejs	(revision 255e3d35582549cc0de8fa12acbc354d08fcbfdb)
@@ -0,0 +1,90 @@
+<%
+  // Duur mm:ss
+  function fmtDur(s){ s = parseInt(s,10)||0; var m=Math.floor(s/60), x=s%60; return m+':'+String(x).padStart(2,'0'); }
+  var _accent = (site && site.accent) ? site.accent : '';
+  var _photo = (site && site.profile_photo) ? site.profile_photo : '';
+  var _isMail = epkContact && epkContact.indexOf('@') !== -1 && epkContact.indexOf(' ') === -1;
+  var _isUrl = epkContact && /^https?:\/\//i.test(epkContact);
+%>
+<section class="epk" <%= _accent ? ('style="--epk-accent:' + _accent + '"') : '' %>>
+  <header class="epk-hero">
+    <% if (_photo) { %><div class="epk-photo"><img src="<%= _photo %>" alt="<%= site.title %>"></div><% } %>
+    <div class="epk-hero-text">
+      <div class="epk-kicker">Perskit</div>
+      <h1 class="epk-title"><%= site.title %></h1>
+      <% if (epkBio) { %><p class="epk-bio"><%= epkBio %></p><% } %>
+      <div class="epk-actions">
+        <% if (_isMail) { %>
+          <a class="epk-btn epk-btn-primary" href="mailto:<%= epkContact %>">✉ Contact / boeking</a>
+        <% } else if (_isUrl) { %>
+          <a class="epk-btn epk-btn-primary" href="<%= epkContact %>" target="_blank" rel="noopener">Contact / boeking</a>
+        <% } %>
+        <a class="epk-btn" href="<%= siteUrlBase %>/">Bekijk de site →</a>
+        <% if (_photo) { %><a class="epk-btn" href="<%= _photo %>" download>⬇ Persfoto</a><% } %>
+      </div>
+    </div>
+  </header>
+
+  <% if (epkTracks && epkTracks.length) { %>
+    <div class="epk-block">
+      <h2 class="epk-h2">Muziek</h2>
+      <ul class="epk-tracks">
+        <% epkTracks.forEach(function(t){ %>
+          <li class="epk-track">
+            <% if (t.cover_url) { %><span class="epk-cover" style="background-image:url('<%= t.cover_url %>')"></span><% } else { %><span class="epk-cover epk-cover-empty">♪</span><% } %>
+            <span class="epk-track-meta">
+              <span class="epk-track-title"><%= t.title %></span>
+              <% if (t.artist) { %><span class="epk-track-artist"><%= t.artist %></span><% } %>
+            </span>
+            <% if (t.duration) { %><span class="epk-track-dur"><%= fmtDur(t.duration) %></span><% } %>
+          </li>
+        <% }); %>
+      </ul>
+    </div>
+  <% } %>
+
+  <% if (epkPosts && epkPosts.length) { %>
+    <div class="epk-block">
+      <h2 class="epk-h2">Recent</h2>
+      <ul class="epk-posts">
+        <% epkPosts.forEach(function(p){ %>
+          <li><a href="<%= siteUrlBase %>/<%= p.slug %>"><%= p.title %></a></li>
+        <% }); %>
+      </ul>
+    </div>
+  <% } %>
+
+  <footer class="epk-foot">
+    <% if (_isMail) { %><a href="mailto:<%= epkContact %>"><%= epkContact %></a> · <% } %>
+    <a href="<%= siteUrlBase %>/"><%= site.title %></a>
+  </footer>
+</section>
+
+<style>
+  .epk { max-width: 860px; margin: 0 auto; padding: 28px 18px 64px; --epk-accent: var(--accent, #6b8f71); }
+  .epk-hero { display: flex; gap: 26px; align-items: center; flex-wrap: wrap; margin-bottom: 40px; }
+  .epk-photo { flex: 0 0 auto; }
+  .epk-photo img { width: 190px; height: 190px; object-fit: cover; border-radius: 18px; box-shadow: 0 8px 30px rgba(0,0,0,.18); }
+  .epk-hero-text { flex: 1 1 280px; min-width: 240px; }
+  .epk-kicker { text-transform: uppercase; letter-spacing: .14em; font-size: 12px; font-weight: 700; color: var(--epk-accent); margin-bottom: 6px; }
+  .epk-title { font-size: clamp(30px, 6vw, 52px); line-height: 1.05; margin: 0 0 12px; }
+  .epk-bio { font-size: 16px; line-height: 1.6; opacity: .9; margin: 0 0 18px; max-width: 52ch; }
+  .epk-actions { display: flex; gap: 10px; flex-wrap: wrap; }
+  .epk-btn { display: inline-block; padding: 9px 15px; border-radius: 999px; border: 1px solid rgba(128,128,128,.35); text-decoration: none; font-size: 13.5px; font-weight: 600; color: inherit; }
+  .epk-btn-primary { background: var(--epk-accent); border-color: var(--epk-accent); color: #fff; }
+  .epk-block { margin: 34px 0; }
+  .epk-h2 { font-size: 13px; text-transform: uppercase; letter-spacing: .1em; opacity: .6; margin: 0 0 14px; }
+  .epk-tracks { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }
+  .epk-track { display: flex; align-items: center; gap: 12px; padding: 8px 10px; border: 1px solid rgba(128,128,128,.18); border-radius: 12px; }
+  .epk-cover { flex: 0 0 auto; width: 42px; height: 42px; border-radius: 8px; background-size: cover; background-position: center; display: grid; place-items: center; }
+  .epk-cover-empty { background: var(--epk-accent); color: #fff; opacity: .85; }
+  .epk-track-meta { display: flex; flex-direction: column; flex: 1 1 auto; min-width: 0; }
+  .epk-track-title { font-weight: 600; }
+  .epk-track-artist { font-size: 12.5px; opacity: .65; }
+  .epk-track-dur { font-variant-numeric: tabular-nums; opacity: .6; font-size: 13px; }
+  .epk-posts { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
+  .epk-posts a { text-decoration: none; color: inherit; border-bottom: 1px solid transparent; }
+  .epk-posts a:hover { border-bottom-color: var(--epk-accent); }
+  .epk-foot { margin-top: 44px; padding-top: 18px; border-top: 1px solid rgba(128,128,128,.2); font-size: 13px; opacity: .7; }
+  .epk-foot a { color: inherit; }
+</style>
