How to Build a Product Docs Site with Djebel
Every product needs documentation. Getting-started guides, integration tutorials, API references, and release notes all need a clear home.
Many teams reach for a hosted documentation platform or build another CMS. But if your team already works in Git, you can keep the whole documentation site as Markdown files in the same kind of workflow you use for code.
Djebel gives you that setup without a database or admin panel. The theme owns the design, plugins provide the functionality, and your documentation stays in content files and site configuration.
Why Use a Standalone Install?
Instead of adding documentation to an existing marketing site, a dedicated Djebel install gives you:
- A separate domain such as
docs.yourproduct.com - Independent deployments for documentation changes
- A focused navigation and URL structure
- Git history, branches, pull requests, and reviews
- Markdown files your developers can edit without learning another CMS
- A lightweight PHP application with no content database
The important part is the separation of responsibilities:
- The theme controls layout and presentation
- Plugins render Markdown, collections, and SEO metadata
- Page text and documentation live in files
- Site-specific labels, navigation, and defaults live in
app.ini
Step 1: Create the Site Structure
A public-directory installation starts with this structure:
your-docs-site/
.ht_djebel/
app/
plugins/
conf/
app.ini
public/
index.php
.htaccess
dj-content/
data/
plugins/
themes/
Point the web server's document root to public/. The .ht_djebel/ directory remains outside the document root for configuration and non-public plugin code.
Your public/index.php loads Djebel through the PHAR or framework checkout used by your deployment.
Step 2: Install the Required Plugins
The documentation site needs three plugins:
djebel-static-contentmaps URLs to content files and renders collectionsdjebel-markdownparses frontmatter and converts Markdown to HTMLdjebel-seowrites the page title and meta fields
Keep the renderer in the public plugin directory and the server-side Markdown and SEO plugins outside the document root:
your-docs-site/
.ht_djebel/
app/
plugins/
djebel-markdown/
djebel-seo/
public/
dj-content/
plugins/
djebel-static-content/
Each distributable plugin lives in its own repository. From the site root, add the current repositories as submodules:
git submodule add https://github.com/djebel-app-plugins/djebel-static-content.git public/dj-content/plugins/djebel-static-content
git submodule add https://github.com/djebel-app-plugins/djebel-markdown.git .ht_djebel/app/plugins/djebel-markdown
git submodule add https://github.com/djebel-app-plugins/djebel-seo.git .ht_djebel/app/plugins/djebel-seo
The site repository records the exact commit used by each plugin, so deployments remain reproducible.
Step 3: Configure app.ini
Edit .ht_djebel/conf/app.ini:
[site]
site_title = Your Product Docs
description = Official documentation for Your Product
timezone = America/New_York
strip_url_segment = public
[theme]
theme_id = djebel-docs
[meta]
default.title = Your Product Documentation
default.description = Official documentation, API reference, and product guides
default.keywords = your product, documentation, api, reference
home.title = Your Product Documentation
home.description = Guides, API references, and release notes for Your Product
docs.title = Documentation | Your Product
docs.description = Guides and tutorials for Your Product
api.title = API Reference | Your Product
api.description = API endpoints, authentication, requests, and responses
changelog.title = Changelog | Your Product
changelog.description = Product releases and notable changes
[app]
env = production
[page_nav]
home.title = Home
home.url = /
docs.title = Docs
docs.url = /docs
api.title = API Reference
api.url = /api
changelog.title = Changelog
changelog.url = /changelog
[plugins]
; Markdown site pages live in the static-content pages directory.
djebel-static-content.site_content_dir = pages
; Collection URLs render through design-only theme templates.
djebel-static-content.url_contains[/docs] = "template_file=docs.php"
djebel-static-content.url_contains[/api] = "template_file=api.php"
djebel-static-content.url_contains[/changelog] = "template_file=changelog.php"
; Docs and API pages use explicit frontmatter slugs for clean URLs.
djebel-static-content.docs.use_content_slugs = 1
djebel-static-content.api.use_content_slugs = 1
; Numbered filenames define documentation order.
djebel-static-content.docs.sort_by = file
djebel-static-content.api.sort_by = file
; Release notes remain newest-first.
djebel-static-content.changelog.sort_by = publish_date
The url_contains settings choose a theme template for each collection. The shortcode inside that template selects the matching content directory.
Slug mode works well for long-lived documentation URLs. Give every document an explicit slug so filename prefixes used for organization never leak into the URL.
Step 4: Use a Design-Only Theme
Themes should contain design and layout, not page copy. A reusable documentation theme follows the current naming convention:
public/dj-content/themes/djebel-docs/
index.php
css/
style.css
pages/
docs.php
api.php
changelog.php
If the theme will be reused, keep it in its own repository and add it to the site as a submodule. A genuinely site-only theme uses the djebel-site-docs name instead.
The theme's index.php provides the outer layout:
<?php
/*
theme_name: Docs
theme_uri: https://djebel.com/themes/djebel-docs
description: Clean, readable documentation layout
version: 1.0.0
tags: documentation, clean, full-width
stable_version: 1.0.0
min_php_ver: 7.4
min_dj_app_ver: 1.0.0
tested_with_dj_app_ver: 1.0.0
author_name: Your Team
company_name: Your Company
author_uri: https://example.com
text_domain: djebel-theme-docs
*/
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://djebel.com/dj-content/themes/djebel/css/style.statopt_ver.1775672091.css" />
</head>
<body class="dj-app-default-body djebel-theme-docs">
<div class="djebel-theme-docs-site-wrapper">
<header class="djebel-theme-docs-site-header">
<a href="https://djebel.com/en/" class="djebel-theme-docs-site-name">Djebel</a>
<nav class="djebel-theme-docs-navigation dj-app-menu-container">
[djebel_page_nav]
</nav>
</header>
<main class="djebel-theme-docs-content dj-app-content">
<div class="dj-app-page-content">
[djebel_page_content]
</div>
</main>
<footer class="djebel-theme-docs-footer dj-app-footer">
[djebel_page_footer]
</footer>
</div>
</body>
</html>
Use djebel-theme-docs-* for theme-owned CSS classes. The dj-app-* classes belong to Djebel core and should only be used as integration points, not redefined by the theme.
Step 5: Keep Collection Templates Small
Collection templates connect the theme layout to plugin output. They should contain markup and literal plugin shortcodes, not product copy.
pages/docs.php:
<div class="djebel-theme-docs-collection">
[djebel_static_content content_id="docs" results_per_page="50" template_file="docs.php"]
</div>
pages/api.php:
<div class="djebel-theme-docs-collection">
[djebel_static_content content_id="api" results_per_page="100" template_file="api.php"]
</div>
pages/changelog.php:
<div class="djebel-theme-docs-collection">
[djebel_static_content content_id="changelog" results_per_page="20" template_file="changelog.php"]
</div>
The content_id maps directly to a directory under data/app/plugins/djebel-static-content/.
Step 6: Put Page Content in Markdown Files
The homepage belongs in the static-content pages/ directory, not in the theme:
public/dj-content/data/app/plugins/djebel-static-content/pages/home.md
---
title: Your Product Documentation
summary: Everything you need to integrate and use Your Product.
status: published
---
# Your Product Documentation
Everything you need to integrate and use Your Product.
## Getting Started
- [Read the guides](/en/docs)
- [Browse the API reference](/en/api)
- [See what changed](/en/changelog)
This keeps product wording in a content file while the same theme remains reusable by another site.
Step 7: Create the Documentation Collections
Set up one directory per collection:
public/dj-content/data/app/plugins/djebel-static-content/
pages/
home.md
docs/
getting-started/
01-installation.md
02-quick-start.md
03-configuration.md
guides/
01-deployment.md
02-webhooks.md
03-integrations.md
api/
01-authentication.md
02-endpoints.md
03-error-handling.md
04-rate-limits.md
changelog/
2026-03-29-v1-0-0.md
2026-02-15-v0-9-0.md
These are separate collections with their own URL prefixes, ordering rules, and theme templates. The same static-content plugin renders all of them.
Step 8: Write Documentation with Complete Metadata
Every document starts with frontmatter. For docs using slug mode, set an explicit slug. Set meta_description when you want a unique search description:
---
title: Authentication
slug: authentication
summary: Learn how API keys and tokens authenticate requests.
meta_title: API Authentication | Your Product
meta_description: Authenticate Your Product API requests securely with API keys and bearer tokens.
author: Your Team
creation_date: 2026-03-29 10:00:00
category: API Reference
tags: authentication, api-keys, tokens, security
status: published
---
The fields have different jobs:
summaryis the description used in static-content listingsmeta_descriptionis the description used by the SEO plugincategoryandtagsare stored metadata and can be displayed by the renderer
The static-content plugin does not group or filter content by category or tag on its own. Add a theme or plugin extension if you need category archives, tag filters, or related-document discovery.
Now add the Markdown body:
# Authentication
All API requests require authentication through an API key.
---
## Getting Your API Key
1. Log in to your dashboard
2. Open Settings > API Keys
3. Select Generate New Key
4. Copy the key and store it securely
---
## Using the API Key
Include the key in the request header:
Authorization: Bearer your-api-key-here
---
## Example Request
curl -H "Authorization: Bearer sk_live_abc123" \
https://api.yourproduct.com/v1/users
The Markdown plugin extracts the first H1 and the static-content single-post renderer outputs the page title once, so the source remains readable without duplicating the rendered heading.
Step 9: Document Djebel API Responses Accurately
If the product API is built with Djebel, document its standard result structure: {status, msg, code, data}. Put endpoint payloads and pagination inside data.
{
"status": true,
"msg": "",
"code": "",
"data": {
"items": [
{
"id": 42,
"name": "John Doe",
"email": "john@example.com"
}
],
"pagination": {
"page": 1,
"per_page": 20,
"total": 156
}
}
}
An error uses the same envelope:
{
"status": false,
"msg": "Invalid API key",
"code": "app.auth.invalid",
"data": []
}
If you are documenting an external API, show its real response instead. Do not reshape another service just to make it look like Djebel.
Step 10: Understand the SEO Fallbacks
The static-content and SEO plugins work together, but summary and meta_description are separate fields.
For a single document:
meta_titlefrom frontmatter overrides the document title for the browser title- If
meta_titleis empty, static-content falls back totitle meta_descriptionfrom frontmatter overrides page and default descriptions- If it is empty, the SEO plugin checks page-specific values such as
meta.docs.description - If those are empty, it uses
meta.default.description
Add meta_description to important documents when each search result should have a unique description. A summary alone only changes the collection listing.
Step 11: Deploy Through Git
Your documentation content, site configuration, and submodule pointers all live in Git. A normal authoring workflow looks like this:
git checkout -b docs/add-webhook-guide
# Write or update Markdown files.
git add public/dj-content/data/app/plugins/djebel-static-content/docs/
git commit -m "Add webhook integration guide"
git push origin docs/add-webhook-guide
On the production server, update both the site repository and its pinned submodules:
git pull
git submodule update --init --recursive
A plain git pull updates submodule pointers but does not check out those commits inside the submodules. The second command completes the deployment.
Static-content collection scans may be cached. Choose an explicit cache policy for your site: clear the relevant cache during deployment, use a short collection TTL, or disable caching for collections that must reflect every file change immediately. The ?dj_cache=0 query parameter is useful for bypassing cache while verifying a request, but it is not a deployment-wide cache purge.
There is still no content build step or database migration. Once Git and the cache policy are handled, Djebel reads the Markdown files directly.
Step 12: Organize the Site as It Grows
Use numbered filenames when the sequence matters:
01-installation.md
02-quick-start.md
03-configuration.md
Filename prefixes control the collection order only because app.ini explicitly selects file sorting:
[plugins]
djebel-static-content.docs.sort_by = file
The explicit frontmatter slug keeps the number out of the public URL. If you need to insert a document between two existing files, use wider prefixes such as 010-, 020-, and 030- from the start.
Use status: draft while a document is in progress. Drafts remain hidden from listings and are not served as published content.
Complete Directory Layout
The finished site looks like this:
your-docs-site/
.ht_djebel/
app/
plugins/
djebel-markdown/
djebel-seo/
conf/
app.ini
public/
index.php
.htaccess
dj-content/
themes/
djebel-docs/
index.php
css/
style.css
pages/
docs.php
api.php
changelog.php
plugins/
djebel-static-content/
data/
app/
plugins/
djebel-static-content/
pages/
home.md
docs/
getting-started/
01-installation.md
02-quick-start.md
guides/
01-deployment.md
02-webhooks.md
api/
01-authentication.md
02-endpoints.md
03-error-handling.md
changelog/
2026-03-29-v1-0-0.md
2026-02-15-v0-9-0.md
.git/
.gitmodules
The theme provides a reusable documentation layout. The plugins provide Markdown, collections, and SEO. The content stays in files, and the site configuration connects everything.
Your Next Step
Start with one collection and three documents. Create the homepage, add an installation guide, a quick-start guide, and one API page, then verify their URLs and metadata before expanding the structure.
Once that small version works, add the changelog, category or tag extensions, and a deployment cache step that matches how often your documentation changes.
No database. No admin panel. No generated site to rebuild. Just a focused Djebel site, Markdown content, and the Git workflow your team already uses.