4.1 KiB
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_statusandseo_suggestionsin 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 asPATCH /v1/article/{id}, plus an optionalbody(neversite_idorauthor_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_dismissedcodes are filtered out ofsuggestionsand 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 fromGET /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}/sitemapis public, like the other read routes that serve online articles. SEO edits are logged as anarticlesevent; no field values or body text are stored. PATCH /v1/article/{id}still requires at least one known field and still answers 400 onnull. The SEO fields joinbody,site_idandauthor_ids.
Slices
- SEO data (backend). Article and site fields, slug rule and uniqueness per site (409 plain-text
slug_taken; the first free alternative is in theX-Slug-Suggestionresponse header), backfill,excerptin reads and lists, media usage widening. No resolver yet. - SEO output (backend).
GET /v1/article/{id}/seo(fallback chain, title template, JSON-LD),POST /v1/article/{id}/seo/check,seo_status,seo_suggestionsand?seo=on the article list,GET /v1/site/{key}/sitemap. - 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.
- 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.