Repository navigation
docs: decisions needed to migrate the user guide to MkDocs #10683
Description
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/sourcewith 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
developand4.8:Check Count Pages 330 PHP signatures ( php:method,php:functionand so on)628 Code samples, literalincludeincluded2106 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:
- Download the
docs-develop(ordocs-4.8) artifact from the latest workflow run and unzip it into adocs/folder in a clone ofcodeigniter4/docs-update. - Run
make install, thenmake 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 serveThe 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
developthat replacesuser_guide_srcwith the Markdown,mkdocs.yml, the theme overrides andrequirements.txt, then merged up into4.8. - A short freeze on user guide PRs while it is open. Open RST PRs would need rebasing onto the Markdown afterwards.
docs-updateconverts single pages (make convert PAGE=libraries/email), so the changed RST pages can be run through it individually. docs-updateis 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.8only
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-pagesbranch, which is then deleted. This needs the repository's Pages source changed to "GitHub Actions". - A push to
developor the minor branch builds both branches intodevelop/andnext/, writes aversions.jsonlisting the three entries, and deploys the result as one Pages artifact. The folder is alwaysnext/, 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 todevelop/, so current links keep working. - A small theme script reads
versions.jsonand 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.ymlwaits for the new file and fails without it, so it needs changing (item 7).- The
codeigniter.comhome 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.phpeditsconf.pyandchangelogs/v{version}.rstadmin/update-upgrade-guide.phpwritesinstallation/upgrade_{version}.rstadmin/create-new-changelog.phpandadmin/generate-changelog.php.github/scripts/deploy-userguideand the user guide workflows (test-userguide.yml,deploy-userguide-latest.yml,deploy-distributables.yml)verify-release.yml,admin/RELEASE.mdandcontributing/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.gitattributestoadmin/userguide/, whichdeploy-userguidealready copies into the repository on each release. - The
.gitattributesexport-ignores the EPUBs, the HTML and the site's assets, so the Composer download holds only the Markdown pages and thellms*.txtfiles. A test withgit archivegave 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
michalsn commentedon Oct 29, 2026
First off, thank you Paul for all the work you've done recently on the
docs-updaterepo!I agree with all the points raised. We should get this done ASAP and then migrate to the
4.8branch.I also ran the docs locally, and everything looks pretty good!
lonnieezell commentedon Oct 29, 2026
Looks like you've done a ton of work on this. Thanks for that!
It looks great. I agree with all points.
michalsn commentedon Oct 30, 2026
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?
paulbalandan commentedon Oct 30, 2026
Yes, I was thinking the same. To 4.7.7 will be a lot easier.
paulbalandan commentedon Oct 30, 2026
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-updatenow 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.michalsn commentedon Oct 30, 2026
I'm okay with the current state.
paulbalandan commentedon Oct 30, 2026
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:verify-release.ymldepends 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.mkdocs-llmstxtplugin, because the plugin rebuilt the Markdown from HTML and lost code fence languages and admonitions. Each page's Markdown now sits beside its HTML.llms*.txtfiles.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.
michalsn commentedon Oct 30, 2026
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.
neznaika0 commentedon Oct 31, 2026
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.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.
paulbalandan commentedon Nov 1, 2026
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.txtandllms-full.txtand 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 ofcodeigniter4/userguidealready 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,
developstays on RST until then and every docs fix there conflicts with the Markdown on the merge-up.