Index: src/routes/search.js
===================================================================
--- src/routes/search.js	(revision 1720482bc8e10937812eea5cdd213db0cc85a347)
+++ src/routes/search.js	(revision 16b0c005569dfa6bbec9512f9815fd7100ebe95a)
@@ -37,4 +37,20 @@
 function likeArg(q) {
   return '%' + q.replace(/[%_\\]/g, '\\$&') + '%';
+}
+
+// Maak de FTS-snippet leesbaar: shortcodes ([[...]]) en markdown-tekens eruit.
+// De <mark>…</mark>-highlights van FTS blijven staan. Valt terug op de excerpt
+// (geëscaped) als er na het schoonmaken niets leesbaars overblijft.
+function cleanSnippet(html, excerpt) {
+  const esc = (s) => s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
+  const s = (html || '')
+    .replace(/!\[[^\]]*\]\([^)]*\)/g, ' ')   // markdown-afbeeldingen
+    .replace(/\[\[[^\]]*?\]\]/g, ' ')         // shortcodes (incl. <mark> erin)
+    .replace(/\[\[|\]\]/g, ' ')               // losse haakjes door truncatie
+    .replace(/[#>*_`~]+/g, ' ')               // markdown-opmaaktekens
+    .replace(/\s+/g, ' ')
+    .trim();
+  if (!s || /^[…\s]*$/.test(s)) return esc((excerpt || '').slice(0, 160));
+  return s;
 }
 
@@ -85,4 +101,5 @@
         LIMIT 50
       `).all(ftsQuery, site.id);
+      results = results.map((r) => ({ ...r, snippet: cleanSnippet(r.snippet, r.excerpt) }));
     } catch (err) {
       queryError = err.message;
