Repository navigation
feat: migrate content from Contentful to EmDash - #1196
Merged
Merged
Conversation
fbuireu
force-pushed
the
feat/migrate-to-emdash
branch
from
October 10, 2026 06:23
209481f to
b28cb13
Compare
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
EmDash runs inside the site Worker over its D1 (content) and R2 (media) bindings, with its admin at /_emdash/admin. Pages read content through Astro live collections per request, behind the Workers cache, which EmDash purges by tag on every publish (ADR 0021, ADR 0022 superseding the prerendering of ADR 0011). - seed/seed.json holds the content model; Tags become the tag taxonomy and the Author relation gets a field on both ends - src/worker.ts adds EmDash's scheduled handler and plugin bridge - scripts/importContentful copies every entry and asset into an empty EmDash (pnpm import:contentful) - publish-article.yml is gone: a publish no longer needs a rebuild
…ited emailDelivery is a native plugin holding email:provide and the exclusive email:deliver hook. It hands every invitation, magic link and recovery email to EmailClient.sendCmsEmail, the contact form's Resend client and sender, tagged cms.
…n every minute - emdash and @emdash-cms/cloudflare 1.2.0, which bounds the 404-log scan (emdash-cms/emdash#3748), so the cron goes back to every minute - the admin ships English only (admin.locales), a smaller bundle - an Author's social network rows carry a name beside the URL; the import names each after its host
… and grow the slider's markers with their slide - each entry is current from its heading crossing the reading line until the next one does: two scroll-driven flags and a style query, so the marker scales and the label slides on a transition - a slider with dots uses native ::scroll-markers where supported, each widening and turning gold as its slide crosses the centre
…llection - an Author is a byline; job title, company and social networks are byline custom fields (one 'Name | URL' line per network, http(s) only, since a byline field cannot be a repeater) and the JSON-LD is unchanged - the import registers the fields, creates the bylines and credits each Article; it now needs a token with the admin scope - bylineCache purges the bylines cache tag on byline:afterSave and byline:afterDelete, which EmDash does not purge itself
…ngs and menus - Articles and Projects render through emdash/ui's PortableText; the DTO prepares every block (anchors and section scopes, CDN images with blur, classified links, YouTube/Vimeo players, invalid and raw HTML blocks dropped) and the components only print it (ADR 0023, ADR 0012 amended) - videoEmbed leaves the editorial plugin for EmDash's own blocks - per-entry SEO on Articles, site settings and header/footer menus come from EmDash with today's values as the DTO's fallback; editor URLs are checked in the DTO - EmDashHead/EmDashBodyStart/EmDashBodyEnd are mounted; EmDash owns the shared head tags and Seo.astro keeps only what it does not emit - bylineCache holds bylines:read, without which EmDash ignores its hooks; emailDelivery uses hooks.email-transport:register - frame-src allows the Vimeo player; the slider's marker rules are flat so lightningcss keeps their selectors
fbuireu
force-pushed
the
feat/migrate-to-emdash
branch
from
October 10, 2026 13:29
e833e64 to
d48eeb8
Compare
fbuireu
enabled auto-merge (squash)
October 10, 2026 17:34
fbuireu
disabled auto-merge
October 10, 2026 17:34
Owner
Author
|
🎉 This PR is included in version 1.26.0 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
This branch was successfully deployed
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.
Summary
Contentful is replaced by EmDash, which runs inside the site Worker: content in the
DBD1 binding, media in theMEDIAR2 binding, admin at/_emdash/adminwith passkeys.cacheCloudflare()+CONTENT_CACHEroute rules). Every content route carries every collection tag plus thetagtaxonomy tag, and EmDash purges them on publish, sopublish-article.ymland the rebuild it triggered are gone. ADR 0022 supersedes ADR 0011.src/live.config.ts) →application/entitiesloaders →CmsClientLive(in-processgetEmDashCollection/getEmDashReferences, published entries only).seed/seed.json. Tags become thetagtaxonomy, and the Author relation gets a field on both ends, so a listing needs no reference query per article.src/worker.tswraps Astro's handler with EmDash's scheduled handler (cron every 15 min until cleanup404Log scans the 404 log on every cron tick — ~13M rows read/day at the recommended every-minute schedule emdash-cms/emdash#3748 ships) and the plugin bridge.pnpm import:contentfulcopies every entry and asset into an empty EmDash. It assigns terms in batches of 30 to stay under D1's 100 bound variables.Before this can pass
E2E (preview)Previews share the development D1, which is empty until imported:
CLOUDFLARE_ENV=development pnpm build && pnpm wrangler deploy --env developmentbiancafiore-developmentworkers.dev addresscontent:read,content:write,media:read,media:write,taxonomies:managepnpm import:contentful --dry-run, thenpnpm import:contentful, withEMDASH_URL,EMDASH_TOKENandCONTENTFUL_*setAfter merge
On the empty production database, CI deploys, smoke fails, and production rolls back to the Contentful build. That is expected. Then, at a quiet hour:
pnpm wrangler versions list --env production, thenpnpm wrangler rollback <version-id> --env productionto promote the new versionhttps://biancafiore.me/_emdash/admin, with sample content untickedTest plan
pnpm verify(format, typecheck, astro check, unit + coverage)E2E (preview)green once the development database is imported