DEV Community

Cover image for Building a Simple Grav CMS Theme with Twig, PHP, and CSS
Reuben Walker, Jr.
Reuben Walker, Jr.

Posted on • Originally published at symfonystation.mobileatom.net

Building a Simple Grav CMS Theme with Twig, PHP, and CSS

This article first appeared on Symfony Station.

Illustration of astronauts floating in space

Introduction

If you're reading this you know building content-oriented websites today is an overcomplicated clusterfuck.

But there is a content management system that makes it easier and simpler. And this is especially true for frontend developers. It's Grav CMS.

I'm going to customize a theme for grav.mobileatom.net which is my main business site. Guess what? It won't involve any AI.

And writing this article is going to be my way to learn how to do it plus help the community. You don't see many articles about Grav.

We're going to cover:

(1) Organization / file structure
(2) Twig templates
(3) CSS
(4) Twig functionality
(5) Customization

If you don't know, GravCMS is one of the many CMSs based on Symfony.

The technical details of this article are mostly paraphrased from the Grav documentation. As I just said, I'm learning this myself.

Grav says:

"The core of Grav is built around the concept of folders and markdown files for content. These folders and files are automatically compiled into HTML and cached for performance.

Its pages are accessible via URLs that directly relate to the folder structure that underpins the whole CMS. By rendering the pages with Twig Templates, you have complete control over how your site looks, with virtually no limitations."

Alright, let's take a look at themes.

Grav themes

Themes in Grav are built with Twig templates and you can learn much more about Twig in my article, Twig: The Ultimate Guide to the Premier PHP Templating Language. Plus, we will go into some details here.

As I wrote there, Twig is a PHP templating language that outputs variables into the HTML of views in MVC (models, views, controllers) programming. So, it contributes to the structure of your website's frontend.

It was created by Fabien Ponticier who also created Symfony, thus it's no surprise it's used in Grav.

He noted that "a template language is something that helps you to write templates that respect this (MVC) separation of concerns. A template language should find a good balance between giving enough features to ease implementing the presentation logic and restricting the advanced features to avoid having the business logic cripple your templates."

What exactly are PHP templates? As noted above, they are used to separate the view of your PHP application from its models and objects.

Twig's key features are that it's:

  • Fast: Twig compiles templates down to plain optimized PHP code. The overhead compared to regular PHP code was reduced to the very minimum.
  • Secure: Twig has a sandbox mode to evaluate untrusted template code. This mode allows Twig to be used as a template language for applications where users modify the template design.
  • Flexible: Twig is powered by a flexible lexer and parser. This flexibility allows the developer to define custom tags and filters (more about those later) and create their unique DSL.

A few final quick notes:

  • Twig Template names end with .html.twig.
  • You configure them with YAML.
  • And they work well with vanilla CSS.

Each page you create in Grav via the admin interface references a Twig template file. A best practice is to match template file names to page names as much as possible. Or at least your content files' folder structure.

For example, blog.md would render with the Twig template blog.html.twig

Grav Theme File Structure

(1) Organization / file structure

Ok, let's look at how a Grav theme is structured.

Each theme has a definition file named blueprints.yaml. It can also provide form definitions for the admin panel.

To use theme definition options, provide default settings in a your_theme_name.yaml file.

Include a 303x300 jpg named thumbnail.jpg in the theme root.

(2) Twig Templates and more

Your Grav page's Twig templates should be in a templates/ folder with subfolders for:

  • forms/
  • modular/
  • partials/

A best practice is to develop your theme in conjecture with your content. This strategy is one of the reasons why I'm so invested with Grav. Page files = Twig templates.

Again, default.md, blog.md, error.md, item.md, modular.md would equate to default.html.twig, blog.html.twig, etc.

Your theme needs a css/ folder for your CSS.

Add images/, fonts/, and js/ folders to your root as well for storing custom assets.

A blueprints/ folder will house the file with your form definitions as mentioned earlier.

Plugins are brought into Grav themes via hooks.

So, your_theme_name.php will house your non-Twig logic.

Just FYI, if you want to build a commercial theme to sell to others you will also need these files:

  • CHANGELOG.md
  • LICENSE.md
  • README.md
  • screenshot.jpg
  • thumbnail.jpg

base.html.twig file

A Base Template

You could get my with just a default Twig template with Grav.

But, it's better to use the Twig Extends tag to define a base layout via blocks in a base template. This file is stored in the partials/ subfolder as base.html.twig. See the image above.

In your default and other specialized templates use the extends tag to pull in your base layout from base.html.twig.

So, for your default.html.twig file using Twig syntax you would code:

{% extends 'partials/base.html.twig'%}

{%block content %}
  {{page.content | raw}}
{%endblock%}
Enter fullscreen mode Exit fullscreen mode

The first set of code extends the base template which contains your base layout.

The second overides the content from the base template with your new template's code.

