10 KiB
10 KiB
This release adds sites, authors and search and sharing data (SEO) to articles: every article now belongs to a site, can credit authors, and carries what a website needs to be found and shared. Several API shapes change, so read the upgrading notes if you call the API.
New
Sites
- Every article belongs to exactly one site, and exactly one site is the default. Existing articles are moved to the default site, which is created from
PUBLIC_URLon the first start. - The new Sites screen under Settings lets the owner add, edit, delete and set the default site, with a name, a key, a base address, a default robots setting, a locale and a default social image. Deleting a site with articles asks where to move them.
- The editor and the articles list let you choose an article's site, and the articles list can be filtered by site.
- A site also holds site-wide search defaults: a site name, a title template (it must contain
%title%) and a default description, with a live example while you type.
Authors
- The new Authors screen manages public bylines, with or without an account: name, slug, bio, avatar, website and up to five social links. Owners and admins manage every author, and anyone can edit the author linked to their own account.
- Articles credit an ordered list of authors, and the first is the primary byline. The editor offers a search box with keyboard and pointer reordering, and a "Create author" shortcut for owners and admins.
- Users without an author profile are offered to create their own from the editor, and a new article is credited to its creator's author when there is one.
- Deleting an author that is credited on articles asks who takes over the credits, or whether to remove them.
Search and sharing
- An article has a slug, an excerpt, a search title and description, a cover image with its alt text, a social title, description and image, a canonical address, a noindex flag and a list of dismissed suggestions.
- The slug is generated from the title, is unique per site and can be changed at any time; an empty slug regenerates it from the title.
- The editor has a new Search and sharing section with soft length counters, fallback chips that show where each value comes from, search and social previews, and a "What the frontend gets" view of the resolved data.
- The editor checks the article as you type, without saving, and shows at most three suggestions with links to the field to fix. Any suggestion can be dismissed for an article.
- Articles list items show a search status chip, and a "Needs attention" toggle keeps only the articles that still have suggestions.
GET /v1/article/{id}/seoreturns the resolved search and sharing data (title with the site template, description, canonical address, robots, Open Graph, Twitter, image, authors and ready JSON-LD), so a frontend can render its meta tags without reimplementing the fallback chain. RenewCMS itself renders no page.GET /v1/site/{key}/sitemaplists the published URLs of a site.- The Integration page documents the new search and sharing routes.
Lists
- The Sites and Authors lists are paged, with a page size of 5, 25, 50 or 100, a server-side search, and a page, size and search kept in the address so a reload or a shared link opens the same view. A page past the end goes to the last page with a notice.
Improvements and fixes
- An image used as a cover, a social image, an author avatar or a site default social image now counts as used. It shows in the media library usage list, stays out of the unused filter, and is repointed by a merge or a purge.
- Deleting an image never fails because of its uses: the covers, social images, avatars and site images that point at it are cleared.
- The image picker names the selected image even when it is outside the first 100 media items, without requesting the whole list.
- Author profile pictures now show everywhere in the app.
- Every toggle switch in the app now uses one shared component, so they all have the same, correct geometry.
- Identical SEO checks are answered from a bounded cache, and a failed check is never cached.
- The activity log has two new filters, Sites and Authors, and records site, author and SEO field edits. Free-text fields record a size change and never their text.
- The Create author dialog and the Integration screens match the design on mobile.
API
GET /v1/site/lists the sites, the default first. It takesq,pageandsizeand sends the matching total inX-Total-Count; withoutpageandsizeevery site is still returned, as a JSON array. Read access needs a verified session or an API key.POST /v1/site/,PATCH /v1/site/{id},PATCH /v1/site/{id}/defaultandDELETE /v1/site/{id}?reassign_to={id}are for the owner and accept a session only. Errors are plain text tokens:site_key_taken(409),site_has_articles(409),default_site(403),key_immutable,invalid_site_url,invalid_locale,invalid_title_template,image_not_found,use_set_defaultandinvalid_reassign(400), andsite_not_found(404).GET /v1/site/{key}/sitemapis public and returns[{ url, modified_at, noindex }]for the online articles of a site, paged withpageandsizeand with the total inX-Total-Count.GET /v1/author/lists authors, newest first, withq,pageandsize, as{ items, total, page, size }and the total inX-Total-Count.POST /v1/author/andDELETE /v1/author/{id}?reassign_to={id|none}are for owners and admins,POST /v1/author/mecreates the caller's own author and answersslug_adjusted, andPATCH /v1/author/{id}is open to owners, admins and the linked account. All of them accept a session only. Errors includeauthor_not_found,user_not_found,author_slug_taken,author_has_articles,user_already_linked,author_already_linked,invalid_slug,invalid_reassign,image_not_found,bio_too_long,invalid_url,too_many_linksandauthor_rights.GET /v1/article/takessite=<key>andseo=ready|suggestions|hidden. Items gainsite_id,slug,excerpt,authors,seo_statusandseo_suggestions, andcountsgainsuggestions.PATCH /v1/article/{id}takesbody,site_id,author_idsand the twelve SEO fields.cover_image_idandsocial_image_idacceptnull. A slug already used on the target site answers409slug_takenwith the headerX-Slug-Suggestionholding the first free slug.GET /v1/article/{id},POST /v1/article/,PATCH /v1/article/{id},PATCH /v1/article/{id}/publishandPATCH /v1/article/{id}/unpublishreturnsite_id,authorsand the twelve SEO fields.GET /v1/article/{id}/seoreturns the resolved search and sharing data. It is public for online articles, and a verified session or API key also reads drafts.POST /v1/article/{id}/seo/checkevaluates an article without saving, with optional overrides, and returns the status, the suggestions and whether the slug is free.GET /v1/auth/mealso returnsauthor, the linked author of the caller ornull.GET /v1/media/{id}reads one image with the fields of a media list item. A missing image answers404and a malformed id400.GET /v1/activityaccepts the newsitesandauthorscategories, with the eventssite.create,site.edit,site.set_default,site.delete,author.create,author.editandauthor.delete.- Changed:
PATCH /v1/article/{id}no longer acceptstitle, and{},{"body": null}or any object without an accepted field now answers400instead of setting an empty body.{"body": ""}still empties the body. - Changed:
GET /v1/media/{id}/usagestays an array, and every item gainstype(article,authororsite) andfieldswithout losingid,titleandpublished. Authors and sites that use the image are now listed, without apublishedkey. - Changed:
POST /v1/media/mergeandPOST /v1/media/purgealso reportsites_updatedandauthors_updated. - Changed:
X-Total-Countis now exposed to browsers through CORS.
Under the hood
- Add the site, author and article SEO domains, repositories, mappers and use cases behind the existing layers, with a resolver and a checker for the search and sharing data.
- Upgrade
jwtauthto v5.4.0 andlestrrat-go/jwxto v3, and refresh the related indirect dependencies. - Look up authors, sites and credits in batches that work on SQLite, MySQL, MariaDB and PostgreSQL.
- Document the routes in
docs/api.mdanddocs/api/articles.md, the measured cost of the?seo=filter indocs/performance.md, and the layering indocs/architecture.md. - Add the specifications, design checks and Go and Vitest suites for sites, authors, search and sharing, and list pagination.
Upgrading
- Replace the binary, or pull the new image. Back up the database first: the migration changes existing rows.
- The first start after the upgrade creates the sites and authors tables, seeds the default site (name "Default", key "default") from the scheme and host of
PUBLIC_URLand moves every article to it. An unparseablePUBLIC_URLstops the migration, so check it before upgrading.PUBLIC_URLis never read for sites afterwards. - The same start adds the new columns, gives every existing article a slug generated from its title (in id order within each site, with
-2,-3on conflicts) and creates the unique(site_id, slug)index. A deleted article now frees its slug. The backfill writes in batches of 500 rows, a start that was interrupted resumes where it stopped, and a second start changes nothing. - Existing sites get the default title template
%title% | %site%, an empty site name and an empty default description. - No new environment variable is needed.
- Any script that sends
PATCH /v1/article/{id}with atitle, an empty object or a null body must change, as described in the API section. - Reading
GET /v1/media/{id}/usageas an array of articles still works, but now also yields authors and sites. Filter ontypeif you only want articles.
Known limitations
- The
?seo=filter andcounts.suggestionsassess every visible article in memory, so their cost grows with the number of articles. On the development machine, 5,000 articles of about 5 KB each answer in roughly 300 ms. - Only the owner can manage sites, and an API key cannot write sites or authors.