Skip to content

feat: migrate to Astro 6 + Content Layer API#28

Open
nathanredblur wants to merge 3 commits into
mainfrom
feat/astro-6-migration
Open

feat: migrate to Astro 6 + Content Layer API#28
nathanredblur wants to merge 3 commits into
mainfrom
feat/astro-6-migration

Conversation

@nathanredblur

Copy link
Copy Markdown
Owner

Summary

Migrates the site from Astro 5.17.1 → 6.2.1 following the official upgrade guide.

Ran pnpm dlx @astrojs/upgrade and followed the breaking changes through: bumped @astrojs/cloudflare 12 → 13.3, @astrojs/svelte 7 → 8.1, wrangler 4.62 → 4.87, plus the Vite 7 / Zod 4 / Shiki 4 transitive upgrades.

Content collections — migrated to Content Layer API

Astro 6 removes the legacy content collections API. The legacy.collectionsBackwardsCompat flag is advertised as a migration helper, but in 6.2.1 it does not preserve entry.render() at runtime (build still fails with TypeError: entry.render is not a function), so the legacy-first / migrate-later plan wasn't viable. Done in this PR:

  • src/content/config.tssrc/content.config.ts using glob() loader from astro/loaders. generateId strips /index so slugs like guide/ keep matching the old entry.slug
  • entry.slugentry.id across content-utils, [...slug], rss.xml, PostCard, PostPage, ArchivePanel
  • entry.render()render(entry) from astro:content
  • Cover image basePath resolves from entry.filePath instead of getDir(entry.id) (the id no longer contains the file path)
  • z now imported from astro/zod (astro:content export is deprecated)

Cloudflare adapter v13 breaking changes

  • wrangler.jsonc: main field → "@astrojs/cloudflare/entrypoints/server" (v13 deletes the old _worker.js/index.js path)
  • Static output moved under dist/client/, so pagefind --site distpagefind --site dist/client in the build script
  • .wrangler/ added to .gitignore (new dev mode writes local state there)

Dev workaround: debug package crashes workerd runner

astro dev returned HTTP 500 on every request with ReferenceError: module is not defined — the CJS debug package is pulled transitively by micromark and stylus, and @cloudflare/vite-plugin's workerd runner has no module global. Worked around here by aliasing debug to an ESM shim backed by obug (same replacement astro core uses after withastro/astro#15565).

Upstream fix proposed in withastro/astro#16569 — applies the same alias inside @astrojs/cloudflare so nobody needs the local workaround anymore. Once that ships in a @astrojs/cloudflare release, remove:

  • src/shims/debug.js
  • the debug alias in astro.config.mjs
  • the obug dep from package.json

Both locations carry a TODO pointing at #16569.

Test plan

  • pnpm check — 0 errors, 0 warnings
  • pnpm build — all 12 prerendered pages rendered with content, 3 resume PDFs generated, Pagefind indexes 6 pages / 1833 words
  • pnpm dev/, /posts/:slug/, /blog/, /about/, /archive/, /projects/ all return 200 with full content
  • pnpm wrangler dev against the built output — all routes 200 under the real Workers runtime
  • Deploy preview on Cloudflare Workers CI

Upgrade astro 5.17.1 -> 6.2.1 via @astrojs/upgrade. Brings
@astrojs/cloudflare 12 -> 13.3, @astrojs/svelte 7 -> 8.1, plus Vite 7 /
Zod 4 / Shiki 4.

Astro 6 removes the legacy content collections API. The
legacy.collectionsBackwardsCompat flag doesn't preserve entry.render()
at runtime in 6.2.1, so migrate collections to the Content Layer API:

- src/content/config.ts -> src/content.config.ts using glob() loader
  from astro/loaders; generateId strips /index so slugs match the
  legacy filesystem-based ids
- Replace entry.slug with entry.id across content-utils, rss.xml,
  [...slug], PostCard, PostPage, ArchivePanel
- Replace entry.render() with render(entry) imported from astro:content
- Resolve cover image basePath from entry.filePath instead of
  getDir(entry.id) (id no longer contains the file path)

Cloudflare adapter v13 breaking changes:

- wrangler.jsonc main -> "@astrojs/cloudflare/entrypoints/server"
- Static output moved to dist/client/, so pagefind --site dist/client

Bump wrangler 4.62 -> 4.87 to satisfy @cloudflare/vite-plugin peer.

Known issue: astro dev currently returns 500 "module is not defined"
from the @cloudflare/vite-plugin runner-worker. Production build and
wrangler dev on the built output both work; local dev via
`pnpm wrangler dev` is the workaround until the dev runner is fixed.
astro dev 500s on every request with "module is not defined" when the
@cloudflare/vite-plugin runner loads a component whose dep graph
includes the CJS `debug` package: it references `module.exports`, and
`module` is not a global in the workerd runner.

Astro core already replaced `debug` with `obug` (ESM fork) in
withastro/astro#15565, but integrations like expressive-code still
pull `debug` via their markdown/rehype pipelines
(expressive-code/expressive-code#439 tracks the same error).

`obug` only exposes named exports, so a raw alias breaks consumers
that do `import debug from "debug"`. Add `src/shims/debug.js` which
re-exports obug and re-exposes a default, then wire it in via
vite.resolve.alias. Install obug as a direct dependency so the shim
resolves in the Workers runner (it's only a transitive dep of astro
otherwise).

Also add .wrangler to .gitignore - the new dev mode writes local
state there.

Verified: all routes (/, /blog/, /posts/..., /about/, /archive/,
/projects/) return 200 under pnpm dev; pnpm check and pnpm build stay
green.
Add TODO pointers next to both the astro.config.mjs alias and
src/shims/debug.js so the workaround is easy to retire once
withastro/astro#16569 ships in a @astrojs/cloudflare release.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant