Skip to content
Grav CMS Guide — Flat-File CMS for Developers

Grav CMS Guide — Flat-File CMS for Developers

DodaTech Updated Jun 6, 2026 7 min read

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;
  
Prerequisites: Basic understanding of HTML, CSS, and Markdown. Familiarity with Twig or PHP helps for theme customization.

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 page

Frontmatter 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 files

Twig 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: No

Taxonomy

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: grav

CLI 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 check

Key Features

FeatureDescription
Flat-fileNo database required — everything is files
TwigPowerful template engine with inheritance
BlueprintsYAML config files for page types and forms
TaxonomyTags, categories, and custom classifications
CachingBuilt-in file, Redis, and Memcached backends
Admin pluginOptional web-based admin interface
GPMGrav Package Manager for plugins and themes
MarkdownContent 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

  1. 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.

  2. How do pages work in Grav?
    Answer: Each page is a folder in user/pages/ containing a Markdown file (.md). The folder name determines the URL slug; an optional number prefix controls ordering.

  3. 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.

  4. 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

Does Grav need a database?
: No. Grav is flat-file. All content is stored as Markdown files. This makes deployment, backups, and version control simpler than database-driven CMS platforms.
Can I use Grav for e-commerce?
: Yes, via the Shopping Cart plugin. However, Grav is not purpose-built for e-commerce like Magento. For simple stores it works well; for complex stores, consider Magento or WooCommerce.
How does Grav handle performance?
: Very well for content sites. Grav compiles Twig templates to PHP and caches the output. Without database queries, page loads are faster than most CMS platforms.
Can I use an admin panel with Grav?
: Yes. The Admin plugin provides a web-based interface for managing pages, users, and configuration. Install it via GPM: bin/gpm install admin.
Is Grav good for multi-author blogs?
: Yes. Grav supports multiple users with role-based permissions via the Admin plugin. It works well for small to medium-sized editorial teams.

Try It Yourself

  1. Download and install Grav (bin/grav new-project)
  2. Create a home page and an about page in user/pages/
  3. Install the Quark theme via GPM
  4. Create a custom Twig template that shows a list of blog posts
  5. Enable caching and test performance

What’s Next

TopicDescription
TwigAdvanced templating with inheritance and macros
MarkdownWriting content with Markdown syntax
PHPCreating custom Grav plugins
CSSStyling Grav themes
HTMLUnderstanding 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