Headless CMS: in-place edit, CDN-cacheable pages, hide unpublished posts - #1264
Draft
joepio wants to merge 23 commits into
Draft
Headless CMS: in-place edit, CDN-cacheable pages, hide unpublished posts#1264joepio wants to merge 23 commits into
joepio wants to merge 23 commits into
Conversation
Generated Next.js and SvelteKit sites no longer list, search, or route forks or blog posts with a missing or future published-at. Cmd/Ctrl+E and an Edit this page link open the Data Browser edit form; --cms-url covers a split editor origin. Blogpost cover-image and published-at are recommended so incomplete posts can be saved. Co-authored-by: joepmeindertsma <joepmeindertsma@gmail.com>
The empty guide is now the product walkthrough: apply the template, generate Next.js or SvelteKit, edit from the live site. The Astro guide no longer tells readers to use a Drive DID as the server URL. Co-authored-by: joepmeindertsma <joepmeindertsma@gmail.com>
Co-authored-by: joepmeindertsma <joepmeindertsma@gmail.com>
isListedCmsResource and cmsEditUrl are the tested core of the generated-site publish filter and edit-from-site URL. Templates keep local copies so they do not depend on an unreleased lib export. Co-authored-by: joepmeindertsma <joepmeindertsma@gmail.com>
`/` now serves the Website resource's homepage property instead of whichever page happens to have path `/`. Nav and the site title keep the current locale prefix so `/nl/blog` → Home is `/nl`. Next.js updates `<html lang>` from the URL, and Svelte blog cards no longer crash when description is missing. Co-authored-by: joepmeindertsma <joepmeindertsma@gmail.com>
Template e2e now scaffolds with --cms-url pointing at the Data Browser, asserts that origin on Cmd/Ctrl+E, checks Next.js html lang, and clicks Home from /nl/blog. Tutorial and coverage map match. Co-authored-by: joepmeindertsma <joepmeindertsma@gmail.com>
Next caches `fetch` during `next build`. A collection that is briefly empty after applying the Website template then stays empty on `next start`. The catch-all route is now force-dynamic and the server store uses cache: no-store so blog listings re-query AtomicServer on each request. Co-authored-by: joepmeindertsma <joepmeindertsma@gmail.com>
cache: no-store on the store fetch made /_not-found fail static generation (DYNAMIC_SERVER_USAGE). The root layout is now force-dynamic so 404s and listings both re-query AtomicServer. Co-authored-by: joepmeindertsma <joepmeindertsma@gmail.com>
isListedCmsResource took `now` as a positional number, and listings used `.filter(isListedCmsResource)`. The index (0, 1, …) became `now`, so every post looked unpublished. `now` is now on an options object. Co-authored-by: joepmeindertsma <joepmeindertsma@gmail.com>
`.filter(isListedCmsResource)` is a type error once `now` lives on an options object. Call sites now pass the resource explicitly. Co-authored-by: joepmeindertsma <joepmeindertsma@gmail.com>
Generated sites need public URL lists that already dropped forks and unpublished posts. Keep the XML builders next to isListedCmsResource so the filter contract is unit-tested, not only asserted in Playwright. Co-authored-by: joepmeindertsma <joepmeindertsma@gmail.com>
Generated Next.js and SvelteKit sites now expose /sitemap.xml, /rss.xml, and /robots.txt from the same public-content filter as listings. Blog cards on /nl/blog keep the language prefix instead of dropping back to the default-language path. Co-authored-by: joepmeindertsma <joepmeindertsma@gmail.com>
The Website template e2e now points homepage at About, forks that page under a leak-detectable title, and asserts sitemap/RSS omit unpublished posts. Tutorial and coverage map the new public-feed routes. Co-authored-by: joepmeindertsma <joepmeindertsma@gmail.com>
SvelteKit e2e failed because a single /query timeout threw out of page.evaluate instead of retrying. Catch the timeout and open About from the sidebar when it is already visible. Co-authored-by: joepmeindertsma <joepmeindertsma@gmail.com>
A leftover next-server on :3000 made the following e2e run fail with EADDRINUSE even after kill-port in the previous test's finally block. Co-authored-by: joepmeindertsma <joepmeindertsma@gmail.com>
Chromium intercepts Control+E, so a synthetic keydown is a weak signal. The footer Edit this page control uses the same URL; clicking it is the reliable popup. SvelteKit now registers the hotkey with addEventListener. Co-authored-by: joepmeindertsma <joepmeindertsma@gmail.com>
On /nl/blog the test clicked a Home link that had not yet resolved to /nl, so the URL never left /nl/blog. Co-authored-by: joepmeindertsma <joepmeindertsma@gmail.com>
Prerender/ISR public paths, send Cache-Control s-maxage instead of no-store, set html lang from the URL in the initial HTML, and keep blog search client-side so listings stay cacheable. Co-authored-by: joepmeindertsma <joepmeindertsma@gmail.com>
Next.js statically analyzes `export const revalidate` and rejects an imported constant, which broke `next build`. Co-authored-by: joepmeindertsma <joepmeindertsma@gmail.com>
kill-port missed an IPv6 next-server on :3000, so pnpm start failed with EADDRINUSE after a successful ISR build. Co-authored-by: joepmeindertsma <joepmeindertsma@gmail.com>
instrumentation.ts does not run in generateStaticParams workers, so typed .props (blocks, menu items) were empty in prerendered HTML. Co-authored-by: joepmeindertsma <joepmeindertsma@gmail.com>
Prerendered files are served by sirv and drop hooks.server.ts headers. SSR keeps first-byte lang/content and sends s-maxage for shared caches. Co-authored-by: joepmeindertsma <joepmeindertsma@gmail.com>
Wire @tomic/edit-mode into generated Next.js sites so Edit this page and Cmd/Ctrl+E turn headings and body text into contentEditable fields that save to Atomic on blur. The agent secret stays in localStorage; Cmd/Ctrl+Shift+E still opens the Data Browser. Co-authored-by: joepmeindertsma <joepmeindertsma@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Related Issues
Investigation of the Website-template CMS. No single issue number; closes the tutorial/docs gap and product holes called out in
planning/website-templates.md.Checklist
What this is
Atomic already has a capable CMS (Website template + Next.js/SvelteKit generators, i18n, forks). This PR fixes the high-impact product holes, then makes generated pages CDN-friendly, then wires in-place WYSIWYG into the Next.js template.
In-place editing (Next.js)
Generated Next.js sites render
@tomic/edit-mode(EditModeProvider+Editable). Edit this page / Cmd/Ctrl+E turn the heading and body into contentEditable fields; blur saves to Atomic. The editor signs in with an agent secret stored inlocalStorageon the site origin — it is never baked into the public bundle. Cmd/Ctrl+Shift+E and Open in Data Browser still open/app/edit?subject=…. SvelteKit keeps the Data Browser footer link (the package UI is React).CDN / first-byte locale
generateStaticParams+ ISR (revalidate = 60). Catch-all layout owns<html lang>so/nl/...islang="nl"in the first HTML byte. Ontologies register at store load so SSG includes blocks/menus (instrumentation.tsdoes not run in generateStaticParams workers).Cache-Control: public, s-maxage=60, stale-while-revalidate=86400(prerendered files are served by sirv and would drop hook headers).%lang%is filled from the URL on the first byte. Blog posts are awaited during SSR so listings are in the HTML./blogis not?search=-dynamic.Earlier in this PR
Tutorial, unpublished/fork filtering, homepage property, locale nav, sitemap/RSS/robots.
Testing
browser/lib/src/cms.test.ts— listing filters,cmsEditUrl, sitemap/RSS helpers,cmsPathToSlug/CMS_CDN_CACHE_CONTROL.template.spec.tsNext.js: ISR production build, homepage About, first-byte locale, CDNCache-Control, in-place edit (assertInPlaceEdit), Data Browser link on the sign-in banner.template.spec.tsSvelteKit: same first-byte locale/content andCache-Control; footer Edit this page still opens the Data Browser.