Skip to content

docs: decisions needed to migrate the user guide to MkDocs #10683

Open

Description

@paulbalandan

Following up on the discussion in #10133, the converter in codeigniter4/docs-update is now complete enough to plan the switch. Before preparing the cutover PR, I'd like the maintainers' decisions on the points below.

Where the converter stands

  • Converts the whole of user_guide_src/source with pandoc plus a set of filters, then builds with Material for MkDocs in strict mode (no warnings, no broken links or anchors).

  • A verification script compares the RST and the Markdown on every run. It currently passes all checks on both develop and 4.8:

    Check Count
    Pages 330
    PHP signatures (php:method, php:function and so on) 628
    Code samples, literalinclude included 2106
    Admonitions 996
    Leftover RST directives, roles or raw HTML 0
  • CI converts, verifies and builds both branches nightly, so new RST changes upstream are picked up automatically.

  • The RST markup errors found along the way were fixed in docs: fix RST markup errors in the user guide #10668.

Previewing the converted guide

The quick route uses the converted pages from CI and needs only Python 3:

  1. Download the docs-develop (or docs-4.8) artifact from the latest workflow run and unzip it into a docs/ folder in a clone of codeigniter4/docs-update.
  2. Run make install, then make serve, and open http://127.0.0.1:8000.

To run the conversion yourself, you also need PHP 8.1 or newer with intl, and pandoc 3.12.1:

# pandoc 3.12.1: the macOS .pkg and Windows .msi are at https://github.com/jgm/pandoc/releases/tag/3.12.1
# On Debian or Ubuntu:
curl -fsSL -o pandoc.deb https://github.com/jgm/pandoc/releases/download/3.12.1/pandoc-3.12.1-1-amd64.deb
sudo dpkg -i pandoc.deb

git clone https://github.com/codeigniter4/docs-update && cd docs-update
echo 'DOCS_PROJECT_PATH=/path/to/CodeIgniter4/user_guide_src/source/' > .env
make install   # Python venv with MkDocs
make convert   # RST to Markdown into docs/
make verify    # compares the RST and the Markdown
make serve

The converter warns with any other pandoc version, and the output may differ from the verified one.

PHP class references

This was the main concern raised in #10133. Each php:class, php:method and php:function becomes a heading with its signature, followed by its parameter and return fields as lists. Every such heading has an anchor, so links to a method still resolve. For example, Email::setFrom() renders as:

#### setFrom($from[, $name = ''[, $returnPath = null]])

- **Parameters**
    - **$from** `string` "From" email address
    - **$name** `string` "From" display name
    - **$returnPath** `string` Optional email address to redirect undelivered email to

- **Returns**: CodeIgniter\Email\Email instance (method chaining)

There is no Sphinx-style object index or :php:meth: cross-reference role in Markdown. References to methods become plain links to these headings.

Decisions

Each point has a proposed default. A reply such as "agree with all except 4" is enough.

Updated after the first replies: items 4, 5, 7, 8 and 9 now reflect what was found while implementing them in docs-update.

1. Go or no-go

Migrate the user guide source from RST to Markdown and build it with Material for MkDocs.

Proposed: go. As noted in #10133, the content is what matters, and Zensical stays compatible with the same Markdown and mkdocs.yml if we ever move.

2. Cutover

  • Proposed: a one-time conversion PR to develop that replaces user_guide_src with the Markdown, mkdocs.yml, the theme overrides and requirements.txt, then merged up into 4.8.
  • A short freeze on user guide PRs while it is open. Open RST PRs would need rebasing onto the Markdown afterwards. docs-update converts single pages (make convert PAGE=libraries/email), so the changed RST pages can be run through it individually.
  • docs-update is archived once those PRs are rebased. The Markdown becomes the only source, and nothing converts RST at release time.

Which release should ship it?

  • 4.7.6, the next patch release
  • A later 4.7.x, if 4.7.6 comes too soon to review the preview
  • 4.8.0, with the PR to 4.8 only

The change touches no framework code, so a patch release can carry it. Landing it on develop keeps one format on both branches. With 4.8.0, develop stays on RST until the release, so docs fixes there would conflict with the Markdown on every merge-up.

3. URLs

Sphinx publishes libraries/email.html. MkDocs defaults to libraries/email/.

Proposed: keep the .html URLs (use_directory_urls: false), so existing links and search results into codeigniter.com/user_guide/ keep working. RST-specific anchors (:ref: labels and PHP object anchors) mostly change to heading slugs, so old links that use an anchor still open the right page but lose the scroll position.

4. Version switcher

The current switcher (#10135, #10665) offers Stable and Latest, and a third entry for the next minor is planned.

Proposed:

Entry Built from Served at
Stable release tag codeigniter.com/user_guide/, unchanged, through codeigniter4/userguide
Latest develop codeigniter4.github.io/CodeIgniter4/develop/
Next minor 4.8, later 4.9 codeigniter4.github.io/CodeIgniter4/next/
  • Pages deploys from GitHub Actions in place of the gh-pages branch, which is then deleted. This needs the repository's Pages source changed to "GitHub Actions".
  • A push to develop or the minor branch builds both branches into develop/ and next/, writes a versions.json listing the three entries, and deploys the result as one Pages artifact. The folder is always next/, so its links do not go stale. When a minor ships, one workflow variable changes to name the following minor's branch and label, such as "Next minor (4.9)".
  • The root /CodeIgniter4/ redirects to develop/, so current links keep working.
  • A small theme script reads versions.json and shows the entries in the header. It reuses the styling of Material's version selector, which cannot link to another host.
  • Switching keeps the reader on the same page, and goes to that version's home page when the page does not exist there. This check needs CORS headers from the other host. Without them on codeigniter.com, a page missing from Stable shows a 404.

The alternative is hosting all versions on Read the Docs, which changes where codeigniter.com/user_guide points. I'd rather keep the current hosts and URLs as part of this migration.

5. EPUB

Every release currently ships CodeIgniter<version>.epub in codeigniter4/userguide, and all 76 files are still there. MkDocs has no first-party EPUB output. The current consumers:

  • verify-release.yml waits for the new file and fails without it, so it needs changing (item 7).
  • The codeigniter.com home page mentions "1.6MB for the user guide (epub)".
  • GitHub's traffic shows a few readers: 27 views of six EPUB files over 14 days, including old versions. These are page views, not downloads.

Proposed: stop adding new EPUBs and keep the existing ones. This can be reversed, since a later request can be met by building any release's EPUB from its Markdown with pandoc. A first trial produced a 1.5 MB file, but it needs a small filter for admonitions, dollar signs, links and images, and has not been opened in a reader yet.

6. Fonts

Material loads Roboto from Google Fonts by default. #10133 proposes self-hosted Inter and JetBrains Mono.

Proposed: turn off Material's Google Fonts loading and self-host Inter and JetBrains Mono, as proposed in #10133.

Corrected after the first replies: this item originally said that #10133 had moved to Bunny Fonts, but that PR now self-hosts them.

7. Release tooling

These scripts edit the RST guide directly or depend on the EPUB, and need porting in the cutover PR, with no change to the rest of the release steps:

  • admin/prepare-release.php edits conf.py and changelogs/v{version}.rst
  • admin/update-upgrade-guide.php writes installation/upgrade_{version}.rst
  • admin/create-new-changelog.php and admin/generate-changelog.php
  • .github/scripts/deploy-userguide and the user guide workflows (test-userguide.yml, deploy-userguide-latest.yml, deploy-distributables.yml)
  • verify-release.yml, admin/RELEASE.md and contributing/documentation.rst, for the EPUB steps

Proposed: the version moves from conf.py into mkdocs.yml, and test-userguide.yml runs mkdocs build --strict on every PR.

8. Docs for coding agents

Related to #10638. Once the source is Markdown, the build can also publish llms.txt (a page index), llms-full.txt (the whole guide in one file) and each page's Markdown beside its HTML, such as libraries/email.md.

A small standalone script in the repository (admin/llms.py) does this from our own pages. It reads only the nav and the Markdown, with no MkDocs API, so it runs the same after any builder, and it needs only Python and PyYAML, which MkDocs already installs. The pages already have every code sample inline, so nothing has to add samples back. I tried the mkdocs-llmstxt plugin first, but it rebuilds the Markdown from the rendered HTML, which loses code fence languages and admonitions, and it needs Python 3.11 or newer.

Proposed: ship these files in codeigniter4/userguide and on the hosted site. Nothing goes into codeigniter4/framework or appstarter. With the package from item 9, installing the docs is opt-in and matches the framework version, so local tools such as an MCP server or an editor's docs search can index the docs for the exact installed version, offline. The framework download does not grow, and a docs failure cannot block a framework release. No AGENTS.md is added to appstarter.

9. codeigniter4/userguide as a Composer package

The repository is tagged on every release but has no composer.json and is not on Packagist. It also holds every EPUB since 4.0.0-alpha.3 and the HTML guide, about 90 MB.

Proposed:

  • Add a composer.json (codeigniter4/userguide, no autoload) and a .gitattributes to admin/userguide/, which deploy-userguide already copies into the repository on each release.
  • The .gitattributes export-ignores the EPUBs, the HTML and the site's assets, so the Composer download holds only the Markdown pages and the llms*.txt files. A test with git archive gave a 1.3 MB zip.
  • Register the package on Packagist once. Packagist only lists tags that contain a composer.json, so the first version is the first release after the cutover.

Then composer require --dev codeigniter4/userguide installs the docs for the matching version, with pages at paths such as vendor/codeigniter4/userguide/docs/libraries/email.md.

After the decisions

I'll prepare the cutover PR with the ported tooling and workflows, plus the switcher, and post the preview of the converted guide for review before the freeze starts.

Activity

  1. michalsn commented on Oct 29, 2026

    @michalsn
    Member

    First off, thank you Paul for all the work you've done recently on the docs-update repo!

    I agree with all the points raised. We should get this done ASAP and then migrate to the 4.8 branch.

    I also ran the docs locally, and everything looks pretty good!

  2. lonnieezell commented on Oct 29, 2026

    @lonnieezell
    Member

    Looks like you've done a ton of work on this. Thanks for that!

    It looks great. I agree with all points.

  3. michalsn commented on Oct 30, 2026

    @michalsn
    Member

    I just remembered that we have some security advisories to release with 4.7.6, so it might be easier to start the transition right after the release. Otherwise, merging these changes could get complicated. What do you think?

  4. paulbalandan commented on Oct 30, 2026

    @paulbalandan
    MemberAuthor

    Yes, I was thinking the same. To 4.7.7 will be a lot easier.

  5. paulbalandan commented on Oct 30, 2026

    @paulbalandan
    MemberAuthor

    I corrected item 6 in the issue body. It said #10133 had moved to Bunny Fonts, but that PR now self-hosts its fonts.

    docs-update now self-hosts Inter and JetBrains Mono from #10133, with Material's Google Fonts loading turned off and code ligatures on. Since the earlier replies only saw the old wording, please say if you'd rather not have JetBrains Mono or the ligatures. Both are easy to take out.

  6. michalsn commented on Oct 30, 2026

    @michalsn
    Member

    I'm okay with the current state.

  7. paulbalandan commented on Oct 30, 2026

    @paulbalandan
    MemberAuthor

    I updated the issue body with what came up while implementing these in docs-update. The note under Decisions lists the items. The main changes since your replies:

    • Item 5 (EPUB): the proposal is now to stop adding new EPUBs and keep the existing 76. verify-release.yml depends on the EPUB, so it changes in the cutover PR. The codeigniter.com home page mentions it, and GitHub's traffic shows a few people still viewing the files. It can be brought back later with pandoc if needed.
    • Item 8 (agent docs): a small MkDocs hook replaces the mkdocs-llmstxt plugin, because the plugin rebuilt the Markdown from HTML and lost code fence languages and admonitions. Each page's Markdown now sits beside its HTML.
    • Item 9 (Composer package): a test archive gave a 1.3 MB zip of the Markdown and llms*.txt files.

    Items 4 and 7 have smaller updates. Please say if any of this changes your earlier agreement. The cutover still starts after 4.7.6.

  8. michalsn commented on Oct 30, 2026

    @michalsn
    Member

    5 - We should drop it and never look back
    8 - That will require some automation to include all the code samples back into the Markdown files we generate? I wouldn't rely heavily on MkDocs, since that will make an eventual switch to Zensical harder.
    9 - Sounds fine to me.

  9. neznaika0 commented on Oct 31, 2026

    @neznaika0
    Contributor
    1. Markdown looks better and simpler. Personally, I like the style and large fonts. The transition is a justified step.
    2. Of course, you want to see new things faster. To avoid problems, I would release this in version 4.8. If I'm not mistaken, the new version is released in about a year, there's not much time left.
    3. The links in the index will be updated gradually. The problem will be with the posted texts (posts, articles). But yes, .html is logical to leave.
    4. The links codeigniter4.github.io/CodeIgniter4/4.8/ will become outdated over time. It would be correct to use /next/ — this way, you can see the latest articles at any time. I would prefer to have a version history. There are more and more notes like “Added in version 4.6”. But the information stops being new after the release of the next version, 4.7, and that’s normal.
    5. I’ve never read EPUB. Probably, it’s an atavism from the early versions.
    6. Local fonts are good. The browser cache works great.

    Regarding the parsing of PHP code when I first studied the framework, I was a bit surprised that there was such a description. Why, when all the main information is available in the IDE? I understand that long ago, people wrote in notepad++ and other simple editors. Now, I think, this has lost its relevance.

    In any case, thank you all.

  10. paulbalandan commented on Nov 1, 2026

    @paulbalandan
    MemberAuthor

    Thanks for the feedback.

    Item 8: the Markdown pages already have every code sample inline, since the converter writes them in. The generated files are plain copies of those pages, so nothing has to put samples back. I agree with not relying on MkDocs here, so the hook is now a standalone script that reads only the nav and the Markdown. It produces the same llms.txt and llms-full.txt and runs the same after any builder.

    Item 4: I'll use /next/ for the next minor. The folder stays the same each cycle and only the label changes, such as "Next minor (4.8)". A version history isn't part of this proposal. Every release tag of codeigniter4/userguide already holds that release's built docs, so older versions could be served later. We can put this up as a follow-up issue if needed.

    Item 5: ok no new EPUBs. The existing 76 stay unless someone wants them removed.

    Item 2: the plan is still 4.7.7. If the Markdown waits for 4.8.0, develop stays on RST until then and every docs fix there conflicts with the Markdown on the merge-up.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    documentationPull requests for documentation only

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions