Files

46 lines
6.3 KiB
Markdown

# Routes
| Route | Screen | Query | API |
|---|---|---|---|
| /settings | Settings (Version, Media card, Media cleanup, Retention) | none | GET/PATCH /v1/media/purge-settings, GET/PATCH /v1/settings |
| /settings/media/variants | Image variants (admin) | none | GET/PATCH/DELETE /v1/image-variants, POST /v1/image-variants/{name}/purge |
| /settings/media/cache | Cache (admin) | none | GET /v1/image-variants/cache, POST /v1/image-variants/cache/purge {scope: all|unused|variant|image} |
| /media | Media library | page, size, q, filter, sort, view | GET /v1/media/?page=&size=&q=&filter=&variants=&sort= (page, size; total in the `X-Total-Count` header) |
| /media (detail) | Variants tab | none | GET /v1/media/{id}/variants, POST and DELETE /v1/media/{id}/variants/{name} |
| /articles | Articles list | page, size, tab, q | GET /v1/article/?page=&size=&q=&status= (page, size; total in the `X-Total-Count` header; array body unchanged) |
| /activity | Activity | q, actor, category, outcome, security, range, from, to, page, size | GET /v1/activity (page, size), GET /v1/activity/export (shipped, CSV) |
| /integration | Integration | none | none |
| /settings/sites | Sites (owner only; other roles get a 403 page and no sidebar entry): list, add and edit slide-over, delete with reassignment. The key is read-only after creation | none | GET/POST /v1/site/, PATCH/DELETE /v1/site/{id} (DELETE takes `reassign_to`) |
| /authors | Authors, all roles. Owner and admin: list, search, add and edit slide-over, delete with reassignment. Other roles: read-only list and detail | q, page, size | GET/POST /v1/author/, PATCH/DELETE /v1/author/{id}, POST /v1/author/me |
| /articles | Articles list gains Authors column; Site column and filter when more than one site | site | GET /v1/article/?site={key} |
| /article/:id/edit | Editor gains the "Site and authors" section (Site select and authors, any role that can edit the article) | none | PATCH /v1/article/{id} {site_id, author_ids[]} |
| /profile | Profile gains the "Author profile" card, all roles | none | POST /v1/author/me |
| /integration/api-keys | API keys | none | GET/POST /v1/api-key, DELETE /v1/api-key/{id} |
## Pagination in the URL (Articles, Media)
`/articles?page=2&size=50` and `/media?page=7&size=50`. Parameter names follow the repo (activity already uses `page` and `size`). Allowed sizes 5, 25, 50, 100. Defaults `page=1`, `size=25`, omitted from the URL when default. Changing search, tab, filter or size resets `page` to 1. `page` above the last page redirects (replace) to the last page and shows "That page doesn't exist. Showing the last page." An invalid `size` falls back to 25.
**API:** `GET /v1/article/` accepts `page` (default 1) and `size` (5, 25, 50, 100; default 25), as `GET /v1/activity` does. The body stays a JSON array so existing consumers keep working; the total comes back in `X-Total-Count` (the response shape is to be confirmed with the specifier). Anonymous callers only see online articles, and the total counts only those. Invalid `page` or `size` answers 400, the same as Activity.
**Media API:** `GET /v1/media/` takes the same `page` and `size`, with the same 400 and the total in `X-Total-Count`; the array body stays. The earlier `cursor` and `limit` parameters are replaced by them.
**Page size memory:** the size chosen on Articles, Activity or Media is remembered for the user and used when the URL has no `size`; an explicit `size` in the URL wins.
**SPA:** never shows that 400. A `size` outside 5, 25, 50, 100 or a `page` that is not a positive integer is replaced in the URL by the default (`history.replace`), silently. A `page` past the last page is replaced by the last page and the notice "That page doesn't exist. Showing the last page." appears.
## Activity pagination
`page` and `size`, allowed sizes 5, 25, 50, 100, default 25 (as implemented).
## Activity export
`GET /v1/activity/export`: implemented. CSV only, synchronous (one streamed download, no job, no progress, no later notification). Accepts the list filters q, actor, category, outcome, security, range, from, to. Owner and admin only; others get 403. "Export current view" calls it with the active filters. "Export all activity" calls it with no filters and an optional `from`/`to` range. JSON (`format=json`) is **proposed**: new backend feature.
## Public image request
`/media/photo.png?v=<variant-name>`. Unknown or disabled variant: 400 `{ "status": 400, "error": "unknown_variant", "message": "Unknown variant", "detail": "<name>" }`. Any other query parameter: 400 `{ "status": 400, "error": "unsupported_parameter", "message": "Unsupported parameter", "detail": "<parameter>" }`. Missing source image: 404.
## Sites and authors in the URL
`/articles?site=journal` filters by site key; it combines with `page`, `size`, `tab` and `q`, and resets `page` to 1 when it changes. An unknown key is dropped from the URL with no error. `/authors?q=camille&page=2&size=25` follows the same pagination rules as Articles. Deep links: `/authors?edit={slug}` and `/settings/sites?edit={key}` open the slide-over for owner and admin (authors) and the owner (sites); an unknown value shows the info toast "That author no longer exists" or "That site no longer exists". For other roles `/authors?edit={slug}` opens the read-only detail, and `/settings/sites` and its `?edit=` link show the 403 page "You don't have access to Sites".
Sites pagination: `/settings/sites?q=&page=&size=` with the same rules as Articles (sizes 5, 25, 50, 100; default 25; defaults omitted; search and size changes reset to page 1; a page past the end falls back to the last page). API: GET /v1/site/?q=&page=&size=, total in `X-Total-Count` (design assumption). Authors: `/authors?q=&page=&size=` as above.
## SEO
No new page routes. The panel and dialog are overlays on `/article/:id/edit`: `?panel=seo` (optionally `&field=seo_title|seo_description|slug|cover|authors|body` for the suggestion jump) and `?dialog=seo-api`. `/articles?seo=suggestions` is the Needs attention filter. API: GET /v1/article/{id}/seo, GET /v1/site/{key}/sitemap?page=&size=, PATCH /v1/article/{id} (new fields), PATCH /v1/site/{id} {site_name, title_template, default_description, social_image_id, default_robots}, GET /v1/article/?seo=ready|suggestions|hidden. 401 without a session; 403 owner_only on site SEO fields; 409 slug_taken {suggestion} on PATCH slug; 400 on invalid canonical_url or title_template.