# Migrating a mkdocs.yml project in one upload Zip the repository, upload it, and your mkdocs.yml is read for site name, description, language and navigation. What arrives intact, what a plugin was doing that no config can carry, and how to go back. _Source: https://docszero.com/resources/migrate-a-mkdocs-project_ _how-to · 6 min read_ _Published 10 September 2026_ > **In short:** Zip the repository with mkdocs.yml at the root and upload it. Site name, description, language and the nav tree are read out, so your navigation survives without being rebuilt. What does not come across is anything a plugin or a theme override was doing. ## Why this is the easy one Of every migration on this site, a MkDocs project is the least work, and it is not close. Your content is already Markdown in a folder tree, your images already sit beside the pages that use them, and your navigation is already written down in a file we read. There is a second reason, worth knowing if you run Material for MkDocs. Docszero builds with **Zensical**, which the Material for MkDocs team wrote as their own successor and released under MIT. This is not a migration out of the family — it is the same lineage, minus the pipeline. > Relevant background if you have not seen it: Material for MkDocs entered maintenance mode at version 9.7.0 in November 2025 — all Insiders features made free, sponsorware discontinued, bug and security fixes for at least twelve months and no new features, with the team’s attention moving to Zensical. [The MkDocs comparison](https://docszero.com/compare/mkdocs) covers what that means for a self-hosted setup. ## What is read out of mkdocs.yml Four keys, and it is worth being exact, because "we read your config" is the kind of claim that means different things to different products. | Key | Becomes | | --- | --- | | `site_name` | The site’s name | | `site_description` | The description, and the meta description | | `theme.language` or `site_language` | The site language | | `nav` | The navigation tree, with your titles and your order | That last one is the whole reason this is a one-upload migration. `nav` carries both the ordering and the human titles you chose, which are the two things a folder tree cannot express on its own: **the four keys that matter, and the tree that arrives intact** ``` site_name: Acme Handbook site_description: How to run and deploy Acme. nav: - Home: index.md - Getting started: - Install: getting-started/install.md - First project: getting-started/first-project.md - Guides: - Deploying: guides/deploying.md - Troubleshooting: guides/troubleshooting.md - Reference: reference/cli.md ``` A `zensical.toml` works the same way, so a project already migrated to Zensical is read from that instead. ## The steps ### 1. Zip the project Include `mkdocs.yml` at the top level of the zip alongside your `docs/` folder. If the config is buried a level down we will not find it, and you will get the folder tree without your `nav` — recoverable by dragging, but avoidable by zipping from the right place. You do not need to strip anything. Extra files are ignored rather than rejected, so there is no need to prune `requirements.txt`, a CI workflow or an `overrides/` folder before uploading. ### 2. Upload it Up to 200 MB, which is a very large docs project. There is no build command to choose and no theme to install; the config is written for you from what we read. ### 3. Compare the tree against your nav Open the page list next to your `mkdocs.yml` and check the order and the titles match. If `nav` was read, they will. If you had pages in `docs/` that were not listed in `nav` — MkDocs simply appends those — they will be present here too, which is often the moment you discover a page nobody had linked for a year. ### 4. Deal with what the plugins were doing The one real task, covered next. Everything else at this point is done. ### 5. Publish Search is generated at publish time and served from the site, so whatever search plugin you were configuring is now not your problem. Navigation and a 404 page come with it. ## What does not come across Everything here has the same cause: it was produced by code running during your build, and the Markdown never contained it. - **Plugin-generated pages.** `mkdocstrings` reference built from docstrings, `gen-files`, `literate-nav`, an OpenAPI page. The generated output was never in your repository, so there is nothing to upload. - **Theme overrides.** An `overrides/` folder with custom templates and partials. There are four themes, a brand colour and a logo instead. - **Custom `markdown_extensions`.** Standard Markdown, tables, code fences and mermaid all work. Exotic pymdownx extensions configured in your YAML do not carry their configuration. - **Macros and variables.** Anything substituted at build time by `mkdocs-macros` or similar arrives as the unsubstituted source. - **Hooks.** Python that ran during the build. - **Versioned docs.** If you run `mike`, each version is a separate build; there is one published site here, with rollback to earlier builds rather than parallel versions. The honest read: if `mkdocstrings` is generating half your reference, this migration is not for you and self-hosting is the right answer. If your plugin list is a search plugin, a minifier and one or two conveniences, you are losing very little. ### The five-minute check Open `mkdocs.yml` and look at `plugins:` and `markdown_extensions:`. If both are short and mostly cosmetic, upload and you are done today. If either is doing content generation, stay where you are. ## Going back, if you want to Worth saying because the audience for this page owns their pipeline already and is being asked to give it up. **Export source** hands back your Markdown with a generated config that builds with plain Zensical, nothing of ours involved, on every plan including Free. It is not a `mkdocs.yml` — it is the config for the generator we actually build with — but it is a working project, and your Markdown is unchanged from what you uploaded. Which means the experiment is cheap. Copy your docs folder, import it on the free plan, look at the result, and either keep it or close the tab. You have not moved anything; the repository you have now is untouched throughout. ## Questions ### Does Docszero read my mkdocs.yml? Yes, if it is at the top level of the uploaded zip. Site name, description, language and the nav tree are read out, so your navigation arrives with your titles and your ordering rather than needing to be rebuilt. A zensical.toml is read the same way. ### What happens to my MkDocs plugins? They do not come across, because plugins run during your build and their output was never in your repository. That matters most for content generation — mkdocstrings reference, gen-files, literate-nav, OpenAPI pages. If your plugin list is a search plugin and a couple of conveniences you are losing very little; if it is generating pages, self-hosting remains the right answer. ### Do I need to remove anything from the repo before zipping? No. Extra files are ignored rather than rejected, so requirements.txt, CI workflows and an overrides folder can stay. The only thing that matters is that mkdocs.yml sits at the top level of the zip beside your docs folder, so it is found. ### Is Docszero the same as MkDocs? No, but it is closely related. Docszero builds with Zensical, which the Material for MkDocs team wrote as their next-generation generator and released under MIT. Material for MkDocs itself entered maintenance mode at 9.7.0 in November 2025 with no new features planned, so Zensical is where that lineage continues either way. ### Can I go back to self-hosting MkDocs afterwards? Yes. Export source gives you your Markdown with a config that builds with plain Zensical, on every plan including Free. Your original repository is also untouched by the import, so trying this on a copy costs you nothing but the upload. --- Published by Docszero (https://docszero.com) — docs, minus the setup. Upload Markdown, a Word document or a PDF and get a searchable documentation site. Free for one site; export the source on every plan.