It's better when it's simple

User Tools

Site Tools


How to convert a WordPress theme to a DokuWiki template

Seen a nice WordPress theme you wish was available as a DokuWiki template? Need a wiki alongside your company's blog in the same style? This tutorial will walk you through all the necessary steps to convert a WordPress (WP) theme to a DokuWiki (DW) template.

1. Start with Starter template

Follow the first 3 steps on the general template tutorial: Getting started (i.e. copy the Starter template). The rest of this tutorial will explain how to do the 4th step.

Commit already to be able to see differences later.

2. Basic HTML/PHP

  • Read about the main window to understand words and functionality used in the following.
  • Refer to templates and main.php to read what every DW function is used for.
  • Refer to WP vs. DW functions for knowing which WP function can be substituted with which DW function.

Meta elements

Copy any relevant meta elements (anything between <head></head>) from WP's header.php which DokuWiki doesn't already provide into DW's main.php.

Check if the WP theme adds anything to the body classes via add_filter( 'body_class', [...] );. If yes, add them to the element which includes the tpl_classes(). In case that element is not the body and the CSS contains any body selectors with such classes (body.), you would either need to move the tpl_classes() into the body or change the CSS accordingly (e.g. by just removing the body. in such cases).

Site containers

Copy anything between WP's <body> and its header in header.php to DW's main.php between the <body> and the start of the HEADER section. Don't overwrite DW's functions there but merge them into the code from WP.

Make sure every element is closed properly at the bottom (or removed at the bottom if you removed any element).

Copy the code for the header from WP's header.php into DW's HEADER section in main.php. Substitute WP functions with DW functions and delete the code for the DW header (except for the breadcrumbs, copy that code somewhere else to re-use later).

You can also extract that code into its own file and include it there instead.

Content area

Copy the start of the content main area from the end of WP's header.php, the beginning and end of index.php into the CONTENT aread in main.php and close everything like in the beginning of footer.php.

The only thing essential to keep is <?php tpl_content() ?> for the actual content.

Copy most of WP's footer.php into DW's FOOTER section. Keep at least DW's tpl_pageinfo() and tpl_license(). Adding a link back to would be nice.

Templates usually have 0, 1 or 2 sidebars. When a template has a sidebar, it can be optional or permanent. Even if the original WP theme doesn't have a sidebar, you should consider adding one anyway. And if the original WP theme has a permanent sidebar, you should consider making it optional.

DW has a core setting ($conf['sidebar']) which every template with a sidebar should use to determine a) if to show a sidebar and b) which page should be included for the sidebar content.

The way sidebars are usually done in DW are not exactly equivalent with how they are done and how they behave in WP. You could implement your own way of dealing with sidebars but the DW way should be fine for most circumstances. With tpl_include_page() you can include the content of the “nearest” page with the name you pass through to it:

<?php tpl_include_page($conf['sidebar'], 1, 1) ?>

Because the functionality is different from WP's usual sidebar, most “widgets” will be implemented with plugins rather than in the template. Therefore, most of the widget CSS can be safely deleted.

WP vs. DW functions

Most of the above will require you to change WP-specific functions to DW-specific functions. These are usually within <?php ?> blocks.

What WordPress DokuWiki Notes
wiki/blog title


