Lossless Changelog
product

Dark Matter Jumps from Astro 5 to Astro 7

A full dependency-upgrade pass took the site from Astro 5 and a stale, workspace-hoisted install to Astro 7 with its own independent lockfile — and uncovered a silent content-collection regression along the way.

Michael StatonMusic Editoraugmented with Claude Code on Claude Sonnet 5

Changelog - 2026-07-06 (#1)

Dark Matter Jumps from Astro 5 to Astro 7

Why Care?

Dark Matter (matter-site) was two majors behind the rest of the Astro Knots fleet. This pass brings it current — Astro 7, the Vercel adapter's v11, and every other dependency at latest — and, in the process, gives the site its own independent pnpm-lock.yaml for the first time instead of quietly riding on the parent workspace's hoisted node_modules.

What's New?

  • Astro 5.16.4 → 7.0.6

  • @astrojs/vercel 9.0.2 → 11.0.2

  • @shikijs/rehype 3.20.0 → 4.3.1

  • satori 0.18.3 → 0.26.0

  • three 0.181.2 → 0.185.1

  • tailwindcss / @tailwindcss/vite patch-bumped to 4.3.2 (safe update pass)

  • Added @astrojs/check + typescript as devDependencies so astro check can run at all (it never had a typecheck story before)

  • The site now installs from its own local pnpm-lock.yaml rather than resolving through astro-knots' root workspace — matching the independent-deploy convention every other site in the fleet already follows

How it Works

The safe patch/minor pass (pnpm update) was a no-op — the site's existing semver ranges already permitted the latest 5.x/9.x/3.x/0.18.x/0.181.x releases, so nothing moved until the major bumps started.

Each major was installed and built in isolation, most-important-first: Astro, then the Vercel adapter, then Shiki/Satori/three. Two real breaks surfaced along the way, both from Astro 7's stricter compiler and Vite 8's new rolldown bundler:

  1. <!-- HTML comment --> inside a JS expression in src/pages/slides/[...slug].astro — legal-ish under Astro 5's compiler, a hard parse error under Astro 7's. Swapped for a /* JS comment */.

  2. An unclosed <BaseThemeLayout> tag in src/pages/design-system/needs-modes.astro — the file is marked "NOT IN USE" in its own header comment, so nobody had hit this until the compiler got stricter. Closed the tag.

  3. A MISSING_EXPORT for MONTHS_FULL/MONTHS_SHORT in src/lib/dates/convertRawDatesToPreferredFormats.ts — these were only ever exported inside the file's export default {...} object, never as named exports, even though src/lib/dates/index.ts re-exported them by name. Astro 5's bundler tolerated the dangling re-export; Vite 8's rolldown does not. Promoted both to export const.

Under the Hood: the quiet content-collection regression

After the Vercel adapter bump, the build succeeded but silently dropped both markdown-backed slide decks — getCollection('slides') returned [] with a console warning ("does not exist or is empty") instead of throwing. Digging into Astro 7's content/utils.js: legacy type: 'content' collections (still used by narratives, changelog, and slides in src/content.config.ts) are no longer auto-wired to a loader unless legacy.collectionsBackwardsCompat: true is set in astro.config.mjs. Without it, defineCollection() accepts the config without complaint, astro sync reports no errors, types generate correctly — but the collection is simply never populated at build or request time.

Set the flag to restore prior behavior 1:1. The longer-term fix — migrating all three collections to explicit loader: glob(...) definitions — is left as follow-up work; the compat flag is the documented escape hatch and carries no known downside today.

Separately, src/data/markdownDecks.ts was refactored from a top-level await getCollection('slides') (a singleton side effect at module-import time) to a memoized async loader, called lazily from getStaticPaths() and the slides index page. This wasn't the root cause of the collection-empty bug, but it's a more resilient pattern regardless of content-layer timing quirks in future Astro versions.

astro check findings (not fixed, not new)

Running astro check for the first time ever on this project (it had no typecheck dependency before this pass) surfaced 124 pre-existing errors — missing @types/node for node:path/node:fs/Buffer/process/crypto usage across API routes, plus a handful of unrelated component-prop typing gaps (portfolio/index.astro, design-system/flare/white-cell.astro). None of these trace back to the packages bumped in this pass, and none block pnpm build. Left untouched per scope; flagging here so they don't get mistaken for a regression later.

Build Verification

  • pnpm build — clean pass after every major bump, and again from a fully fresh rm -rf node_modules && pnpm install

  • Both slide decks (dark-matter-bio-longevity-fund-ii-deck-draft, longevity-science-market-map) confirmed prerendering correctly post-fix, matching pre-upgrade output exactly

  • The one runtime warning in the build log (NocoDB API error: 403) is a pre-existing external API auth issue unrelated to this dependency work — present in the baseline build before any changes too

Files Touched

  • package.json — version bump to 0.2.5, all dependency ranges updated, @astrojs/check + typescript added

  • pnpm-lock.yaml — new, site-local (previously absent; the site was resolving through the parent workspace's hoisted store)

  • astro.config.mjs — added legacy.collectionsBackwardsCompat: true

  • src/pages/slides/[...slug].astro — fixed invalid HTML comment in JS expression; switched to lazy markdown-deck loading

  • src/pages/slides/index.astro — switched to lazy markdown-deck loading

  • src/pages/design-system/needs-modes.astro — closed unclosed <BaseThemeLayout> tag

  • src/lib/dates/convertRawDatesToPreferredFormats.ts — promoted MONTHS_FULL/MONTHS_SHORT to named exports

  • src/data/markdownDecks.ts — refactored from top-level-await singleton to memoized lazy loader