Creating a Custom DokuWiki Template — From Scratch Development Guide
In this tutorial, you'll learn how to create a custom DokuWiki template from scratch, including planning the design, creating template files, building the layout, adding CSS, and testing across browsers.
What You'll Learn
- Planning a custom template design
- Creating the template directory and manifest
- Building the main.php layout
- Adding CSS for styling
- Handling template inheritance
- Testing and debugging templates
Why It Matters
Pre-built templates like Bootstrap3 are powerful, but they are also complex. A custom template gives you complete control. You can create a minimal, fast-loading template that matches your brand exactly. You understand every line of code. No unused CSS, no unnecessary JavaScript, no dependency on third-party frameworks.
Real-World Use
A developer creates a custom template for a documentation wiki. The template is minimal — just CSS, no JavaScript framework. It loads in under 200ms (vs 800ms for Bootstrap3). The design matches the company's main website exactly. The template has no unused code, making it easy to maintain and update.
Learning Path
flowchart LR A[Bootstrap Template] --> B[Custom Template] B --> C[Template Configuration] C --> D[Caching] D --> E[SEO] E --> F[Multi-Language]
Planning Your Template
Before writing code, design your template:
Create a Wireframe
+----------------------------------------------------+
| HEADER: Logo | Search | User Menu |
+------------+---------------------------------------+
| SIDEBAR | MAIN CONTENT |
| Navigation | |
| Tags | |
| Recent | |
+------------+---------------------------------------+
| FOOTER: Copyright | Links | License |
+----------------------------------------------------+
Define Your CSS Requirements
- Color scheme (primary, secondary, background, text)
- Typography (headings, body, code)
- Layout (fixed width or fluid)
- Breakpoints for Responsive Design
- Component styles (buttons, tables, forms)
Creating the Template Structure
# Create template directory
mkdir -p lib/tpl/mytemplate/{css,images,lang/en}
# Create required files
touch lib/tpl/mytemplate/template.info.txt
touch lib/tpl/mytemplate/main.php
touch lib/tpl/mytemplate/css/style.css
The template.info.txt Manifest
base mytemplate
author Your Name
email your@email.com
date 2026-06-28
name My Custom Template
desc A minimal, clean template for documentation
url https://example.com/mytemplate
The main.php Layout
<?php
if (!defined('DOKU_INC')) die();
?><!DOCTYPE html>
<html lang="<?php echo $lang['lang'] ?>" dir="<?php echo $lang['dir'] ?>">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title><?php echo hsc($title) ?></title>
<?php tpl_metaheaders() ?>
<?php echo tpl_favicon() ?>
</head>
<body>
<div id="dw__container">
<header id="dw__header" role="banner">
<div class="dw-header-inner">
<div class="dw-logo">
<a href="<?php echo wl('start') ?>">
<img src="<?php echo tpl_url() ?>/images/logo.png" alt="Logo" height="40">
<span class="dw-wiki-title"><?php echo hsc($conf['title']) ?></span>
</a>
</div>
<nav class="dw-user-menu">
<?php tpl_userinfo() ?>
</nav>
</div>
<nav class="dw-navbar" role="navigation">
<ul>
<li><a href="<?php echo wl('start') ?>">Home</a></li>
<li><a href="<?php echo wl('projects:start') ?>">Projects</a></li>
<li><a href="<?php echo wl('guides:start') ?>">Guides</a></li>
<li><a href="<?php echo wl('about') ?>">About</a></li>
</ul>
<div class="dw-search">
<?php tpl_searchform() ?>
</div>
</nav>
</header>
<div id="dw__wrapper" class="dw-clearfix">
<aside id="dw__sidebar" role="complementary">
<?php tpl_sidebar() ?>
</aside>
<main id="dw__content" role="main">
<?php tpl_flush() ?>
<?php tpl_content() ?>
</main>
</div>
<footer id="dw__footer" role="contentinfo">
<div class="dw-footer-inner">
<p>© <?php echo date('Y') ?> <?php echo hsc($conf['title']) ?></p>
<p><?php tpl_license() ?></p>
</div>
</footer>
</div>
</body>
</html>
CSS Styling
/* lib/tpl/mytemplate/css/style.css */
/* Reset */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
/* Layout */
#dw__container {
max-width: 1200px;
margin: 0 auto;
padding: 0 20px;
}
.dw-clearfix::after {
content: "";
display: table;
clear: both;
}
/* Header */
#dw__header {
padding: 20px 0;
border-bottom: 2px solid #333;
}
.dw-header-inner {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
}
.dw-logo a {
text-decoration: none;
color: #333;
font-size: 24px;
font-weight: bold;
}
.dw-wiki-title {
margin-left: 10px;
}
/* Navigation */
.dw-navbar {
display: flex;
justify-content: space-between;
align-items: center;
background: #f5f5f5;
padding: 10px;
border-radius: 4px;
}
.dw-navbar ul {
list-style: none;
display: flex;
gap: 20px;
}
.dw-navbar a {
text-decoration: none;
color: #333;
padding: 5px 10px;
}
.dw-navbar a:hover {
background: #ddd;
border-radius: 3px;
}
/* Sidebar */
#dw__sidebar {
float: left;
width: 250px;
padding: 20px;
background: #fafafa;
min-height: 400px;
}
/* Main Content */
#dw__content {
margin-left: 270px;
padding: 20px;
min-height: 400px;
}
/* Footer */
#dw__footer {
padding: 20px 0;
border-top: 1px solid #ccc;
text-align: center;
color: #666;
}
/* Typography */
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
line-height: 1.6;
color: #333;
}
h1, h2, h3, h4 {
margin: 20px 0 10px;
color: #222;
}
a {
color: #0066cc;
}
a:hover {
color: #004499;
}
/* Responsive */
@media (max-width: 768px) {
#dw__sidebar {
float: none;
width: 100%;
min-height: auto;
}
#dw__content {
margin-left: 0;
}
.dw-navbar {
flex-direction: column;
gap: 10px;
}
.dw-navbar ul {
flex-direction: column;
align-items: center;
}
}
Additional Template Files
detail.php
For media detail pages, create a minimal detail.php:
<?php
if (!defined('DOKU_INC')) die();
?><!DOCTYPE html>
<html lang="<?php echo $lang['lang'] ?>" dir="<?php echo $lang['dir'] ?>">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title><?php echo hsc($title) ?></title>
<?php tpl_metaheaders() ?>
</head>
<body>
<div id="dw__detail">
<?php tpl_content() ?>
</div>
</body>
</html>
Optional HTML Files
Create header.html and footer.html for content that can be edited without modifying PHP:
lib/tpl/mytemplate/
├── header.html # Included before main content
├── footer.html # Included after main content
These files contain plain HTML and are included using tpl_includeFile().
Testing Your Template
1. Enable the Template
<?php
// conf/local.php
$conf['template'] = 'mytemplate';
2. Test All Page Types
- Normal page view
- Edit mode
- History / diff view
- Search results
- Media manager
- Admin pages
- 404 / non-existent page
- Sidebar-enabled pages
- Media detail page
3. Check Browser Compatibility
Test in:
- Chrome (latest)
- Firefox (latest)
- Safari (latest)
- Edge (latest)
- Mobile Safari and Chrome
Template Inheritance
If your template is based on another template, use the parent field:
base mychildtemplate
parent dokuwiki # Inherit from default template
Files in your child template override files from the parent template. For files not present in your template, DokuWiki falls back to the parent.
This is useful for making small customizations without duplicating an entire template.
Common Mistakes
- Not resetting CSS: Browsers have default styles that vary. Always include a CSS reset or normalize to ensure consistent rendering.
- Forgetting tpl_metaheaders(): Without this function call, CSS and JavaScript from plugins and DokuWiki itself are not loaded.
- Hard-coding page IDs: Use
wl('start')instead of/wiki/start. This ensures links work even if the wiki is moved to a different URL. - Not testing edit mode: Edit mode has different layout requirements than view mode. Test both.
- Skipping responsive design: More than 50% of web traffic is mobile. A template that does not work on mobile is a broken template.
Practice Questions
- What are the mandatory files for a custom DokuWiki template?
- Why is
tpl_metaheaders()essential in main.php, and what happens if it is omitted? - How does template inheritance work, and when would you use it instead of writing a template from scratch?
- Challenge: Create a complete custom template from scratch. The template should include: a fixed-width container (max 960px), a top header with logo and search, a left sidebar (250px) for navigation, a main content area, a footer with copyright and license info, responsive design that collapses the sidebar on screens under 768px, custom colors matching a given brand (#2c3e50 header, #ecf0f1 text), and proper handling of edit mode, history, and media pages. Test the template on all major browsers and at least two mobile devices.
FAQ
{{< faq "How do I add JavaScript to my template?" "Add script tags in the head section of main.php, or create a script.js file in your template directory and include it: <script src=\"<?php echo tpl_url() ?>/js/script.js\"></script>." >}}
Mini Project
Goal: Build and test a complete custom template.
- Plan a template design (draw a wireframe)
- Create the template directory structure
- Write
template.info.txt - Build
main.phpwith header, sidebar, content, and footer - Create
detail.phpfor media pages - Write CSS for all components (layout, typography, navigation, responsive)
- Add a logo placeholder
- Enable the template and test every page type
- Fix any layout issues
- Document your template structure
What's Next
Your custom template is live. Learn how to configure templates with user CSS, settings, and inheritance for maintainable designs.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro