Interaction case · Phase 1 refactor
The site carried the same navigation in three places: the top-level themeConfig, the root locale and the zh locale. The AI partner assumed the root locale would inherit the top-level defaults, so editing the shared block would update English pages. It did not: the root locale had its own copy, which shadowed the defaults. The fix was not "copy the values again" but "remove the duplicate and make the merge order explicit".
Phase 1 consolidated scattered configuration in a bilingual VitePress site. The relevant shape before the change was:
themeConfig: {
logo, socialLinks, footer, editLink,
nav: [...], sidebar: {...} // English defaults
},
locales: {
root: { themeConfig: { nav, sidebar } }, // duplicate of the defaults
zh: { themeConfig: { nav, sidebar, editLink } }
}VitePress resolves a page's theme config as a shallow merge:
themeConfig: {
...siteData.themeConfig,
...siteData.locales[localeIndex]?.themeConfig
}That behaviour is correct, but it means a locale block is not "only overrides" unless it is written that way. The root block was a full copy, so the top-level block was dead weight for English pages.
| Assumption | Actual behaviour | Consequence |
|---|---|---|
| Root inherits top-level nav | Root has its own nav and wins the merge | Edits to the shared block never reach / |
| One source of truth exists | Three copies can drift independently | Silent EN/ZH divergence |
| Removing the root block is safe | Only if English defaults live at the top level | Requires moving the defaults first |
This is the kind of gap that does not produce an error message. Both copies were valid; the site simply ignored one of them.
themeConfig.root.themeConfig block entirely.zh.themeConfig (nav, sidebar, editLink)./, /projects/, /zh/, /zh/projects/.| Check | Result |
|---|---|
| Production build | Passed, 21 HTML pages |
| English nav | Home / Projects |
| Chinese nav | 首页 / 项目 |
| English sidebar | Projects by Role / Individual Projects |
| Chinese sidebar | 按角色分类 / 个人项目 |
| Logo, footer, social link | Present on both locales |
| Locale regressions | 0 |
Pass. The consolidation removed a shadowing block instead of adding a fourth copy, and every rendered locale route was checked after the build.
The reusable rule: a locale themeConfig should contain only the keys that actually differ. Everything else belongs in the shared default, and the merge order should be documented next to it.
The next risk is not configuration but content: a single loader now feeds multiple card surfaces. That contract is covered in the content loader evaluation.