82 lines
9.3 KiB
Markdown
82 lines
9.3 KiB
Markdown
# States
|
||
|
||
Every state in the three boards is drawn in light and dark (theme switch) at 1440×900 and 390×844. Counts are in README.md.
|
||
|
||
## Clock-sensitive states
|
||
Only individual states that render a relative time or a countdown are marked "Clock-sensitive" on the board: Articles "Published" (Updated reads "Just now"), Media "Upload: too many requests (429)" and Settings "Too many requests (429)" (countdowns), Users "Renew invite: done", and the Settings update states that show "Last checked today at 09:41" or "yesterday" (Up to date, Check failed, Update available, Update available with notes open, Update done, Plain restart: confirm, Admin view, Role changed, Update already running). Capture and test them with a frozen clock at 13 Oct 2026, 09:41. Frames that merely list dated rows are not marked.
|
||
|
||
## Sites and authors: roles
|
||
Sites: only the owner can create, edit, delete or set the default; other roles have no Sites entry and get a 403 page on a direct link. Anyone who can edit an article can set its site and read the site list. Authors: owner and admin manage; other roles see the list and detail read-only and can create and edit their own author only. The site key is immutable after creation.
|
||
|
||
## Copy glossary
|
||
| Use | Not |
|
||
|---|---|
|
||
| Delete (removes a record: article, variant, image, invite, cache files) | Remove |
|
||
| Remove link, Remove from the article, Remove (detaches; the record stays) | Delete |
|
||
| Create, Add variant, Create draft | New (except the page and button name "New article") |
|
||
| Save (a form or the editor), Save changes (edit forms) | Update (Update is the software-update action only) |
|
||
| Cancel on the left, primary on the right | Close on a dialog that has an action |
|
||
| Close only when the dialog has no action | Done, OK |
|
||
| Explicit non-destructive label in place of Cancel when Cancel would be ambiguous: "Keep invite", "Keep key", "Restart later" | Cancel there |
|
||
| Sentence case everywhere | Title Case |
|
||
| Errors say what happened and what was kept, end with a full stop | Exclamation marks |
|
||
| Toast: title is a short result in the past tense ("Article deleted", "Download started"), body one sentence with a full stop | Titles with a full stop; future tense |
|
||
| In-flight verb ends in an ellipsis character: "Saving…", "Creating…", "Preparing download…" | Three dots |
|
||
|
||
Glossary pass 2, changes made: activity log lines "Removed N expired invites" and "Removed N generated files" became "Deleted …" (they delete records or files); Activity export footer "Close" next to "Download again" became a single "Close"; export title "Export ready" became "Download started"; export failure title "Couldn't prepare the export" became "Couldn't prepare the download"; "Cancel export" became "Cancel". Checked by search across all frames and boards for exclamation marks (none found), Remove and Delete, Update and Save, "New", and dialog footers. Not re-read line by line; see README "Not done".
|
||
|
||
## HTTP status to copy
|
||
| Status | Copy |
|
||
|---|---|
|
||
| 400 | "That request wasn't valid. Check the fields and try again." |
|
||
| 401, 403 | Global redirect, no local copy (403 from an unverified account). Role 403s have local copy: see the rows below |
|
||
| 404 | "That item no longer exists." |
|
||
| 409 | "This changed somewhere else. Reload and try again." |
|
||
| 413 | "That file is too large." |
|
||
| 429 | "Too many requests. Try again in a few minutes." |
|
||
| 500, network | "Something went wrong on our side. Nothing was changed. Try again in a moment." |
|
||
| 400 invalid_site_url | "Use https. For example https://blog.example.com." / "Remove the path. Use only the host, like https://blog.example.com." / "Enter a full URL, like https://blog.example.com." (inline under base url) |
|
||
| 409 site_key_taken | "A site with the key "journal" already exists. Choose another key." (inline under key, with a suggestion) |
|
||
| 409 site_has_articles | "Choose where the articles go. This site has 38 articles." (inside the delete dialog) |
|
||
| 403 "Only the owner can do this." (page) | "You don't have access to Sites" / "Only the owner can manage sites. Ask the owner of this site if you need a change." / "Back to Settings" (403 page on /settings/sites) |
|
||
| 403 "Only the owner can do this." (action) | "Only the owner can manage sites" / "Ask the owner of this site." (error toast, role changed while the page was open) |
|
||
| 403 author_rights | "Only an owner or admin can change authors" / "You can still edit your own author profile." (error toast, role changed while the page was open) |
|
||
| 400 key_immutable | "Used in API paths, so it can't change." (not shown: the edit form has no editable key) |
|
||
| 400 invalid_locale | "Use a language tag like en or fr-CH." (inline under locale) |
|
||
| 403 default_site | "The default site can't be deleted. Make another site the default first." (toast if the menu was stale) |
|
||
| 404 site_not_found | "That site no longer exists" / "It was deleted somewhere else, so we removed it from the list." (info toast) |
|
||
| 409 author_slug_taken | "The slug "camille-roche" is already used by another author." (inline under slug, with a suggestion) |
|
||
| 409 author_has_articles | "Can't delete this author" / ""Camille Roche" is credited on 3 articles. Choose another author to credit instead, or remove Camille Roche from those articles first." (server fallback dialog, drawn once) |
|
||
| 409 user_already_linked | "That user already has an author. Choose another user." (inline under linked user) |
|
||
| 422 bio_too_long | "Shorten the bio to 280 characters." (inline under bio) |
|
||
| 422 invalid_url | "Enter a full URL starting with https://." (inline under website and each social link) |
|
||
| 404 author_not_found | "That author no longer exists" / "It was deleted somewhere else, so we removed it from the list." (info toast) |
|
||
| 404 site_not_found (sitemap) | GET /v1/site/{key}/sitemap, unknown key. The body is the code `site_not_found`, shown on Integration in the code style (not rewritten as prose). |
|
||
| 400 (sitemap page or size) | "The request cannot be processed due to a mismatch in the format of the body." (same text as the other routes on Integration) |
|
||
| 403 owner_only vs article SEO | Integration note under the 403 row: "Site SEO defaults are owner only. Article SEO fields need only the right to edit the article." |
|
||
| 500 – | "Couldn't save the site. Your changes are still here. Try again in a moment." / "Couldn't save the author. Your changes are still here. Try again in a moment." / "Couldn't create the author" / "The article is unchanged. Try again in a moment." (notice inside the panel or dialog) |
|
||
|
||
## Public image 400 bodies
|
||
`{ "status": 400, "error": "unknown_variant", "message": "Unknown variant", "detail": "hero" }` and `{ "status": 400, "error": "unsupported_parameter", "message": "Unsupported parameter", "detail": "width" }`. The original is not served as a fallback.
|
||
|
||
## Articles and Media pagination
|
||
Same states and copy on Articles and Media (Media draws them under the grid or list). Loading next page keeps row height, controls disabled, summary "Loading page 7…". Error "Couldn't load page 7. Showing page 6." with Retry. Out of range "That page doesn't exist. Showing the last page." Page size menu offers 5, 25, 50, 100. Invalid `page` or `size` in the URL (size=30, page=abc, page=0) is replaced by the default without a notice; the API 400 never reaches the user.
|
||
|
||
## Sites and authors pagination
|
||
Groups "Sites: pagination" and "Authors: pagination", 10 states each, same pager as Articles and Media, sizes 5, 25, 50, 100 (default 25). First, middle and last page; single page (count line "N sites" or "N authors" only, no pager, no size select); page-size menu; loading ("Loading page N…", skeleton rows, pager kept and disabled); error ("Couldn't load page N. Showing page M." with Retry, rows and page number kept); empty after search (existing empty state, no pager); search resets to page 1; long labels on mobile. Out of range: ?page past the end is replaced by the last page, with "That page doesn't exist. Showing the last page." (not drawn; as Articles). Details in screens/sites.md and screens/authors.md.
|
||
|
||
## Editor
|
||
Counter without limit ("1,204 words · 7,318 characters"; at 120,000 characters "19,845 words · 120,000 characters"), "Saving…", "Saved", "Couldn't save. Your text is kept. Retry". Link states and the toolbar overflow are drawn in the Editor group (11 states).
|
||
|
||
## Activity export
|
||
Only CSV is offered. "Preparing download…", "Download started", "Couldn't prepare the download", "Nothing to export", "You can't export all activity". The CSV/JSON format control is drawn once, labelled proposed.
|
||
|
||
## Media cleanup, Settings navigation, Activity toggles
|
||
As in screens/settings.md, screens/image-variants.md and screens/activity.md. Sync rule for filter cards: card pressed, chip present and the Outcome segment on Failed are one state; removing any removes all three.
|
||
|
||
## Per-screen copy
|
||
screens/<name>.md, section "Copy per state" (generated from the board source).
|
||
|
||
## SEO round
|
||
Frames: Editor: search and sharing (24), Editor: what the frontend gets (6), Sites: SEO defaults (5), Articles: search status (3). Each is drawn desktop and mobile; light and dark follow the theme switch. None is clock-sensitive: dates in the API preview are fixed sample values. Disabled state: all fields at 40% while saving. Validation: slug taken, canonical not absolute, title template without %title%, excerpt over 300. Suggestions never block saving or publishing. Copy per state: screens/editor.md, articles.md, sites.md.
|