Grav CMS Guide — Flat-File CMS for Developers
Grav is a flat-file content management system — it uses Markdown text files for content instead of a database. If WordPress is like a house with a fully automated basement (database, PHP, server), Grav is like a well-organized filing cabinet — every page is a folder with a Markdown file inside. No database setup, no complex queries, just files.
What You’ll Learn
- Grav’s flat-file architecture and folder-based page structure
- Writing content in Markdown with YAML frontmatter
- Twig templating for themes and layouts
- Taxonomy (tags, categories) and blueprints
- Caching, CLI commands, and the Admin plugin
Why Flat-File CMS Matters
Most CMS platforms (WordPress, Drupal, Joomla) store content in a database. This is powerful but adds complexity — backups require SQL dumps, version control is difficult, and performance requires database caching.
Grav flips this model: content is files on disk. You can:
- Put your entire site in Git (version control built in)
- Deploy with
git pull— no database migration - Edit content in any text editor
- Serve pages without database queries (faster)
DodaTech’s own documentation could run on Grav — the flat-file model is perfect for tutorial sites where content is created by developers. Even Durga Antivirus Pro uses file-based documentation for some of its technical specs.
flowchart LR
A["CMS Overview"] --> B["Grav CMS<br/><strong>You are here</strong>"]:::current
B --> C["Choose Your CMS"]
classDef current fill:#38bdf8,color:#0f172a,stroke-width:2px;
Page Structure
In Grav, every page is a folder inside user/pages/. The folder name includes a number prefix for ordering:
user/pages/
├── 01.home/
│ └── default.md # / → Home page
├── 02.blog/
│ ├── blog.md # /blog → Blog listing
│ └── 01.my-post/
│ └── item.md # /blog/my-post → Blog article
└── 03.about/
└── default.md # /about → About pageFrontmatter and Content
Each Markdown file starts with YAML frontmatter between --- delimiters:
---
title: Home Page
menu: Home
published: true
---
# Welcome to Grav
This is a **Markdown** page. Grav renders this into HTML.
- No database queries
- No admin panel required
- Just filesTwig Templating
Grav uses Twig (the same templating engine as Symfony and Drupal) for themes. Templates live in user/themes/:
{% extends 'partials/base.html.twig' %}
{% block content %}
<div class="page-content">
{{ page.content|raw }}
</div>
{% for child in page.children %}
<article>
<h2><a href="{{ child.url }}">{{ child.title }}</a></h2>
{{ child.summary(200)|raw }}
<a href="{{ child.url }}">Read more →</a>
</article>
{% endfor %}
{% endblock %}Template Inheritance
Templates use block-based inheritance:
{# partials/base.html.twig #}
<!DOCTYPE html>
<html>
<head>
<title>{% block title %}{{ site.title }}{% endblock %}</title>
</head>
<body>
{% block header %}{% include 'partials/header.html.twig' %}{% endblock %}
<main>
{% block content %}{% endblock %}
</main>
{% block footer %}{% include 'partials/footer.html.twig' %}{% endblock %}
</body>
</html>Blueprints
Blueprints are YAML files that define the form fields for page editing. They work with the Admin plugin to create custom content types:
# user/blueprints/pages/blog_post.yaml
title: Blog Post
fields:
header.title:
type: text
label: Title
validate:
required: true
header.taxonomy.category:
type: select
label: Category
classes: fancy
options:
technology: Technology
design: Design
business: Business
header.published:
type: toggle
label: Published
highlight: 1
default: 1
options:
1: Yes
0: NoTaxonomy
Grav uses taxonomy for content classification (tags, categories, etc.):
---
title: My Blog Post
taxonomy:
tag:
- php
- cms
- grav
category: technology
---Display taxonomy-filtered content in templates:
{% for page in taxonomy.findTaxonomy({'tag': 'php'}) %}
<li><a href="{{ page.url }}">{{ page.title }}</a></li>
{% endfor %}Caching
Grav has built-in caching with multiple backends:
- File cache (default) — Stores compiled Twig and rendered pages
- Redis / Memcached — For high-traffic sites
- Auto-cache — Automatically clears when files change (development)
Configure in user/config/system.yaml:
cache:
enabled: true
driver: file
prefix: gravCLI Commands
# Installation and maintenance
bin/grav install # Install dependencies
bin/grav new-project # Create new Grav project
bin/gpm selfupgrade # Upgrade Grav CLI
# Plugin/theme management (via GPM)
bin/gpm install admin # Install Admin plugin
bin/gpm install quark # Install Quark theme
bin/gpm update # Update all packages
# Development
bin/grav cache # Clear cache
bin/grav security # Security checkKey Features
| Feature | Description |
|---|---|
| Flat-file | No database required — everything is files |
| Twig | Powerful template engine with inheritance |
| Blueprints | YAML config files for page types and forms |
| Taxonomy | Tags, categories, and custom classifications |
| Caching | Built-in file, Redis, and Memcached backends |
| Admin plugin | Optional web-based admin interface |
| GPM | Grav Package Manager for plugins and themes |
| Markdown | Content written in Markdown with YAML frontmatter |
Common Mistakes
1. Using Grav for Dynamic Content
Grav excels at content sites (blogs, docs, marketing pages). Don’t use it for user-generated content (forums, social networks, e-commerce) — a database-driven CMS is better for those.
2. Ignoring Folder Number Prefixes
The number prefix in folder names (e.g., 01.home) determines page ordering in menus. Omit it if you don’t need ordering; use it when positioning pages.
3. Not Enabling Caching in Production
Without caching, Grav processes every page request through Twig compilation. Enable caching in system.yaml for production.
4. Editing Core Theme Files
Always create a custom theme or use theme inheritance. Changes to the default theme (Quark) are lost on update.
Practice Questions
What makes Grav different from WordPress or Drupal?
Answer: Grav is flat-file — it uses Markdown files instead of a database. No SQL setup, no database migrations, and the entire site can be version-controlled with Git.How do pages work in Grav?
Answer: Each page is a folder inuser/pages/containing a Markdown file (.md). The folder name determines the URL slug; an optional number prefix controls ordering.What is a blueprint in Grav?
Answer: A blueprint is a YAML file that defines the form fields for editing a page in the Admin plugin. It works like a content type definition in traditional CMS platforms.Challenge: Create a Grav site with a home page, blog page, and 2 blog posts. Add a Twig template that lists blog posts on the blog page. Use taxonomy tags and create a page that filters posts by tag.
FAQ
Try It Yourself
- Download and install Grav (
bin/grav new-project) - Create a home page and an about page in
user/pages/ - Install the Quark theme via GPM
- Create a custom Twig template that shows a list of blog posts
- Enable caching and test performance
What’s Next
| Topic | Description |
|---|---|
| Twig | Advanced templating with inheritance and macros |
| Markdown | Writing content with Markdown syntax |
| PHP | Creating custom Grav plugins |
| CSS | Styling Grav themes |
| HTML | Understanding Grav’s output structure |
What’s Next
Congratulations on completing this Grav tutorial! Here’s where to go from here:
- Practice daily — Consistency is more important than long study sessions
- Build a project — Apply what you learned by building something real
- Explore related topics — Check out other tutorials in the same category
- Join the community — Discuss with other learners and share your progress
Remember: every expert was once a beginner. Keep coding!
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro