|
|
# Salvageable closed PRs — vuejs/vitepress
|
|
|
|
|
|
Last reviewed 2026-08-03 · `main` @ v2.0.0-alpha.19
|
|
|
|
|
|
21 closed-but-unmerged pull requests address needs that are still real, still unimplemented, and not tracked by any open issue or PR. The table below ranks them; the per-area pages carry the full write-ups — what each PR did, why it was closed, why it still matters, and how to land it properly this time.
|
|
|
|
|
|
**Reading the tables:** *salvage* — the closed branch is still a usable starting point; reopen or rebase it. *redo* — the need is real, but reimplement fresh rather than reviving the old diff. *Value* is estimated impact (1–5), *Effort* is S/M/L, and *Priority* ranks areas by how much worthwhile work they hold.
|
|
|
|
|
|
## Candidates
|
|
|
|
|
|
Ranked by value, then effort.
|
|
|
|
|
|
| PR | Title | Verdict | Value | Effort | Why now |
|
|
|
| --- | --- | --- | ---: | --- | --- |
|
|
|
| [#2002](https://github.com/vuejs/vitepress/pull/2002) | fix: allow language page without ending slash | salvage | 3 | S | `getLocaleForPath` still matches `` `^/${key}/` ``, so a bare `/zh` silently falls back to root-locale config, strings and search bucket; one regex in one tracked file. |
|
|
|
| [#2010](https://github.com/vuejs/vitepress/pull/2010) | docs: DigitalOcean App Platform deploy steps | salvage | 3 | S | `deploy.md` still has no DigitalOcean section, though Kinsta, Stormkit, CloudRay and Hostinger were all added after this closed. |
|
|
|
| [#3419](https://github.com/vuejs/vitepress/pull/3419) | fix(cli/shortcuts): CTRL-C should be a normal exit | salvage | 3 | S | `shortcuts.ts:77` still exits 1 on Ctrl-C while the `q` quit shortcut at `:52` exits 0 — a one-token reopen resolving a live inconsistency. |
|
|
|
| [#4876](https://github.com/vuejs/vitepress/pull/4876) | feat(init): validate config directory is inside cwd | redo | 3 | S | The `// TODO make sure directory is inside` comment is still verbatim in `src/node/init/init.ts`; the original branch dragged in dozens of unrelated files, so redo clean. |
|
|
|
| [#1236](https://github.com/vuejs/vitepress/pull/1236) | feat(theme): add ability to hide nav per-page | redo | 3 | M | No blank or bare layout exists in the theme today and no matching implementation ever landed, so per-page nav hiding is still unserved. |
|
|
|
| [#1449](https://github.com/vuejs/vitepress/pull/1449) | feat: Smooth Scrolling behavior | redo | 3 | M | Filed six times and killed each time by the same two objections; redo as an opt-in `themeConfig` flag rather than an always-on global style. |
|
|
|
| [#2329](https://github.com/vuejs/vitepress/pull/2329) | feat(theme): use inert for hidden mobile menus | salvage | 3 | M | `composables/nav.ts` and `Layout.vue` still have no `inert` or focus-trap handling; `inert` is now baseline, so the Vue-rendering workaround the PR needed is likely unnecessary. Subsumes [#1448](https://github.com/vuejs/vitepress/pull/1448). |
|
|
|
| [#2990](https://github.com/vuejs/vitepress/pull/2990) | feat(theme): allow link on nav item with children | redo | 3 | M | `NavItemWithChildren` still declares only `text`/`items`/`activeMatch`; needs an explicit design for click-to-navigate vs click-to-open on touch. |
|
|
|
| [#3387](https://github.com/vuejs/vitepress/pull/3387) | Fix: Make the outline follow the page scroll | redo | 3 | M | `.aside-container` is `position: fixed` with `overflow-y: auto` and no scroll-into-view logic, so the active marker still leaves the viewport on long pages; three attempts, none merged. |
|
|
|
| [#703](https://github.com/vuejs/vitepress/pull/703) | perf(a11y): make font size follow user browser settings | redo | 3 | L | `vars.css`/`base.css` still hardcode px sizes, so browser text-zoom is ignored; redo scoped to `font-size`/`line-height` only, sidestepping the objections to the original 45-file sweep. |
|
|
|
| [#348](https://github.com/vuejs/vitepress/pull/348) | feat: allow displaying fallback when ads are blocked | redo | 2 | S | `VPCarbonAds` still leaves an empty 256px tinted block when an ad blocker fires; detect the blocked state and expose an opt-in fallback slot. |
|
|
|
| [#1544](https://github.com/vuejs/vitepress/pull/1544) | Added smooth scrolling | redo | 2 | S | Self-closed duplicate of [#1449](https://github.com/vuejs/vitepress/pull/1449) — the same smooth-scroll need; one decision covers both. |
|
|
|
| [#2384](https://github.com/vuejs/vitepress/pull/2384) | refactor: standardize import sort | redo | 2 | S | Still no import-sort tooling in the repo; only worth doing as a prettier plugin plus one mechanical reformat, per brc-dd's stated preference. |
|
|
|
| [#3885](https://github.com/vuejs/vitepress/pull/3885) | docs: add documentation for `publicDir` | salvage | 2 | S | `publicDir` appears nowhere in `docs/en/`; one paragraph in `asset-handling.md`, folding in the un-landed half of [#4600](https://github.com/vuejs/vitepress/pull/4600). |
|
|
|
| [#4228](https://github.com/vuejs/vitepress/pull/4228) | feat(theme): add the `success` custom block | salvage | 2 | S | `::: success` styling is still absent while `--vp-c-success-*` variables sit unused; add the CSS + label, or document the `customContainers` route — the stale-bot close settled nothing. |
|
|
|
| [#5002](https://github.com/vuejs/vitepress/pull/5002) | fix(cli): gate ora spinner behind tty check | salvage | 2 | S | `task.ts:10` still constructs ora with no TTY gating, so non-interactive builds hide errors and look hung; brc-dd was open in principle and the thread just trailed off. |
|
|
|
| [#2297](https://github.com/vuejs/vitepress/pull/2297) | fix: better `.has-aside` condition | salvage | 2 | M | `hasAside` still ignores the carbonAds/slots/`getHeaders` edge cases; ships slot tests and is a true rebase candidate. |
|
|
|
| [#4457](https://github.com/vuejs/vitepress/pull/4457) | feat(theme): add doc aside scroll spy | redo | 2 | M | Same aside scroll-spy need as [#3387](https://github.com/vuejs/vitepress/pull/3387); self-closed as duplicate of [#3654](https://github.com/vuejs/vitepress/pull/3654), which actually targets the left sidebar, not the outline. |
|
|
|
| [#4575](https://github.com/vuejs/vitepress/pull/4575) | fix: grammar | salvage | 2 | M | ~16 files of English copy fixes, one commit per page, still largely applicable; the cost is review — keep genuine errors, drop style preferences. |
|
|
|
| [#5097](https://github.com/vuejs/vitepress/pull/5097) | Allow overflow-x with horizontal scrolling in VPNav | redo | 2 | M | Nav items still clip silently on overflow; get a maintainer ruling first — wrapping was rejected on [#1271](https://github.com/vuejs/vitepress/issues/1271), scrolling was never ruled on. |
|
|
|
| [#116](https://github.com/vuejs/vitepress/pull/116) | feat: support lowercase url | redo | 2 | L | Case-mismatched internal links still 404 on case-sensitive hosts; a design question, not a rebase — cheapest outcome is a dead-link-checker warning for case mismatches. |
|
|
|
|
|
|
## By area
|
|
|
|
|
|
| Area | Priority | PRs | Summary |
|
|
|
| --- | --- | ---: | --- |
|
|
|
| [Markdown & content authoring](clusters/markdown-authoring.md) | P1 | 1 | Add a `::: success` custom container ([#4228](https://github.com/vuejs/vitepress/pull/4228)) using the `--vp-c-success-*` theme colors that currently have no container styling — low effort, but a maintainer call on whether the built-in container set grows. |
|
|
|
| [Default theme navigation, outline & reading UX](clusters/default-theme-navigation-ux.md) | P1 | 7 | Chronic requests for smooth scrolling ([#1449](https://github.com/vuejs/vitepress/pull/1449), filed six times) and outline scroll-tracking ([#3387](https://github.com/vuejs/vitepress/pull/3387)), plus smaller fixes: per-page nav hiding ([#1236](https://github.com/vuejs/vitepress/pull/1236)), nav overflow ([#5097](https://github.com/vuejs/vitepress/pull/5097)), and the `.has-aside` condition ([#2297](https://github.com/vuejs/vitepress/pull/2297)). |
|
|
|
| [Accessibility](clusters/accessibility.md) | P1 | 2 | Two live gaps in the default theme: the mobile-menu keyboard trap, now cheaply fixable with `inert` ([#2329](https://github.com/vuejs/vitepress/pull/2329)), and hardcoded px typography that ignores browser font-size settings ([#703](https://github.com/vuejs/vitepress/pull/703)). |
|
|
|
| [Config, CLI, types & public API](clusters/config-cli-types-api.md) | P1 | 3 | Three self-contained CLI ergonomics fixes: Ctrl-C exiting non-zero on a normal stop ([#3419](https://github.com/vuejs/vitepress/pull/3419)), a missing directory-escape check in `vitepress init` ([#4876](https://github.com/vuejs/vitepress/pull/4876)), and an ora spinner with no TTY gating ([#5002](https://github.com/vuejs/vitepress/pull/5002)). |
|
|
|
| [Build pipeline, dev server & routing](clusters/build-dev-server-routing.md) | P2 | 1 | No case-insensitive URL handling exists anywhere in the pipeline, so links whose case doesn't match the file on disk work in dev but 404 on case-sensitive hosts ([#116](https://github.com/vuejs/vitepress/pull/116)). |
|
|
|
| [Default theme configuration & extensibility](clusters/default-theme-config-extensibility.md) | P2 | 2 | Two features worth implementing fresh: nav items whose dropdown label can also carry its own link ([#2990](https://github.com/vuejs/vitepress/pull/2990)), and a fallback slot for when Carbon Ads is blocked ([#348](https://github.com/vuejs/vitepress/pull/348)). |
|
|
|
| [i18n & locale handling](clusters/i18n-locales.md) | P2 | 1 | A bare `/zh` (no trailing slash) silently falls back to root-locale config, theme strings and search bucket; [#2002](https://github.com/vuejs/vitepress/pull/2002) is a one-regex fix in the locale matcher. |
|
|
|
| [Docs content, website & repo chores](clusters/docs-site-repo-chores.md) | P3 | 4 | Four small docs fixes: a DigitalOcean deploy entry ([#2010](https://github.com/vuejs/vitepress/pull/2010)), `publicDir` documentation ([#3885](https://github.com/vuejs/vitepress/pull/3885)), import-sort via tooling ([#2384](https://github.com/vuejs/vitepress/pull/2384)), and a still-applicable grammar pass ([#4575](https://github.com/vuejs/vitepress/pull/4575)). |
|