Skip to content

chore(deps): try Nuxt Content v4 - #1470

Draft
larbish wants to merge 1 commit into
mainfrom
test/content-v4-next
Draft

larbish wants to merge 1 commit into
mainfrom
test/content-v4-next

Conversation

@larbish

@larbish larbish commented Oct 16, 2026

Copy link
Copy Markdown
Collaborator

Warning

Draft for tracking what blocks Docus from moving to Nuxt Content v4. It's not meant to be merged. v4 is installed from a local tarball in .content-v4/ (git-excluded), so git-triggered builds fail. Previews are deployed from a local build with vercel build && vercel deploy --prebuilt.

Preview: https://docus-dg15la34v-nuxtlabs.vercel.app

This PR replaces @nuxt/content v3 with the Nuxt Content v4 POC (@nuxt/content4, nuxt/content-v4-temp#7) through a pnpm override, without upgrading any other dependency. The checklists below are everything still missing upstream for Docus to run on v4 without any change on its side. Build-time workarounds live in layer/modules/content-v4.ts, which does nothing on v3.

Nuxt Content v4

Worked around in this PR:

  • @sqlite.org/sqlite-wasm isn't a dependency, but the default hybrid mode needs it (v3 shipped it) → layer/package.json
  • Code highlighting only works with nuxt/content-v4-temp#7, and only after a local fix. That PR makes shiki an optional peer that it only looks for in the app's own dependencies, so a layer setup crashes. The fix makes it a regular dependency resolved from the module. nuxt/content-v4-temp#6 breaks production builds, because its whole-object import.meta.content replace never applies → pnpm-workspace.yaml (locally patched tarball)
  • Runtime content queries hang on serverless. The server fetches its own snapshot (/__nuxt_content/snapshot/<name>.json), which on Vercel only exists on the CDN, so the request reaches v4's /__nuxt_content/** handler and waits on itself until the 300 s timeout. mode: 'server-only' doesn't help: with a v3 content.config.ts the server instance is hard-coded to mode: 'hybrid', and server-only also stops the public snapshot from being generated → content-snapshot.ts, content-v4.ts
  • body is a bare node array instead of v3's { type: 'minimark', value, toc }, so the page TOC is empty. The workaround rebuilds the TOC from the nodes the way @nuxtjs/mdc did → toc.ts, DocsAsideRight.vue
  • .navigation.yml files are ignored, because the YAML plugin isn't registered in v3 mode, so folder titles and icons are lost. The workaround reads them at build time and merges them back into the navigation → content-v4.ts, navigation.ts
  • Components in components/content/ aren't resolved, because v3 registered that folder globally without a prefix and v4 doesn't. :assistant-demo rendered as a raw <assistant-demo> tag → content-v4.ts
  • Links in content are unstyled, because ContentRenderer hardcodes a: NuxtLink, which bypasses Nuxt UI's ProseA. External links also lose v3's rel="nofollow" → DocsContentLink.vue, [...slug].vue, landing.vue
  • #build/content/components.mjs statically re-exports every component in the app, so the initial JS of a docs page grows from 277 KB to 868 KB gzipped. Partially fixed: loading the components on demand brings it down to 428 KB → content-v4.ts
  • "Edit this page" links broke, because stem is now relative to the collection folder and extension is .md instead of md → content-v4.ts, [...slug].vue
  • Frontmatter fields outside the schema are no longer under meta, so sitemap: false and modifiedAt were ignored → urls.ts
  • queryCollection(event, 'missing') throws immediately instead of returning a rejected promise, so /api/__sitemap__/urls returned 500 at runtime when a collection doesn't exist → urls.ts
  • No @nuxt/content/preview (field/group), so nuxt.schema.ts failed to load. The workaround is a local copy of v3's helpers → preview.ts, nuxt.schema.ts

No workaround:

  • The root @nuxt/content package exports none of the v3 types (ContentNavigationItem, Collections, PageCollections, DefinedCollection, TocLink…), and type generation fails silently in the layer, so collection names resolve to never. That gives 22 errors in nuxt typecheck layer.
  • Even with components loaded on demand, initial JS on docs pages stays about 150 KB gzipped above v3 (428 KB vs 277 KB), and the landing page is 383 KB vs 249 KB.
  • Only Markdown files are read in v3 mode. .yml/.json files are skipped without a warning, because the yaml()/json() plugins aren't registered, and .csv has no plugin at all. So v3 data collections in those formats come back empty. Docus doesn't define any, but users extending it can, and the .navigation.yml workaround above only patches the navigation.
  • The server bundle hard-codes the build machine's absolute content path (/Users/…/docs/content) as a fallback source. It's unused while the snapshot loads, but if the snapshot ever fails to load, collections would likely come back empty instead of throwing an error. The local path also ships in the deployed function.

comark / comark-content

  • The SQL plugin of comark-content@0.4.1 doesn't coordinate index builds: concurrent first queries of a collection each rebuild its table, and one can drop it while another reads, so pages, navigation or prev/next links come back missing. v4 fixes it with a pnpm patch that only applies inside nuxt/content-v4-temp, so a published comark-content release with the fix is needed → patches/comark-content@0.4.1.patch
  • With Docus on comark, agents should get markdown/comark output, which fixes the markdown/html issues (escaped attributes like class="[&amp;&gt;div]:*:my-0", MDC slots inside HTML tags) and the nesting problems that motivated #1449. It's blocked by a serializer bug: a code sample that itself contains indented ``` fences is written with a three-backtick fence instead of four, so it closes early and the rest of the page is parsed as code (Steps example in components.md).
  • Heading ids are hierarchical (#basic-inline-code instead of #inline-code), which changes 45 of the 77 anchors in the playground. v3 mode needs an option for flat ids.
  • Two saves about 5 ms apart can leave stale frontmatter until the next save (watcher race).

nuxt-agent-discovery

  • moduleDependencies pins @nuxt/content to ^3.0.0, so Nuxt refuses v4 → patches/nuxt-agent-discovery@0.7.0.patch
  • The built-in Content source depends on v3 internals: #content/manifest (not generated by v4), minimark/stringify (borrowed from @nuxt/content's dependencies) and v3's body.value. On v4 it should switch to the comark adapter wired to v4's server content by itself → layer/server/agent-source.ts, layer/nuxt.config.ts
  • With a custom source, /sitemap.md and /raw/index.md aren't prerendered (they're served at runtime), so pnpm check:vercel-output fails.

Nuxt Studio

  • It imports #content/preview (the v3 preview API), @nuxt/content/runtime (compressTree/decompressTree) and @nuxt/content/server, none of which v4 provides, so it can't build → disabled in docs/nuxt.config.ts

Nuxt UI

  • Prose headings read runtimeConfig.public.mdc.headings.anchorLinks, which @nuxtjs/mdc sets and v4 no longer installs. Heading anchors disappeared and inline code in headings lost its size → content-v4.ts
  • Highlight themes come from @nuxtjs/mdc defaults, so v4 used the GitHub themes instead of Nuxt UI's material-theme-* → content-v4.ts

🤖 Generated with Claude Code, reviewed by @larbish before opening.

@vercel

vercel Bot commented Oct 16, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
docus Error Error Oct 16, 2026 3:42pm UTC

This branch had an error being deployed

1 failed deployment
Preview — d252986e Deployed Oct 16, 2026 by vercel[bot]
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