Skip to contentSkip to Content
Feedback
Migrating from Sphinx

Migrating from Sphinx

Step-by-step guide to moving a Sphinx project to Folioh by hand.

A migration run by your agent, with a migration skill and a few scripts: Not available in this release; the roadmap puts it in 0.4 Agent Ready. Why Folioh covers the reasons to switch; this page covers the move.

Step-by-step migration

1. Install Folioh

Follow Installation.

2. Initialize configuration

Run the init command in your project root. It reads the project name and version from pyproject.toml and finds the source directory on disk:

folioh init

This creates a docs.yaml file. Edit it to point to your Python source directories:

project: name: "my-project" version: "1.0.0" repo: "https://github.com/org/my-project" source: python: paths: - "src/my_project/" exclude: - "src/my_project/_vendor/" docs: - "docs/" nav: - "Guide" - "API Reference"

3. Convert existing documentation

Keep existing Markdown pages and review any directives or components specific to your previous documentation tool.

If you have hand-written documentation in .rst format, convert it to Markdown before adding it to source.docs. Folioh does not ship or invoke an RST converter; use your migration tool of choice, review the generated Markdown, and then let Folioh build the converted pages.

Folioh warns about .rst files only when those files are still present inside a directory listed in source.docs. It does not emit a warning if the .rst files were already removed before running folioh build or folioh serve.

Name guide files and directories with hyphens, not underscores: write common-errors/index.md, published at /docs/common-errors/. In this release a guide page whose path contains an underscore, such as common_errors/index.md, renders a not-found page at both /docs/common_errors/ and /docs/common-errors/. Old Sphinx URLs are not redirected. API reference routes are the exception: Python package and module names keep their underscores.

4. Leave your docstrings alone

Your docstrings need no conversion. With docstring_style: "auto", the default, Folioh detects the style per docstring and reads reStructuredText (:param name:), Google, NumPy and epydoc. Set source.python.docstring_style only to pin one style for a codebase that mixes them by accident.

5. Remove the previous documentation setup

Once migration is verified, remove configuration and dependencies used only by your previous documentation tool. For a Sphinx project, these may include:

  • conf.py
  • Makefile (if only used for docs)
  • make.bat
  • _build/ directory
  • _static/, _templates/ directories
  • Sphinx from your dependencies

6. Build and verify

folioh serve

This starts a dev server at http://localhost:4321 where you can verify your documentation looks correct.

Mapping Sphinx concepts to Folioh

conf.py to docs.yaml

Sphinx conf.pyFolioh docs.yaml
project = "Name"project.name: "Name"
version = "1.0"project.version: "1.0"
extensions = ["autodoc"]Not needed (automatic)
html_theme = "furo"Built-in theme presets (see Theming)
html_static_pathpublic: for files served from the site root; images a page uses go beside the page
html_logotheme.logo
html_favicontheme.favicon
exclude_patternssource.python.exclude
autodoc_member_orderNot configurable (source order)

autodoc to automatic generation

In Sphinx, you write explicit directives to pull in API documentation:

.. automodule:: my_project.core :members: :undoc-members: :show-inheritance:

In Folioh, you list your source directories and everything is documented automatically:

source: python: paths: - "src/my_project/"

No per-module directives needed. Use __all__ in your Python modules to control which symbols appear in the documentation.

RST directives

Folioh does not translate RST directives during a build. Convert them before adding the page to source.docs, then review common constructs against this mapping:

Common manual rewrites:

