Files

4.1 KiB

SEO: decisions and slice order

Spec of record for the design is change-list.md (section "SEO round"), screens/editor.md, screens/sites.md, screens/articles.md, screens/integration.md and states.md. This file records the product decisions that settle the design's open questions, and the order of the implementation slices.

Decisions on the open questions

# Question Decision
1 Is slug immutable after publication? No. It stays editable. RenewCMS does not manage redirects, so the frontend owns them. No extra warning copy is added to the design.
2 SEO object for drafts GET /v1/article/{id}/seo answers drafts to authenticated callers who can read the article, and 404 to anonymous callers. The editor preview needs it.
3 Noindex in the sitemap Included with noindex: true, as drawn. The frontend decides.
4 Who applies title_template The API. title in the SEO object is resolved. The raw seo_title and the site template stay readable on their own routes.
5 Backfill Migration generates a slug for every existing article from its title (same slug rule as authors), unique per site, with -2, -3 suffixes. A title with no letter or digit becomes article, then article-2, article-3. It runs once and is idempotent.
6 Excerpt in the list payload Yes. Article items carry excerpt.

Decisions that the design leaves implicit

  • Suggestions come from one server-side rule set. The same function feeds seo_status and seo_suggestions in the article list, the collapsed section summary, and the editor panel.
  • The editor panel's "checking" states and the "slug taken" state use one non-persisting endpoint: POST /v1/article/{id}/seo/check. Its body takes the same optional SEO fields as PATCH /v1/article/{id}, plus an optional body (never site_id or author_ids), and overrides the saved values for the check only. It answers { status, suggestions: [{ code, field, params }], slug: { available, suggestion } }. Copy for each code lives in the SPA, with a French entry. seo_dismissed codes are filtered out of suggestions and are never counted in the list.
  • The suggestion codes are the ones the board uses: title_long, title_empty, desc_short, desc_long, cover_alt, cover_none, slug_long, no_au, no_h, body_alt, short.
  • Cover, social and site social images are media usages: GET /media/{id}/usage, used_in, the unused filter, merge, purge and delete protection must count them. This also closes the existing gap where author avatars and site social images are missing from GET /media/{id}/usage.
  • Roles: anyone who can edit an article edits its SEO fields and runs the check. Only the owner edits site SEO fields (403 "Only the owner can do this."). GET /v1/site/{key}/sitemap is public, like the other read routes that serve online articles. SEO edits are logged as an articles event; no field values or body text are stored.
  • PATCH /v1/article/{id} still requires at least one known field and still answers 400 on null. The SEO fields join body, site_id and author_ids.

Slices

  1. SEO data (backend). Article and site fields, slug rule and uniqueness per site (409 plain-text slug_taken; the first free alternative is in the X-Slug-Suggestion response header), backfill, excerpt in reads and lists, media usage widening. No resolver yet.
  2. SEO output (backend). GET /v1/article/{id}/seo (fallback chain, title template, JSON-LD), POST /v1/article/{id}/seo/check, seo_status, seo_suggestions and ?seo= on the article list, GET /v1/site/{key}/sitemap.
  3. Editor (SPA). "Search and sharing" section, slide-over and sheet, live previews, suggestions with debounced check, slug field with Auto and Reset, "What the frontend gets" dialog, draft and Save behaviour.
  4. Sites, Articles, Integration (SPA). Site SEO defaults, status chip and "Needs attention" filter, Integration "Search and sharing" group, French strings, catalogue.

Run them in order and commit between them: 2 uses the fields of 1, 3 uses the endpoints of 2, and 3 and 4 share the article API types.