Migration Guide
About 926 wordsAbout 3 min
2026-10-10
Overview
This page explains how to upgrade configurations from versions before 1.0.0-rc.165 to the current version's collections architecture.
At build time, the theme automatically migrates the old blog / notes configuration, so you can keep running without manually rewriting it. However, automatic migration follows a priority rule of "collections takes precedence," and in some scenarios the migration result does not match expectations — these cases require you to handle them yourself.
Just want to quickly confirm that nothing has been migrated?
Jump straight to the Which cases will not be automatically migrated section in this article.
What is collections
The theme now uses collections to uniformly describe "which part of the content, in what form, generates which pages":
| Collection type | Purpose | Generated content |
|---|---|---|
post | Blog-like content | List page, tag page, archive page, category page |
doc | Documentation-like content | Sidebar navigation |
The old version's blog corresponds to the post collection, and the old notes corresponds to a group of doc collections.
How the old configuration gets migrated
The theme is compatible with the old blog/notes configuration by default and performs the conversion at build time. The rules are as follows:
- If
collectionsis not configured, the root-levelblogis converted into apostcollection, andnotesis converted into severaldoccollections. - The note directories configured in
notesare automatically appended to theexcludeof theblogcollection, to prevent note articles from being included in the blog list. - If
collectionsis configured, the root-levelblog/noteswill be ignored. - In multilingual scenarios, when a certain locale declares its own
collections, its ownblog/noteswill be ignored; when it does not declare them, it falls back to using the root-levelblog/notes.
Warning
blog and notes have been marked @deprecated. They are only for transition and will be removed directly in the next major version.
Which cases will not be automatically migrated
The following scenarios require you to adjust manually.
1. collections and blog / notes are configured at the same time
This is the case most prone to pitfalls: when collections exists, blog / notes are directly ignored.
If you want to keep your existing collections while also continuing to use the old blog, manually merge the contents of blog into collections.
2. A certain locale needs separate configuration, but the root level does not have any
The old blog / notes are global configurations, shared by all languages. If you need to use different collections in a certain locale, declare collections inside that locale rather than relying on root-level fallback.
3. Multiple directories in notes correspond to different sidebars
The old notes.notes is an array, and each item has its own dir / link / sidebar. Migration generates an independent doc collection for each item, so the structure can usually correspond; but if you relied on notes.sidebarScrollbar (an old field), note that it has been migrated onto each doc collection.
Manual migration steps
Take a typical 1.x configuration:
Legacy config (for reference only, not type-checked)
export default defineThemeConfig({
blog: {
dir: 'blog',
categories: true,
tags: true,
archives: true,
pagination: {
perPage: 10,
},
},
notes: {
dir: 'notes',
link: '/notes/',
notes: [
{ dir: 'guide', link: '/guide/' },
{ dir: 'api', link: '/api/' },
],
},
})blog / notes are @deprecated and typed as never, so this block intentionally omits twoslash — it exists for comparison, not for copying.
Migrate it to:
import { defineCollections } from 'vuepress-theme-plume'
export default defineCollections([
{
type: 'post',
dir: 'blog',
title: 'Blog',
categories: true,
tags: true,
archives: true,
pagination: {
perPage: 10,
},
},
{
type: 'doc',
dir: 'notes/guide',
title: 'Guide',
linkPrefix: '/notes/guide/',
},
{
type: 'doc',
dir: 'notes/api',
title: 'API',
linkPrefix: '/notes/api/',
},
])Warning
Two differences to note:
titleis a required field (ThemeBaseCollection.title). If your legacy config did not declare a collection title explicitly, you must supply one after migrating.linkPrefixdetermines the URL of articles in the collection. Ifnoteshad no explicitlink, migration falls back to the directory name, so URLs may differ from before.
Tips
If the legacy config used a hand-written sidebar array (notes.notes[].sidebar), it is migrated as-is into the doc collection's sidebar field, which accepts 'auto' or (string | ThemeSidebarItem)[].
How dir matching works for nested collections
When directories are nested, a file belongs to the collection with the longest matching dir:
- Given both
dir: 'docs'(type: 'doc') anddir: 'docs/blog'(type: 'post'),docs/blog/a.mdbelongs to thepostcollection (docs/blogis longer thandocs, so the more specific match wins), whiledocs/guide/b.mdbelongs todoc.
This is resolved automatically — no manual ordering is needed. The logic lives in theme/src/node/collections/findCollection.ts: it sorts collections by dir length in descending order and picks the first whose directory prefix matches, so a longer (more specific) directory always takes priority.
Verify the result
After migrating, check each of the following:
- Blog list pages render correctly, with pagination and article counts matching the pre-migration state
- Tag, archive and category pages are reachable
- Doc sidebars match the pre-migration state, especially deep structures such as
sidebar: 'auto' - URLs have not changed — a wrong
linkPrefixchanges paths and breaks old links - Articles under note directories are correctly excluded from the blog list
Related documentation
- Collection — full
collectionsconfiguration reference - Configuration > Theme — every config field, its type and default
- Configuration > Collections — collections configuration reference
