Native Markdown
Write wiki pages in Markdown, the widely used markup format and the native language of AI agents, rendered as real wiki pages
On this page
External links
Native Markdown for MediaWiki
Native Markdown makes Markdown a native MediaWiki content model. Whole pages are stored as Markdown and rendered as real wiki pages, with working links, categories, templates, a table of contents, and full-text search. Install it and new pages default to Markdown across the whole wiki, while existing pages stay as they are.
Professional Wiki created Native Markdown. We are MediaWiki developers that provide professional MediaWiki services.
Usage Documentation
Markdown as a content model
The content model determines the format in which MediaWiki stores and renders a page. Native Markdown adds Markdown as a content model, so a Markdown page is not wikitext with Markdown embedded inside it. The whole page is Markdown, stored exactly as you typed it, and rendered as a real wiki page. Markdown pages and wikitext pages coexist on the same wiki, and you choose the model per page.
Wiki links, categories, and the table of contents
Wikitext link syntax works inside Markdown, with the semantics you know. [[Page]] gives you a
blue or red link depending on whether the page exists, and the link is tracked in Special:WhatLinksHere and
Special:WantedPages. [[Category:X]] assigns a category.
[[File:Diagram.png|300px|alt=Text|Caption]] embeds an image. Section links, same-page anchors,
and interwiki links all behave like their wikitext counterparts. The table of contents is the real
MediaWiki table of contents, built from your Markdown headings.
| Syntax | Effect |
|---|---|
[[Page]], [[Namespace:Page]] |
Internal link, blue or red by page existence, tracked in Special:WhatLinksHere |
[[Page|label]] |
Internal link with label |
[[Page#Section]], [[#Section]] |
Link to a section of another page or of the current page |
[[Category:X]] |
Assigns the category and renders nothing, like wikitext |
[[Category:X|sort key]] |
Assigns with a sort key |
[[:Category:X]] |
Visible link to the category page |
[[File:X.png]] |
Embeds the file at full size; missing files render as an upload link |
[[File:X.png|300px|alt=Alt text|Caption]] |
Embed with width, alt text and caption (tooltip); each parameter is optional |
[[File:X.png|thumb|Caption]] |
Framed thumbnail with the caption visible below the image, like wikitext thumbs |
[[:File:X.png]] |
Link to the file page instead of embedding |
[[wikipedia:Page]] |
Interwiki link, using the wiki's interwiki table |
#REDIRECT [[Page]] |
On the first line, makes the page a redirect, and a page move writes one automatically |
Anything inside [[...]] that is not a valid title renders as literal text.
A few behaviors differ from wikitext links:
-
Inside GFM table cells,
|separates columns before links are parsed, so write[[Page\|label]]with a backslash escape:| [[Page\|label]] |. -
Height-only image sizes (
x100px) are ignored; only the width of100pxor100x200pxis used. [[Media:X]]links land on the file description page rather than the raw file.-
Relative subpage links (
[[/sub]]) are not resolved; the text is treated as a literal page title. -
[[Special:...]]links render but are not recorded inSpecial:WhatLinksHere, as in wikitext.
Templates and parser functions
You can include your wikitext templates, such as infoboxes, directly in Markdown pages with the
usual {{...}} syntax. Expansion runs through MediaWiki's
own parser, so template dependencies are tracked (editing a template re-renders the pages that use
it), and the output is sanitized exactly as wikitext is.
Parser functions and magic words work inside the braces too, whether built into MediaWiki, like
{{PAGENAME}}, or added by extensions, like
{{#if:}}. Headings inside templates stay out of the table
of contents.
Where you place a call decides whether its output is block or inline, and how the braces are read:
- A call on its own line produces block output, so an infobox renders as a block rather than being wrapped in a paragraph. It may span several lines, including blank parameter lines, until the braces balance.
- A call within a line of text renders inline and has to stay on a single line. Multi-line calls must start on their own line.
-
Template arguments are wikitext rather than Markdown. Inside a GFM table cell, escape argument pipes
as
\|, and write\{\{to keep braces literal. -
A block call with no closing
}}renders as literal text through to the end of the page, since Markdown parsing cannot backtrack, so a forgotten brace shows up as visible braces to fix rather than a silent error.
The page source stays clean Markdown regardless: action=raw returns the literal
{{...}} you typed rather than the expanded output, so the
round trip for AI agents and git stays lossless.
A few less common things are out of scope in this version:
-
<ref>and<references/>in the Markdown body, where footnotes cover citations instead. Citation state is not shared across separate template calls on a page. -
Transcluding another Markdown page with
{{:Page}}. Its source would be reinterpreted as wikitext, so transclude wikitext pages instead. subst:does not substitute on save.
Transclusion and parser functions are on by default. Set
$wgNativeMarkdownWikitextExpansion = false to turn them off and leave
{{...}} as literal text. Turning the feature back on does not
reparse pages that already exist. They show template output once they are next edited or purged, and
running refreshLinks.php populates the template links eagerly.
Markdown flavor
The Markdown flavor is CommonMark plus GitHub Flavored Markdown: tables, strikethrough, task lists, and autolinks, with footnotes on top. Tables are automatically styled as wikitables. YAML front matter is parsed, hidden from the rendered page, and stored as page metadata. Raw HTML is always escaped, so page content cannot inject scripts or other active HTML into your wiki.
For readers coming from wikitext:
| Wikitext | Markdown |
|---|---|
'''bold''', ''italic'' |
**bold**, *italic* |
== Heading == |
## Heading |
* bullet / # numbered |
- bullet / 1. numbered |
[https://example.org label] |
[label](https://example.org) |
{| class="wikitable" ... |
GFM tables (| a | b |), styled as wikitable automatically |
<syntaxhighlight lang="php"> |
fenced code block: ```php (see syntax highlighting) |
<ref>Source</ref> |
footnote: [^1] plus [^1]: Source |
[[Page]], [[Category:X]], [[File:X.png]] |
identical (see wiki links) |
{{Template}}, parser functions, magic words |
transcluded through MediaWiki's parser (see Templates) |
MediaWiki already renders the page title as the top-level heading, so starting a page with a
# Heading is optional. When present, it becomes the first entry of the table of
contents.
Syntax highlighting
Fenced code blocks that name a language are syntax highlighted, the same way a wikitext
<syntaxhighlight> block is, so code looks the same on Markdown and wikitext pages.
This needs the SyntaxHighlight extension bundled with MediaWiki to be enabled. Without it, and for
blocks that do not name a language the highlighter recognizes, the code stays plain preformatted text.
A block like this:
```python
def fetch_markdown(title: str) -> str:
"""Return the page's stored Markdown, byte for byte."""
response = requests.get(f"{WIKI}/index.php", params={"title": title, "action": "raw"})
response.raise_for_status()
return response.text
```
renders as:
Editing
Editing happens in the standard edit form. With the CodeEditor extension installed you get Markdown syntax highlighting, and Show preview renders through the full pipeline. Diffs, history, undo, and rollback work as they do for wikitext pages, comparing and reverting the stored Markdown line by line. Edit conflicts are merged three-way at the Markdown source level, and genuinely conflicting edits surface the normal conflict screen.
Search
Full-text search indexes the rendered prose of a Markdown page rather than the raw markup, so keyword
lookups match what a reader sees. Search snippets are clean text instead of # and
** noise, and front matter stays out of the index. The index updates through the job queue
when a page is edited, so pages saved before Native Markdown was installed or upgraded keep their
previously indexed text until their next edit or a search index rebuild.
Built for AI agents
Markdown is the format that AI assistants like Claude and ChatGPT read and write best. Because Native Markdown stores pages as plain Markdown, an agent can read and edit them directly.
Fetching a page with action=raw returns the Markdown source exactly as it was saved, front
matter and all. The REST API (/rest.php/v1/page/{title}) reports
content_model: markdown alongside the source, so an agent knows what kind of page
it is working with. When an agent wants resolved links and the table of contents instead of the source,
action=parse returns the rendered HTML. Writing works through the ordinary editing APIs, or
more conveniently through the MediaWiki MCP Server, the tool that
lets AI assistants read and edit your wiki. The round trip is lossless: an agent can fetch a page, edit it,
and write it back without the content drifting through a wikitext translation. The same property makes
Markdown pages a good fit for round-trips with git repositories.
Current limitations
Development so far has focused on making the content model itself solid. A couple of MediaWiki editing features are not there yet: there is no VisualEditor support, and no section editing.
If your editors rely on VisualEditor, wikitext remains the right model for those pages, and both models coexist on the same wiki, so you choose per page. On the roadmap: mapping front matter to structured data such as Semantic MediaWiki properties, live preview and WYSIWYG editing, and import tooling for Obsidian vaults and git repositories.
Comparison with other Markdown extensions
Native Markdown exists because no other maintained MediaWiki extension makes Markdown a native content model. The alternatives embed Markdown inside wikitext pages or offer a thin content handler on top of a generic Markdown parser, so the Markdown never becomes a first-class wiki page.
-
Extension:WikiMarkdown
embeds Markdown blocks inside wikitext pages through a tag, plus a shallow
.mdcontent handler built on Parsedown. Inside that Markdown there are no working[[wiki links]], no category assignment, and no MediaWiki table of contents. Native Markdown makes the whole page Markdown, so links, categories, the table of contents, full-text search, and the link tables all behave the way they do on wikitext pages. - Extension:Markdown is archived and points visitors to WikiMarkdown.
- MarkdownExtraParser has been unmaintained for over a decade.
Related but different is our own ExternalContent extension, which embeds Markdown files from external sources such as GitHub into wikitext pages. Native Markdown is instead for the wiki's own pages being Markdown, and the two compose nicely.
Installation
Requirements
- PHP 8.1 or later
- MediaWiki 1.43 or later
Load and enable
Load the extension using Composer:
COMPOSER=composer.local.json composer require --no-update professional-wiki/native-markdown:~1.0
Enable the extension by adding the following to your LocalSettings.php:
wfLoadExtension( 'NativeMarkdown' );
You can verify the installation by checking your wiki's Special:Version page.
Native Markdown is also available via our managed MediaWiki hosting, where you turn it on from the Admin Panel.
Configuration
Markdown is on by default. Once the extension is installed, new pages default to the Markdown content model
across the whole wiki, with deliberate exceptions where wikitext is load-bearing: the discussion (Talk)
namespaces, where signatures and threading depend on wikitext; the Template and MediaWiki namespaces; and
any namespace with an explicitly configured content model, for example Scribunto modules or JSON pages.
Titles ending in .css, .js, or .json never default to Markdown
either, since MediaWiki reserves those for code pages. The default affects page creation only. Existing
pages never change model, and individual pages can be switched between wikitext and Markdown, in both
directions, via Special:ChangeContentModel.
External links on Markdown pages honor the core $wgNoFollowLinks setting, and input size is
bounded by the core $wgMaxArticleSize limit, just as on wikitext pages.
To keep wikitext as the default, set $wgNativeMarkdownEverywhere = false; in
LocalSettings.php. To
offer Markdown only in specific namespaces, list them in $wgNativeMarkdownNamespaces. With
$wgNativeMarkdownSuffixDetection, a title ending in .md is read as a deliberate
per-page choice, so such new pages default to Markdown and both models can mix by naming convention.
Because the suffix is a deliberate choice, this mode also applies inside the Talk namespaces, unlike the
wiki-wide default, and a Markdown talk page created this way has no wikitext signatures or threading. It
still skips the Template and MediaWiki namespaces, where Markdown can act as neither a template nor an
interface message. Add those to $wgNativeMarkdownNamespaces to opt them in anyway. See the
configuration reference
for the full list of settings.
Converting existing pages
Activation modes apply at page creation only, so enabling suffix detection or adding a namespace never
touches pages that already exist. The NativeMarkdown:ConvertToMarkdownModel maintenance script
is the retroactive counterpart. It switches existing pages to the Markdown model using the same rules,
changing the stored content model rather than the page text. The stored wikitext is then reinterpreted as
Markdown and may render differently, so always start with --dry-run to review what would be
converted. The script suits pages whose text already is Markdown, such as files imported from a git
repository before Native Markdown was installed.
Two selectors choose the pages, and at least one is required:
-
--md-suffixfollows live.mdsuffix detection: titles ending in.md, in any namespace except Template and MediaWiki, Talk included. -
--namespace <id>follows$wgNativeMarkdownNamespacesand converts every page in that namespace. An explicit namespace is a deliberate choice, so it works for any namespace, Template and MediaWiki included.
Combined, the two narrow to the .md-titled pages inside a single namespace, so
--md-suffix --namespace 10 converts the .md pages in the Template namespace that
--md-suffix alone would skip. Only pages whose current model is wikitext are ever converted,
other models are left untouched, and redirects are skipped. Use --batch-size to control how
many pages each batch processes.
php maintenance/run.php NativeMarkdown:ConvertToMarkdownModel --md-suffix --dry-run
php maintenance/run.php NativeMarkdown:ConvertToMarkdownModel --namespace 3000
php maintenance/run.php NativeMarkdown:ConvertToMarkdownModel --md-suffix --namespace 10
Each conversion is an ordinary revision by the maintenance user, visible in page history and reversible per page with Special:ChangeContentModel, which stays the tool for one-off, two-way model changes.
More MediaWiki Extensions
Professional MediaWiki Services
MediaWiki services by the authors of Native Markdown
Get superior results from the best MediaWiki developers with a proven track record of creating MediaWiki extensions & integrations.
Make your wiki look great! Use a time-tested responsive MediaWiki theme, or have us create a custom MediaWiki skin for you.
Let us take care of your wiki. We are MediaWiki hosting experts and provide cloud hosting, dedicated hosting, and on-premise hosting.
Bring your wiki to the next level by leveraging our MediaWiki expertise. From strategic planning to wikitext, we have you covered.
Migrate your wiki with confidence. We move your MediaWiki to a new home, or we help you migrate from another system to MediaWiki.
Keep your MediaWiki up-to-date and secure. We offer MediaWiki maintenance services to keep your wiki running smoothly.