echo $conf['title']
echo $conf['tagline']
link to home page
echo home_url('/')
echo wl()
body classes
echo tpl_classes()
but the DW version doesn't need to be on the body
language strings
_e('Skip to content', '<tpl>')
echo $lang['skip_to_content']
DW: core string; WP: template string
_e('Sidebar', '<tpl>')
echo $lang['sidebar']
DW: core string; WP: template string
_e('Menu', '<tpl>')
echo tpl_getLang('menu')
DW: template string; WP: template string
tpl_include_page($conf['sidebar'], 1, 1)
not exact equivalent
if (page_findnearest('nav')){
    tpl_include_page('nav', 1, 1);
not exact equivalent

Logo in WP:

<?php $header_image = get_header_image(); ?>
<?php if (!empty( $header_image )): ?>
    <img src="<?php header_image() ?>" width="<?php echo get_custom_header()->width ?>" height="<?php echo get_custom_header()->height ?>" alt="" />
<?php endif; ?>

Logo in DW:

    $logoSize = array();
    $logo = tpl_getMediaFile(array(':wiki:logo.png', ':logo.png', 'images/logo.png'), false, $logoSize);
    echo '<img src="'.$logo.'" '.$logoSize[3].' alt="" />';

Language strings

Whenever the core $lang (in inc/lang/en/lang.php) already contains a language string you need, you can simply use $lang['foo']. But if you need any other language string, you need to add your lang/en/lang.php file to your template. Then you can use any string in there with tpl_getLang('bar').

3. Basic CSS


Copy WP's style.css to DW's css/style.less (use the .less extension to take advantage of LESS, a CSS pre-processor) and add it to the style.ini.

css/style.less = screen

If style.less contains any @media queries, you need to either change the screen media type to all.

css/style.less = all

Or you can extract the @media queries into separate CSS files and add them to the style.ini with the all media type.

It is advisable but not necessary to split the original CSS file into separate files to ease maintenance. Each of those will need to be added to the style.ini.

Check what you might need from the previously existing CSS files and copy what you need into your own files and delete the original ones, including removing their lines in style.ini.


Copy WP's rtl.css over as rtl.less and add it to the style.ini. DW implements styles for RTL scripts differently than WP, that's why you need to adjust rtl.less to be surrounded by

[dir=rtl] {
/* here is the content */
} /* /rtl */

If the rtl.less includes @media queries, the file needs to be added with the all media type and the [dir=rtl] {} needs to be added around each block inside the @media query, e.g.

@media only screen and (max-width: 767px) {
  [dir=rtl] {
    /* the CSS */

You will potentially need to add to this file later…


Move the print section from the original style.css into print.less. Remove the @media print {} around the styles and add it to style.ini as well:

css/print.less = print

Necessary changes

Adjust all paths (to images, fonts, etc) to be relative to the template's root. E.g. if you have images in an “images” folder, your paths should be like url(images/foo.png).

4. JS

Copy all relevant JS (not including JS meant for the admin screens) to a DW subfolder. Add a script.js in the template's root folder and add all the copied JS files with the include syntax, e.g.

/* DOKUWIKI:include js/foo.js */
/* DOKUWIKI:include js/bar.js */

If the theme's JS is only based on jQuery (and/or jQuery-UI), you don't need to do anything more. But some themes use other libraries which would need to be copied over from WP's wp-includes/js/ folder as well. Check your theme's functions.php for any wp_enqueue_script()s which have a third parameter ($deps = dependencies) with anything else but an empty array() or array('jquery') in it.

5. Further HTML/PHP

Other layouts

DW has two more layout files. While main.php is, well, the main layout file, there is also mediamanager.php for the popup media manager and detail.php for the image detail page.

The media manager popup layout is pretty well defined and cannot change much. So you would only need to potentially change some meta elements and some site containers. This might require a bit more work, manually fixing potential issues.

You have more freedom with the image detail page. You can either move your whole layout into that file (including header and sidebar, etc) or create a different, minimal layout.

Special DW elements

DokuWiki has certain things WordPress doesn't have. You need to decide on a template by template basis where to put those, how to style them and what to do with them:

  • Page, Site and User tools: These include DokuWiki-specific action links (or buttons), e.g. the “Edit this page”, “Sitemap” or “Log In” links. Depending on the type of template, you need to decide where to put them. E.g. for CMS- or blog-type wikis they could be shoved to the bottom of the page, whereas for wiki-type wikis they are more central and at least the page tools should be close to the content and the others somewhere in the header or sidebar.
  • Breadcrumbs: Breadcrumbs can be hierarchical or just a trail of your last visited wiki pages or both. They should rather be in the top area of the page. As they are just a bunch of links, they should be easier to style than the other special elements.
  • Table of contents: The TOC is already placed at the top of the page content (although it is possible to place it outside), so you would only need to style them to fit the template.

Other actions

Following all the tool links will also make possible to check all the other modes and fix potential issues. This needs to be done on a template by template basis as the issues are difficult to predict.

Concentrate first on the modes most users are likely to see most, i.e. edit, search, login,… Something like the admin section on the other hand doesn't need to be pretty but it should at least be workable.

6. Further CSS


Guaranteed colour placeholders

Get all the different colour values of the theme (there are some browser plugins which can do that for you, so you don't need to peruse the code yourself) and change the “guaranteed dokuwiki color placeholders” in the style.ini to them. If you have less colours available, either leave the existing ones (they are usually universal enough) or try to make up some sensible colour alternatives. All the “guaranteed” values need to exist.

If you have more than those colours, you should make up your own entries (with __variable_name_color__) below the guaranteed ones for the rest of them.

When you have all your colours defined, you need to substitute them in all your CSS files. Just search and replace each colour value with @ini_variable_name_color.


If you have this in your style.ini

__theme_color__ = "#123456"

You need to substitute each #123456 with @ini_theme_color.

If the WP theme comes with several CSS files for various colour schemes, you can delete them completely as you don't need them anymore. Any important colour changes can be done with simple changes in the style.ini.

Other values

You can have other values than colours as a style.ini placeholder. Anything you'd like to be configurable which has to do with CSS can be driven by this. E.g. set the template width or responsive breakpoints or fonts or font sizes or a background image or drive various sub themes with a variable…

WP vs. DW classes

There are certain functionalities which both DW and WP have but which are expressed in different class names.

What WordPress DokuWiki
hide something accessibly screen-reader-text a11y
clearing floats clear group
align media left alignleft medialeft
align media right alignright mediaright
align media centred aligncenter mediacenter
menu item with children li.node
selected menu item li.current_page_item|current-menu-item li .curid
parent(s) of selected menu item li.current_page_ancestor
+ li.current_page_parent

There are several ways to fix this.

If you need or want to keep your styles closer to the WP (e.g. so that it's easier to update upstream changes), you should use “the lazy way”. If you need or want to keep the CSS smaller and make maintainability easier, you should use “the clean way”.

The lazy way

When you cannot change the class DW gives you (media alignment and menu classes), let the class from DW inherit the one from WP. This is possible with the power of LESS.

.class-from-dw {

This might not always work 100% as sometimes you have to cater for different child elements/classes.

When you don't need to use the DW classes (a11y and group), you can ignore them and keep the WP styles. But if the WP styles are adding anything which the DW styles don't have, you can let the class from WP inherit the one from DW (so, the other way around as the example above).

.class-from-wp {

The clean way

You can also just search for all WP classes and replace them with the DW classes in both HTML/PHP and CSS/LESS. That might also not work 100% as you might need to fix other selectors (especially in menus). But the amount of possibly necessary fixes will be the same in both ways.

7. Rename IDs

To avoid conflicts with automatically created IDs you should rename all IDs. Best just include <template-name>__ in front of every ID (inside HTML, CSS and JS).

8. Support specific custom WP theme functionality

Custom colours

Due to the power of the style.ini you don't need to do anything to support custom colours, they are already supported!

Custom background

You can prepare a custom background image in the CSS but without adding the actual image. Then add this to your template's main.php:

... style="background-image: url(<?php echo tpl_getMediaFile(array(':wiki:background.png', ':background.png', 'images/background.png') ?>);
);" ...

This way users can (similarly to the logo) upload their own background images via the wiki's media manager, as long as they are called background.png.

FIXME Add more…

Further Reading

echo get_bloginfo('name', 'display')
devel/wp_to_dw_template.txt · Last modified: 2023-02-28 13:29 by saggi

Except where otherwise noted, content on this wiki is licensed under the following license: CC Attribution-Share Alike 4.0 International
CC Attribution-Share Alike 4.0 International Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki