# 17 — API: blog Leggi `CLAUDE.md`. ## Obiettivo Blog con contenuti markdown, ricerca full-text e gestione admin. ## Cosa fare - Pubblico: `GET /blog/posts` (paginazione, categoria, `q` per ricerca full-text con `websearch_to_tsquery('italian', unaccent(q))` e ordinamento per rank), `GET /blog/posts/:slug`, `GET /blog/categories`. Solo post `published` con `published_at <= now()`. - Il dettaglio restituisce sia `content_md` sia `content_html` renderizzato con `marked` e **sanitizzato** (`sanitize-html` con whitelist). - Admin: CRUD post e categorie, slug generato dal titolo e univoco, cambio stato draft/published, preview (`POST /admin/blog/preview` riceve markdown e restituisce HTML sanitizzato). - `GET /sitemap-data` con slug e date di aggiornamento (servirà al frontend SSR per la sitemap). ## Criteri di accettazione - La ricerca "pompa calore" trova un post intitolato "Pompe di calore: guida" (stemming italiano + unaccent). - Markdown con `