RST DirectiveConverted To
.. code-block:: pythonFenced code block (```python)
.. note::Callout (note)
.. warning::Callout (warning)
.. tip::Callout (tip)
.. hint::Callout (tip)
.. danger::Callout (danger)
.. error::Callout (danger)
.. important::Callout (warning)
.. caution::Callout (warning)
.. attention::Callout (warning)
.. seealso::Callout (info)
.. deprecated::Callout (danger) with version
.. versionadded::Callout (note) with version
.. versionchanged::Callout (note) with version
.. image:: path![path](path)
RST headings (underlines)Markdown headings (#, ##, etc.)
inline code `inline code`
:role:`text``text`

Features that need manual redesign:

RST FeatureStatus
.. toctree::Not needed (auto-generated navigation)
.. include::Not supported
.. math::$$ block, rendered with KaTeX (inline: $…$)
.. table::Use Markdown tables instead
.. raw::Not supported
.. tab-set:: / .. tab-item::Convert manually to <Tabs> and <TabItem>
.. only::Not supported
Cross-references (:ref:, :doc:)Not available in this release; use Markdown links
Substitutions (|name|)Not supported
Field lists (:field:)Not supported
FootnotesMarkdown footnotes ([^1])

For Sphinx tab sets, rewrite each block with Folioh’s MDX tabs components:

<Tabs> <TabItem label="Python"> ```python import my_library ``` </TabItem> <TabItem label="CLI"> ```bash my-library run ``` </TabItem> </Tabs>

For callouts that were written as Markdown blockquotes during migration, use Folioh’s Callout component directly. Patterns such as > **Warning:** should become <Callout type="warning">. For example, convert > **Warning:** This changes state. to:

<Callout type="warning"> This changes state. </Callout>

Sphinx extensions to Folioh features

Many common Sphinx extension use cases are built into Folioh. Custom extensions: Not available in this release.

Sphinx ExtensionFolioh Equivalent
autodocBuilt-in (automatic)
napoleonBuilt-in (Google and NumPy styles)
viewcodeBuilt-in: each definition links to its source line when project.repo is set
intersphinxNot available in this release
todoNot supported
coverageBuilt-in (folioh coverage)
doctestNot supported
sphinx-copybuttonBuilt-in (code blocks have copy buttons)
Custom extensionsNot available in this release

make html to folioh build

Sphinx CommandFolioh Command
make htmlfolioh build
make cleanfolioh clean
sphinx-autobuildfolioh serve
sphinx-quickstartfolioh init

What works differently

Sphinx has an extensive cross-reference system (:class:, :func:, :meth:, etc.) that creates links between documented symbols. Folioh generates API links for parsed type annotations; Sphinx role syntax is Not available in this release. In a docstring a role reads as code, unlinked: :class:`MyClass` renders as MyClass. In a Markdown page a role stays as written. Replace roles with Markdown links where you need the link.

No intersphinx

Sphinx’s intersphinx extension lets you link to other projects’ documentation. Intersphinx is Not available in this release. If your docs link heavily to external API documentation (for example the Python standard library), replace those links with plain URLs.

Source order, not alphabetical

Folioh documents members in the order they appear in the source file. Sphinx’s autodoc_member_order option with alphabetical sorting has no equivalent.

Only the field lists of reStructuredText docstrings

Folioh reads the Sphinx field lists in docstrings (:param x:, :type x:, :returns:, :rtype:, :raises:). Other reStructuredText markup in a docstring, such as substitutions, directives or grid tables, is not converted and shows as written.

Common gotchas

Docstring parsing errors. If no style parses a docstring, Folioh falls back to the first line as the summary and the rest as the description. The parameter table still lists the signature’s parameters, without descriptions. Indentation matters: in a Google-style section, a line at column zero ends the section and the lines from there to the next section header are dropped.

Missing __init__ docs. Folioh documents __init__ like any other method. If you were relying on Sphinx’s autoclass_content = "both" to merge class and __init__ docstrings, you may need to adjust your docstrings.

Private members. Without __all__, Folioh documents every top-level class, function and annotated variable, and every unannotated assignment to an upper-case name, when the name does not start with _. Define __all__ in a module to choose exactly what appears: it can list a class, function or annotated variable whose name starts with _, while an unannotated assignment still needs an upper-case name without a leading _.

MyST directives disappear silently. A fenced block whose info string is in braces, such as MyST’s {note} or {eval-rst}, is removed with its content, and the build does not warn. Rewrite each one in Markdown or as a component before adding the page to source.docs. An importer that rewrites these blocks, tab sets and blockquote-style callouts: Not available in this release.

Raw embeds disappear silently. The Markdown-to-MDX step removes raw <iframe>, <script>, <style>, <video>, <audio>, <object>, and <embed> elements, inside code blocks too, and the build does not warn. Use a normal Markdown link or a documented component instead of a raw YouTube or HTML embed.

Images stay beside the page. An image path relative to the page is copied with it, as long as the file sits in the page’s directory or below it. A path with .. is removed from the page and the build warns image not found: ../img.png (escapes the docs directory).

Curly braces are escaped for you. Folioh outputs MDX, where a bare { starts a JSX expression, so it escapes bare braces in prose; code blocks, inline code and $…$ math pass through untouched. A line that starts with < is treated as JSX and left alone, so a literal brace on such a line needs a backslash (\{).

Markdown details that change. Links to .md files drop the extension and point at the published page; class= on an HTML tag becomes className=; a mermaid fence renders as a diagram.

Feature comparison

FeatureSphinxFolioh
Python API docsVia autodoc extensionBuilt-in, automatic
Docstring stylesGoogle, NumPy, reStructuredTextGoogle, NumPy, reStructuredText, epydoc, auto-detected per docstring
ConfigurationPython (conf.py)YAML (docs.yaml)
Output formatHTML, PDF, ePub, etc.HTML (Next.js)
Theme systemJinja2 templatesReact + shadcn/ui
Dark modeTheme-dependentBuilt-in
Hot reload dev serverVia sphinx-autobuildBuilt-in
SearchBuilt-inBuilt-in (Pagefind)
Cross-referencesFull supportGenerated API type links; Sphinx roles: Not available in this release
IntersphinxFull supportNot available in this release
RST supportNativeConvert to Markdown before build
Markdown supportVia MySTNative
Custom extensionsExtensive plugin ecosystemNot available in this release
PDF outputBuilt-inNot supported
i18nBuilt-inNot available in this release
LLM-friendly outputNot built-inllms.txt + llms-full.txt
Custom componentsJinja2 macrosReact/MDX components
Setup complexityHighLow
Build speedModerateFast (Turbopack)

Migration checklist

  • TODO

    Install Folioh and run folioh init

  • TODO

    Edit docs.yaml with project details and source paths

  • WARN

    Convert .rst files to .md

    Folioh ships no converter: use the tool you prefer, then review the Markdown by hand.

  • TODO

    Replace :ref: and :doc: cross-references

    Sphinx roles do not become links: use Markdown links.

  • TODO

    Rewrite {eval-rst} and other MyST directive blocks

  • TODO

    Move html_static_path files to public: or beside the pages that use them

  • TODO

    Run folioh serve and verify every page

  • TODO

    Remove Sphinx configuration files and dependencies

  • TODO

    Update CI/CD scripts to use folioh build