Index: src/routes/admin-sites.js
===================================================================
--- src/routes/admin-sites.js	(revision 8ea3d0d20c8b60c9d9a13843b3b654f0e0a7bfc0)
+++ src/routes/admin-sites.js	(revision 98ecf51d81042b5773ac053aa13dfc773dbdf4e9)
@@ -137,4 +137,24 @@
 }
 
+/** Geldige user-id voor owner-toewijzing, of null bij leeg/onbekend. */
+function validOwnerId(raw) {
+  const id = (raw || '').toString().trim();
+  if (!id) return null;
+  return db.prepare('SELECT 1 FROM users WHERE id = ?').get(id) ? id : null;
+}
+
+/** Geef een user admin-rechten op een site (idempotent upsert). */
+function grantSiteAdmin(siteId, userId) {
+  db.prepare(`
+    INSERT INTO site_members (site_id, user_id, role) VALUES (?, ?, 'admin')
+    ON CONFLICT(site_id, user_id) DO UPDATE SET role = 'admin'
+  `).run(siteId, userId);
+}
+
+/** Kandidaat-owners voor het owner-keuzeveld (god-only). */
+function listOwnerCandidates() {
+  return db.prepare('SELECT id, username, role FROM users ORDER BY username').all();
+}
+
 // ==================== LIST ====================
 router.get('/', requireGod, (req, res) => {
@@ -163,5 +183,6 @@
     bodyClass: 'on-admin',
     isNew: true,
-    site: { slug: '', ...siteEditableFields() },
+    site: { slug: '', owner_id: req.session.user.id, ...siteEditableFields() },
+    users: listOwnerCandidates(),
     palettes: ThemeService.listPalettes(),
     accents: ThemeService.listAccents(),
@@ -187,4 +208,10 @@
 
   const f = { ...siteEditableFields(), ...req.body };
+
+  // Owner: god mag de site aan een ANDERE gebruiker toewijzen — dit is de kern
+  // van hub-modus (elke gebruiker z'n eigen, zelf te beheren Klonkt). Leeg of
+  // ongeldig → de aanmakende god zelf.
+  const ownerId = validOwnerId(req.body.owner_id) || req.session.user.id;
+
   const siteId = uuid();
   db.prepare(`
@@ -200,5 +227,5 @@
     (f.description || '').slice(0, 500),
     (f.tagline || '').slice(0, 200),
-    req.session.user.id,
+    ownerId,
     f.language || 'nl',
     f.palette || 'sage',
@@ -213,10 +240,9 @@
   );
 
-  // The site_members entry lets the god/owner show up in canAdminSite checks.
-  db.prepare(`
-    INSERT INTO site_members (site_id, user_id, role) VALUES (?, ?, 'admin')
-  `).run(siteId, req.session.user.id);
-
-  res.redirect(`/admin/sites/${slug}/edit?success=` + encodeURIComponent('Site created'));
+  // De OWNER (niet per se de aanmaker) krijgt een site_members-admin-rij → zo komt
+  // 'ie door canAdminSite + de requireSiteManager-gates en beheert 'ie z'n site.
+  grantSiteAdmin(siteId, ownerId);
+
+  res.redirect(`/admin/sites/${slug}/edit?success=` + encodeURIComponent('Site aangemaakt'));
 });
 
@@ -236,4 +262,5 @@
     isNew: false,
     site,
+    users: listOwnerCandidates(),
     palettes: ThemeService.listPalettes(),
     accents: ThemeService.listAccents(),
@@ -314,5 +341,15 @@
   );
 
-  res.redirect(`/admin/sites/${req.params.slug}/edit?success=` + encodeURIComponent('Saved'));
+  // Owner (her)toewijzen — ALLEEN god. Een site-owner die z'n eigen site bewerkt
+  // kan de eigenaar niet wijzigen (het veld wordt voor niet-god ook niet getoond).
+  if (req.session.user.role === 'god') {
+    const newOwner = validOwnerId(req.body.owner_id);
+    if (newOwner) {
+      db.prepare('UPDATE sites SET owner_id = ? WHERE id = ?').run(newOwner, site.id);
+      grantSiteAdmin(site.id, newOwner);
+    }
+  }
+
+  res.redirect(`/admin/sites/${req.params.slug}/edit?success=` + encodeURIComponent('Opgeslagen'));
 });
 