CSS file

(3) Theme CSS

Next let's look at the CSS for your Grav theme. There are several ways to implement it including SCSS. But, in the vein of keeping it simple I will focus on vanilla CSS. It's short. Add a custom.css file and go to town.
Twig logo

(4) Twig Functionality

Let's also take a quick look at how Twig works.

Twig tags like Extend control the logic of your templates. They tell Twig what to do. IMHO, Block is the most important tag.

Others include:

  • cache
  • markdown
  • script
  • style
  • switch
  • etc

Twig filters are useful for formatting and manipulating text and variables.

They include:

  • date
  • escape
  • join
  • lower
  • slice
  • etc

Functions can generate content and implement functionality (obviously). They can also do some of the same things filters can do.

So, for your templates use the Twig tags, filters, and functions required for your unique needs.

Grav's Twig tags

In addition to your the tags you choose, Grav includes custom Twig tags to extend its capabilities.

They include:

  • markdown
  • script (you can pull in JavaScript for example)
  • style
  • link
  • switch
  • deferred (loading of assets)
  • throw (exceptions)
  • try/catch
  • render (flex objects)
  • cache

Theme YAML file

Theme Configuration

With Grav you can access theme configuration and blueprints information from your Twig and PHP files. You can do this via theme objects or you can use a Grav plugin with PHP syntax.

As a best practice, don't change your theme's default your_theme_name.yaml file (see image above). Override it in a user/config/themes folder.

As a final note, Twig also has custom objects and variables which we won't discuss here. Remember, I'm keeping it simple.

Assets plugin download page

Asset Manager

Grav's Asset Manager provides a flexible way to manage CSS and JavaScript files. It includes an Asset Pipeline to minify, compress, and inline assets.

It's available and can be accessed in plugin event hooks or directly in themes via Twig calls. It has its own configuration file in user/config/system.yaml.

You can get enterprise-level granular with Asset Manager so we won't cover in any greater detail here.

In the vein of keeping it simple, I recommend using the Assets plugin (see image above). Download it from the Grav admin. Then use it to update or add assets as needed.

(5) Customization

So, we're covered the way to build a quick and simple Grav Theme. Set up your structure, build your Twig templates, and add CSS and JavaScript as needed.

And you have seen there are a variety of ways for making a Grav theme meet your simple or complex needs, but Grav provides features and functionality to make it even easier. And it's the way I'm going to customize my site's theme.

Theme Inheritance

That easier way is to use theme inheritance. I like this because it's similar to what I have done with WordPress and Drupal themes.

It's also Grav's preferred way to customize a theme.

You define a base theme that your are inheriting from. For example the default theme Quark or one you've bought. Then you add or edit what you want customized and let the base theme handle the rest.

This strategy also let's you update the base theme without losing the customizations of your inheritance theme.

There are several ways to create an inheritance theme. But again in the interest of simplicity, let's look at the manual process.

Create a new folder -> user/themes/your_theme_name to hold the custom theme.

Then copy the YAML file from the theme you will be inheriting from into the new folder. Name it your_theme_name.yaml and switch the new theme name wherever you see Quark.

Next, copy the users/themes/quark/blueprint.yaml file into your user/themes/your_theme_name folder.

Now, change the default theme in the user/config/system.yaml file.

pages:
theme : your_theme_name

Finally, to add advanced event-driven functionality, create a user/themes/your_theme_name/your_theme_name.php file.

<?php
namespace Grav\ Theme:

class your_theme_name extends quark

  {
    //new theme's code
  }

?>
Enter fullscreen mode Exit fullscreen mode

You have now set up Grav's streams so that it looks in your_theme_name first, then tries Quark.

Now, provide the CSS, JS, and Twig template modifications you require.

You're done. Fairly simply.

Conclusion

Wow. Thanks for reading the entire article.

You now know more about Grav themes':

(1) Organization / file structure
(2) Twig templates
(3) CSS
(4) Twig functionality
(5) Customization

Consider using Grav for its simplicity, especially when customizing themes. What's not to love about PHP, Twig, vanilla CSS and JS. You even create your content in markdown.

Keep coding Symfonistas and Gravinauts!

Resources

https://learn.getgrav.org/17/themes

https://twig.symfony.com/

https://twig.symfony.com/doc/3.x/

https://www.drupal.org/docs/contributed-modules/twig-tweak-2x/cheat-sheet

Top comments (1)

Collapse
 
xwero profile image
david duymelinck • Edited

Very engaging post!

I'm sad to say i only know Grav CMS for its great local multiple php setup tutorial. Of course now we are in the era of containerisation, so it is a thing of the past for developers.

Too bad it is a only flat file source CMS, as far as I found in the documentation. It would be on par with Statamic, if it provided a way to store content in a database.

But your post made me wanting to explore the solution, to see if it could fit someone's needs