Featured-image alt text + optional SEO description override

Featured-image alt text + optional SEO description override

#44 in Riparion/riparion-cms — merged 2026-06-02

Adds the two follow-up SEO fields flagged in the AI-optimization review: genuine per-image alt text and an optional SEO meta-description override, for both posts and pages. Builds on #43.

Why

  • The featured image previously used the post/page title as its alt — not a real description. Now editors can write proper alt text (better for screen readers and image search), and it also feeds a new og:image:alt / twitter:image:alt.
  • The excerpt was doing double duty as both the on-page summary and the meta description. Now an optional SEO description can override the search/social blurb without changing the excerpt.

Both fields are optional — blank means "fall back" (alt → title, SEO description → excerpt), so existing content renders exactly as before.

Changes

  • Migrations (sqlite + postgres): nullable featured_image_alt and seo_description columns on posts and pages.
  • Wire types: added to PostDetail/PostCard/PostEditData/PostInput and Page/PageCard/PageDetail/PageEditData/PageInput.
  • DB layer: threaded through every post/page SELECT/INSERT/UPDATE, including bind-index fixes for the publish-stamp CASE and the shared POST_CARD_COLUMNS projection.
  • Server fns: create_post/update_post/create_page/update_page carry the fields; a new blank_to_none helper normalizes blank → NULL at the trust boundary.
  • Editor UI: SEO-description and alt-text inputs in both the post and page editors.
  • Reader: fallback logic centralized in head::meta_description / head::meta_image_alt, used by the <head> tags, the featured <img>, the feed/page cards, and the JSON-LD description. New og:image:alt in OgHead.
  • Docs: SEO help article gains the two knobs + checklist updates; AI-search article notes the overrides. Test fixture applies the new migration.

Verification

  • cargo fmt --all -- --check
  • cargo clippy — server sqlite ✓, server postgres ✓, wasm client ✓ (all -D warnings)
  • cargo test --features server,sqlite ✓ (38 passed; the queryloop tests confirm the new columns resolve and bind ordering is correct)

🤖 Generated with Claude Code

Last updated 2026-06-03