May 25, 2026
Blog PostMediaWiki Extension Development Walkthrough

At WikiTeq, we have created dozens of custom extensions for our clients, and we would be happy to meet with you to discuss developing an extension to fit your needs. But, if you want to go through the process of creating the extension from scratch yourself, this blog post should give you a good overview of what you need to do.
Requirements for Extension Development
To start off, you are going to need to have a wiki that you can test against. Make sure you have backend access to it. The simplest option is going to be to set up a local wiki running on your own machine using docker. You can consult our existing blog post for details of how to do that: https://wikiteq.com/post/setting-up-a-local-wiki.
Note that the version of MediaWiki used for that blog post is now no longer supported – generally, you should use the latest version of MediaWiki available, or at least the latest long-term support version. The rest of this blog post will assume you are developing against MediaWiki 1.43. You should also have some version control software available to help track the development of your extension – we recommend git, which is what is used for MediaWiki and many other tools, but other options including mercurial and subversion also work.
Initial Extension Creation
The first step in creating an extension is to choose a name. For this blog post, let’s assume you are going to create an extension called WikiTeqDemo. If you choose a different name, replace the various places that “WikiTeqDemo” appears in the instructions below with your chosen name.
Your testing wiki should have an existing directory of extensions, with each extension in a dedicated folder and all those folders nested under …/extensions/.
Create a new directory for your new extension, …/extensions/WikiTeqDemo/, and in that directory create an extension.json file that will hold the registration details of your extension.
At a minimum, that file needs to specify:
• The extension name – in our case, “WikiTeqDemo”
• The manifest version used – this should always be set to “2”
Create the extension.json file with:
```
{
“name”: “WikiTeqDemo”,
“manifest_version”: 2
}
```
And really, technically, that’s it – you have successfully created an extension! It isn’t running on your wiki, and it doesn’t really do anything, but you have created an extension! It would be anticlimactic if we ended the walkthrough here, so let’s try to add some actual utility to the extension.
Before we start adding functionality, we should probably make sure the extension loads properly. In your configuration file (LocalSettings.php), you need to enable your extension: add the line wfLoadExtension( ‘WikiTeqDemo’ );. At this point, the extension should be running on the wiki – but, since we haven’t added any functionality, the only real way to confirm that the extension is running is to ask the wiki for a list of extensions that are active. Navigate to the Special:Version page on your wiki and confirm that you see an entry for your new extension.
Possible Extension Functionality
The next step is starting to implement the real functionality for your extension, and how to do that depends on what type of extension you want to create. Broadly, extensions will likely do one of the following:
• Expand WikiText functionality with new parser functions and hooks (ParserFunctions, Cite, Poem, SyntaxHighlight)
• Work to improve the editing interface and experience (VisualEditor, WikiEditor, CodeEditor, DiscussionTools, TemplateData)
• Help system administrators and on-wiki maintainers combat spam and vandalism (AbuseFilter, CheckUser, Nuke, SpamBlacklist, TitleBlacklist, ConfirmEdit)
• Improve the account management process (LoginNotify, OATHAuth)
• Automate or streamline repetitive tasks (CiteThisPage, Linter, ReplaceText)
• Add support for new types of content on the wiki (Scribunto)
Or some combination of these. This is by no means an exhaustive list, and plenty of extensions do something more niche. The important thing is that almost all extensions plug into MediaWiki core using the same set of interactions:
• Adding new special pages / API modules / page actions / content models
• Implementing ResourceLoader modules for front-end interactive logic and styles
• Running custom code in hook handlers
Because there are so many different options for how an extension can interact with MediaWiki, this blog post will not be able to cover all of them. However, the general advice is the same for development with any of these integration points:
• Start by adding some equivalent of “Hello, World!” to make sure the new special page or whatever is being registered with MediaWiki, before you dive in to adding the functionality.
• Test frequently on your development wiki.
• Save your work using version control so that you can track changes.
• Consult documentation and existing examples for inspiration and help.
If you decide that you want some help with your extension, WikiTeq could build the extension for you, or we also offer a dedicated training course on how to build an extension from scratch. The extension that we developed for that course, “MinimalExample”, is public at https://github.com/WikiTeq/mediawiki-extension-MinimalExample. That repository has a commit for each thing that is being demonstrated: for example, when registering the special page Special:DoesUserExist, you can see that we started with just adding the page with a placeholder message (b346509). It wasn’t until the next few commits that the functionality was built up – adding an input form, handling request parameters, etc.
Adding Placeholders
The approach of adding placeholders to the initial output, and later implementing the actual functionality, is a common one that you can see in the MinimalExample repository, and it is an approach that we recommend for developers not yet familiar with MediaWiki’s code base and extension points. For example, in the MinimalExample extension when we added the API module for checking if a user exists, the initial commit (7800adf) created an API module with zero parameters always returned a message that the module hadn’t been implemented yet. First we had a placeholder, and then later we implemented the functional logic.
For testing out API modules, especially those that need to be submitted with POST requests, we recommend using the Special:ApiSandbox special page, see the documentation: https://www.mediawiki.org/wiki/Help:ApiSandbox.
You can also see the use of placeholders with the parser functions we created, {{PAGECONTENTMODEL:xxx}} - in the initial implementation (19d2ecb), the parser function would just output “PAGECONTENTMODEL: not implemented yet” regardless of the parameters passed.
By separating out the process of connecting the special page/API module/parser function from the process of implementing it, it can be easier to identify issues when things go wrong. If you run into an error before your functionality is present, the issue is likely caused by the integration between your extension and MediaWiki. If the placeholder version of the code worked, then the issue would be more likely to step from the code to implement the functionality.
General MediaWiki Extension Advice
Autoloading
To make things easier when adding new PHP classes, we recommend using namespace-based autoloading (see https://www.mediawiki.org/wiki/Manual:Extension.json/Schema#AutoloadNamespaces). In your extension.json, add
```
"AutoloadNamespaces": {
"MediaWiki\\Extension\\WikiTeqDemo\\": "src/"
},
```
and then files in the src/ directory of your extension can be automatically loaded by PHP when referenced, e.g. the class \MediaWiki\Extension\WikiTeqDemo\MySpecialPage will try to load from the src/MySpecialPage.php file.
Dependency Injection
Many of the places that extensions can add functionality, including hook handlers, special pages, API modules, and content handlers, support having various services injected with dependency injection. While using dependency injection (DI) is considered the best practice within MediaWiki development, it can make the initial development of new classes more complicated.
Until you are sure which services your special page (or other class) is going to need, don’t be afraid to retrieve the services directly from a MediaWikiServices instance (obtained via MediaWikiServices::getInstance()). Once your code is functioning and stable, then you can migrate to using dependency injection.
For some examples of the migration to dependency injection, the following (non-WikiTeq) patches show the addition of injected dependencies in different types of classes:
• https://gerrit.wikimedia.org/r/c/mediawiki/extensions/CategoryTree/+/736111 (API module)
• https://gerrit.wikimedia.org/r/c/mediawiki/extensions/ReadingLists/+/1160012 (Hook handler)
• https://gerrit.wikimedia.org/r/c/mediawiki/extensions/ImageSuggestions/+/1013221 (Job class)
• https://gerrit.wikimedia.org/r/c/mediawiki/extensions/GlobalPreferences/+/1074747 (special page)
• https://gerrit.wikimedia.org/r/c/mediawiki/extensions/TemplateStyles/+/1183186 (Content handler)
The specification of classes with dependencies injected is documented at https://www.mediawiki.org/wiki/ObjectFactory.
Other
Some additional tips regardless of what kind of extension you are creating:
• Identify any existing functionality that is similar, or even just slightly similar, to what you are trying to do, and look through the code for that. E.g. if you want to add a new parser function, look at how existing extensions add parser functions.
• If you are considering implementing a hook, the category https://www.mediawiki.org/wiki/Category:Extensions_by_hook_usage on MediaWiki.org allows browsing extensions that implement a specific hook, so you can see how they use the hook.
• If you want to add a new special page or API module, you can also look at MediaWiki core’s special pages and API modules, the differences between MediaWiki core and extensions are much smaller for special pages and API modules compared to other integration points.
• Don’t reinvent the wheel – MediaWiki provides a huge number of existing service classes that can easily be injected into your new PHP code, and helper modules for use in your JavaScript code. Identify the version of MediaWiki you are developing against, and consult the documentation for that version at https://doc.wikimedia.org/mediawiki-core/ - there is documentation for both the PHP services and the JavaScript tools that MediaWiki provides.
• Use phpcs and phan to enforce MediaWiki conventions and make things easier to maintain.
• Run the tests provided by MediaWiki core, even if you haven’t yet written any tests of your own yet – the existing tests can frequently catch mistakes.
Additional resources:
• https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Developing_ extensions
• https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Special_pages
• https://www.mediawiki.org/wiki/Special:MyLanguage/API:Extensions