Skip to content

fix: respect global tableOfContents config with zod v4#3751

Merged
delucis merged 5 commits intowithastro:mainfrom
pyxelr:fix/toc-global-config-zod-v4
Mar 11, 2026
Merged

fix: respect global tableOfContents config with zod v4#3751
delucis merged 5 commits intowithastro:mainfrom
pyxelr:fix/toc-global-config-zod-v4

Conversation

@pyxelr
Copy link
Copy Markdown
Contributor

@pyxelr pyxelr commented Mar 11, 2026

Description

Changes

  • schemas/tableOfContents.ts: Extracted a shared TableOfContentsBaseSchema and created two separate exports:
    • UserConfigTableOfContentsSchema() — wraps the base with .default(defaults) for the user config.
    • FrontmatterTableOfContentsSchema() — wraps the base with .optional() so undefined is preserved when frontmatter does not set the field.
  • schema.ts: Updated the frontmatter schema to use FrontmatterTableOfContentsSchema().
  • utils/user-config.ts: Updated to use UserConfigTableOfContentsSchema().

Testing

All 511 existing unit tests pass. The fix can be verified by setting a global tableOfContents config (e.g., maxHeadingLevel: 4) and confirming it applies to pages that do not override it in frontmatter.

A StackBlitz reproduction is available in the linked issue.

@changeset-bot
Copy link
Copy Markdown

changeset-bot bot commented Mar 11, 2026

🦋 Changeset detected

Latest commit: 2339c0b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@astrojs/starlight Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@netlify
Copy link
Copy Markdown

netlify bot commented Mar 11, 2026

Deploy Preview for astro-starlight ready!

Name Link
🔨 Latest commit 2339c0b
🔍 Latest deploy log https://app.netlify.com/projects/astro-starlight/deploys/69b1fad23d756700084602f0
😎 Deploy Preview https://deploy-preview-3751--astro-starlight.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
1 paths audited
Performance: 100 (no change from production)
Accessibility: 100 (no change from production)
Best Practices: 100 (no change from production)
SEO: 100 (no change from production)
PWA: -
View the detailed breakdown and full score reports

To edit notification comments on pull requests, go to your Netlify project configuration.

@github-actions github-actions bot added the 🌟 core Changes to Starlight’s main package label Mar 11, 2026
@astrobot-houston
Copy link
Copy Markdown
Contributor

Hello! Thank you for opening your first PR to Starlight! ✨

Here’s what will happen next:

  1. Our GitHub bots will run to check your changes.
    If they spot any issues you will see some error messages on this PR.
    Don’t hesitate to ask any questions if you’re not sure what these mean!

  2. In a few minutes, you’ll be able to see a preview of your changes on Netlify 🤩

  3. One or more of our maintainers will take a look and may ask you to make changes.
    We try to be responsive, but don’t worry if this takes a few days.

With zod v4, `.default(value).optional()` returns the default value
for `undefined` input instead of `undefined` itself. This caused
frontmatter `tableOfContents` to always resolve to the schema default,
preventing the global Starlight config from being used as a fallback.

This fix introduces a separate `FrontmatterTableOfContentsSchema` that
omits `.default()` so `undefined` is preserved, and updates `getToC()`
to properly merge frontmatter values with the global config.

Closes withastro#3748
@pyxelr pyxelr force-pushed the fix/toc-global-config-zod-v4 branch from a22e322 to 18a01d0 Compare March 11, 2026 22:58
Copy link
Copy Markdown
Member

@delucis delucis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR @pyxelr! I played around a bit and I think we can actually scope the changes entirely to the schema (which is the origin of the problem) and avoid logic changes for now.

pyxelr and others added 3 commits March 12, 2026 00:10
Co-authored-by: Chris Swithinbank <swithinbank@gmail.com>
- Remove old TableOfContentsSchema and duplicate FrontmatterTableOfContentsSchema
- Rename TableOfContentsSchema to UserConfigTableOfContentsSchema in user-config.ts
- Revert test additions (no logic changes in data.ts)
delucis
delucis previously approved these changes Mar 11, 2026
Copy link
Copy Markdown
Member

@delucis delucis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perfect, thank you! I just pushed up some tests I was using to diagnose the issue locally, but this should be good to go!

Thanks again for contributing 🙌

@delucis delucis merged commit fb955ff into withastro:main Mar 11, 2026
16 checks passed
@astrobot-houston astrobot-houston mentioned this pull request Mar 11, 2026
@voytxt
Copy link
Copy Markdown

voytxt commented Mar 12, 2026

this seems to fix the issue in dev (astro dev), but not in prod (astro build && astro preview)

@delucis
Copy link
Copy Markdown
Member

delucis commented Mar 12, 2026

Do you have an example you could point to @voytxt for us to debug? In theory at least there should be no dev/build difference to this API 🤔

@voytxt
Copy link
Copy Markdown

voytxt commented Mar 12, 2026

I would presume this is some obscure caching bug? Could very easily be something completely different I have no idea... I managed to solve it however, both local prod and Vercel prod work properly now! I'm not exactly sure what solved it, but I can reitarate what steps I did.

For local prod, I first tried deleting all gitignored directories and also building with astro build --force, that didn't seem to solve it, but when I commented and later uncommented most options in the astro config file, that somehow fixed it, and I could no longer reproduce the bug on machine whatsoever. Note that there was no git-tracked files changed in the end, nothing.

For Vercel prod, nothing seemed to work, until I bumped Astro from 6.0.3 to 6.0.4. That seemed to magically fix it and I now also can't reproduce it on Vercel, even if I deploy the version with Astro 6.0.3.

If it's not vite/astro directly, my hunch would be on pnpm (I use pnpm 10.32.1) doing some weird shenanigans, or possibly some dependency (tho I'm not sure if that's possible). For the sake of completeness, here they are: (latest versions of everything)

  "devDependencies": {
    "@astrojs/starlight": "^0.38.1",
    "@astrojs/vercel": "^10.0.0",
    "astro": "^6.0.4",
    "astro-vtbot": "^2.1.11",
    "prettier": "^3.8.1",
    "prettier-plugin-astro": "^0.14.1",
    "sharp": "^0.34.5",
    "starlight-sidebar-topics": "^0.7.1"
  }

@delucis
Copy link
Copy Markdown
Member

delucis commented Mar 12, 2026

Ohh, interesting. It is theoretically possible that the content collection cache could have caused an issue here! I would have expected that updating Starlight to 0.38.1 would have been enough to invalidate that but maybe not for some reason. Glad it’s working now anyway and thanks for letting us know — I’ll keep an eye out for anyone else hitting it.

dadezzz pushed a commit to dadezzz/ice-notes that referenced this pull request Mar 16, 2026
This PR contains the following updates:

| Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) |
|---|---|---|---|
| [@astrojs/starlight](https://starlight.astro.build) ([source](https://github.com/withastro/starlight/tree/HEAD/packages/starlight)) | [`0.38.0` → `0.38.1`](https://renovatebot.com/diffs/npm/@astrojs%2fstarlight/0.38.0/0.38.1) | ![age](https://developer.mend.io/api/mc/badges/age/npm/@astrojs%2fstarlight/0.38.1?slim=true) | ![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@astrojs%2fstarlight/0.38.0/0.38.1?slim=true) |

---

### Release Notes

<details>
<summary>withastro/starlight (@&#8203;astrojs/starlight)</summary>

### [`v0.38.1`](https://github.com/withastro/starlight/blob/HEAD/packages/starlight/CHANGELOG.md#0381)

[Compare Source](https://github.com/withastro/starlight/compare/@astrojs/starlight@0.38.0...@astrojs/starlight@0.38.1)

##### Patch Changes

- [#&#8203;3751](withastro/starlight#3751) [`fb955ff`](withastro/starlight@fb955ff) Thanks [@&#8203;pyxelr](https://github.com/pyxelr)! - Fixes a regression causing global `tableOfContents` config to be ignored

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My41OS41IiwidXBkYXRlZEluVmVyIjoiNDMuNTkuNSIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->

Co-authored-by: Renovate Bot <renovate@zarantonello.dev>
Co-committed-by: Renovate Bot <renovate@zarantonello.dev>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🌟 core Changes to Starlight’s main package

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Global tableOfContents config ignored due to zod v4 .default().optional() behavior change

4 participants