Grav is an open source flat-file CMS platform, built by the RocketTheme Team. While there are plenty of great CMS platforms available, they are all mostly database-driven, which can be overkill for smaller websites. Instead of a database, Grav uses folders and a basic file structure, it is focused on speed, simplicity, and flexibility.

WHAT WE’LL BE BUILDING
INSTALLING GRAV
- A web server (Apache, Nginx, LiteSpeed, Lightly, IIS, etc.)
- PHP 5.5.9 or higher
PAGE TYPES
STANDARD PAGE
LISTING PAGE
MODULAR PAGE
FILE STRUCTURE
THE CONTENT
THE THEME
- blueprints.yaml – a file which contains information about the theme.
- themename.php – a file which contains any logic your theme needs.
- themename.yaml – a configuration file used by the plugin to set options the theme might use.
- templates/ – a folder containing the Twig templates to render the pages.
- CHANGELOG.md – a file that follows the Grav Changelog Format to show changes.
- LICENSE – a file containing the license to the theme.
- README.md – a file with documentation for the theme.
- screenshot.jpg – a 1009px x 1009px screenshot of the theme.
- thumbnail.jpg – a 300px x 300px screenshot of the theme.
THE TEMPLATES
THE BLUEPRINTS
PART 1: ONE PAGER MODULAR THEME
CONTENT FILE STRUCTURE
├── 01.home
│ ├── _download
│ │ └── download.md
│ ├── _features
│ │ └── features.md
│ ├── _highlights
│ │ └── highlights.md
│ ├── _intro
│ │ └── intro.md
│ ├── _overview
│ │ ├── grav-logo.png
│ │ └── overview.md
│ └── home.md
THEME FILE STRUCTURE
├── blueprints
│ └── modular
│ ├── highlights.yaml
│ └── showcase.yaml
├── css
│ └── main.css
├── fonts
├── imgs
├── js
├── sass
├── templates
│ ├── home.html.twig
│ ├── modular
│ │ ├── download.html.twig
│ │ ├── features.html.twig
│ │ ├── highlights.html.twig
│ │ ├── intro.html.twig
│ │ └── overview.html.twig
│ └── partials
│ └── base.html.twig
├── blueprints.yaml
├── onepager.yaml
├── screenshot.jpg
└── thumbnail.jpg
CONFIG FILES
SITE.YAML
title: 'One Pager'
author:
name: 'Angie Vella'
email: 'email@email.com'
metadata:
generator: 'Grav'
description: 'Simple One Page Theme for Grav'
keywords: 'HTML, CSS, Grav, Theme, One Page'
author: 'Angie Vella'
robots: 'noindex, nofollow'
THEME FILES
BLUEPRINTS.YAML
name: One Pager
version: 1.0.0
description: "A simple one page theme for Grav"
author:
name: Angie Vella
email: email@email.com
url: http://www.website.com
license: MIT
ONEPAGER.YAML
enabled: true
default_lang: en
THEME TEMPLATES
BASE.HTML.TWIG
{% for module in page.collection.modular() %}
<li><a href="#{{ module.header.anchor }}">{{ module.menu }}</a></li>
{% endfor %}
<!DOCTYPE html>
<html lang="{{ theme_config.default_lang }}">
<head>
{% block head %}
<title>{{ site.title }}</title>
<link rel="canonical" href="{{ page.url(true, true) }}">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" type="image/png" href="{{ url('theme://img/favicon.png') }}">
{% block stylesheets %}
{% do assets.addCss('theme://css/main.css') %}
{% do assets.addCss('https://fonts.googleapis.com/css?family=Montserrat:400,700') %}
{% endblock %}
{{ assets.css() }}
{% block javascripts %}
{% do assets.addJs('jquery', '110') %}
{% do assets.addJs('theme://js/singlepagenav.min.js') %}
{% if browser.getBrowser == 'msie' and browser.getVersion >= 8 and browser.getVersion <= 9 %}
{% do assets.add('theme://js/html5shiv.min.js') %}
{% do assets.add('theme://js/respond.min.js') %}
{% endif %}
{% endblock %}
{{ assets.js() }}
{% endblock head %}
</head>
<body>
<header class="main-header">
<div class="wrapper">
<div class="logo">
<a href="{{ base_url}}">OnePager</a>
</div>
<nav class="main-nav">
<ul>
{% for module in page.collection.modular() %}
<li><a href="#{{ module.header.anchor }}">{{ module.menu }}</a></li>
{% endfor %}
</ul>
</nav>
</div>
</header>
<section class="content-wrapper">
{% block content %}{% endblock %}
</section>
<footer class="main-footer">
<p>©<script type="text/javascript">document.write(new Date().getFullYear());</script> OnePager Grav Theme.</p>
</footer>
{% block bottom %}
{{ assets.js('bottom') }}
<script>
$('.navigation-wrapper').singlePageNav({
offset: $('header.menu').outerHeight(),
updateHash: true,
currentClass: 'menu-active'
});
</script>
{% endblock %}
</body>
</html>
HOME.HTML.TWIG
{% extends 'partials/base.html.twig' %}
{% block content %}
{% for module in page.collection() %}
<div id="{{ module.header.anchor }}"></div>
{{ module.content }}
{% endfor %}
{% endblock %}
INTRO.HTML.TWIG
<div class="intro">
<div class="wrapper">
{{ content }}
</div>
</div>
HIGHLIGHTS.HTML.TWIG
<div class="highlights">
<div class="wrapper">
{{ content }}
{% for highlight in page.header.highlights %}
<div class="highlight">
<i class="fa fa-fw fa-{{ highlight.icon }}"></i>
<h4>{{ highlight.header }}</h4>
<p>{{ highlight.text }}</p>
</div>
{% endfor %}
</div>
</div>
OVERVIEW.HTML.TWIG
<div class="overview">
<div class="wrapper">
<div class="text">
{{ content }}
</div>
<div class="image">
{% set image = page.media.images|first %}
{% if image %}
{{ image }}
{% endif %}
</div>
</div>
</div>
FEATURES.HTML.TWIG
<div class="features">
<div class="wrapper">
{{ content }}
{% for feature in page.header.features %}
<div class="feature">
<i class="fa fa-{{ feature.icon }}"></i>
<h5>{{ feature.header }}</h5>
</div>
{% endfor %}
</div>
</div>
DOWNLOAD.HTML.TWIG
<div class="download">
<div class="wrapper">
{{ content }}
{% for button in page.header.buttons %}
<div class="button-wrapper">
<a class="button" href="{{ button.url }}">{{ button.text }}</a>
</div>
{% endfor %}
</div>
</div>
CONTENT FILES
HOME.MD
---
title: Home
content:
items: '@self.modular'
order:
by: default
dir: asc
custom:
- _intro
- _highlights
- _overview
- _features
- _download
---
INTRO.MD
---
title: Home
anchor: intro
---
# OnePager
## A Simple One Page Modular Theme for Grav
HIGHLIGHTS.MD
---
title: Highlights
anchor: highlights
highlights:
- header: 'Crazy Fast'
text: 'Performance is not just an after thought, we baked it in from the start!'
icon: fighter-jet
- header: 'Easy to build'
text: 'Simple text files means Grav is trivial to install, and easy to maintain.'
icon: database
- header: 'Awesome Technology'
text: 'Grav employees best-in-class technologies such as Twig, Markdown & Yaml'
icon: cubes
- header: 'Super Flexible'
text: 'From the ground up, with many plugin hooks, Grav is extremely extensible'
icon: puzzle-piece
---
### Built on top of Greatness
#### Four core tenants keep Grav focused
OVERVIEW.MD
---
title: Overview
anchor: overview
---
### Fast, Extensible, Open Source!
#### Grav is a modern open source flat-file CMS
Grav is a modern open source flat-file CMS. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse suscipit ultrices ligula eget accumsan. Sed egestas augue a risus semper pretium non sit amet odio.
FEATURES.MD
---
title: Features
anchor: features
features:
- header: Markdown Syntax
icon: text-height
- header: Twig Templating
icon: code
- header: Smart Caching
icon: rocket
- header: Flexible Taxonomies
icon: tags
- header: Simple Install
icon: cloud-download
- header: Powerful Plugins
icon: cogs
- header: Intuitive UI
icon: dashboard
- header: File-Based
icon: file-text
- header: Documentation
icon: bookmark
- header: On Github
icon: github
- header: Responsive Design
icon: html5
- header: Awesomazing
icon: heart
---
### Stuffed full of Amazing Features
#### This is a non-inclusive smattering of them
DOWNLOAD.MD
---
title: Download
anchor: download
buttons:
- text: Download
url: https://getgrav.org/downloads
---
### Get Grav
BLUEPRINTS
HIGHLIGHTS.YAML
title: Highlights
'@extends': default
form:
fields:
tabs:
fields:
advanced:
fields:
columns:
fields:
column1:
fields:
name:
default: modular/highlights
'@data-options': '\Grav\Common\Page\Pages::modularTypes'
overrides:
fields:
header.template:
default: modular/highlights
'@data-options': '\Grav\Common\Page\Pages::modularTypes'
highlights:
type: tab
title: Highlights
fields:
header.highlights:
name: highlights
type: list
label: Highlights
fields:
.icon:
type: text
label: Icon
.header:
type: text
label: Header
.text:
type: text
label: Text
FEATURES.YAML
title: Features
'@extends': default
form:
fields:
tabs:
fields:
advanced:
fields:
columns:
fields:
column1:
fields:
name:
default: modular/features
'@data-options': '\Grav\Common\Page\Pages::modularTypes'
overrides:
fields:
header.template:
default: modular/features
'@data-options': '\Grav\Common\Page\Pages::modularTypes'
features:
type: tab
title: Features
fields:
header.features:
name: features
type: list
label: Features
fields:
.icon:
type: text
label: Icon
.header:
type: text
label: Header
PART TWO – MNMM BLOG THEME
CONTENT FILE STRUCTURE
├── 01.home
│ ├── _blog-post
│ │ ├── media.jpg
│ │ └── item.md
│ └── blog.md
THEME FILE STRUCTURE
├── css
│ └── main.css
├── fonts
├── imgs
├── js
├── sass
├── templates
│ ├── blog.html.twig
│ ├── error.html.twig
│ ├── item.html.twig
│ ├── modular
│ └── partials
│ ├── base.html.twig
│ └── blog_item.html.twig
├── blueprints.yaml
├── mnmm.php
├── mnmm.yaml
├── screenshot.jpg
└── thumbnail.jpg
PLUGINS
- Feed – Lets you view a Grav Collection as RSS or Atom news feed.
- JS Comments – Enables you to add comments to your site with Discourse, Disqus, Facebook, Google+, IntenseDebate, and Muut comment systems.
- Pagination – Adds pagination to your site.
- Readingtime – Adds reading time to your pages.
- SimpleSearch – Enables you to search your site’s content.
CONFIG FILES
SITE.YAML
THEME FILES
BLUEPRINTS.YAML
MNMM.YAML
THEME TEMPLATES
BASE.HTML.TWIG
<!DOCTYPE html>
<html lang="{{ theme_config.default_lang }}">
<head>
{% block head %}
<title>{{ site.title }}</title>
<link rel="canonical" href="{{ page.url(true, true) }}">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" type="image/png" href="{{ url('theme://img/favicon.png') }}">
{% block stylesheets %}
{% do assets.addCss('theme://css/main.css') %}
{% do assets.addCss('https://fonts.googleapis.com/css?family=Open+Sans:300,400,600,700') %}
{% endblock %}
{{ assets.css() }}
{% block javascripts %}
{% do assets.addJs('jquery', '110') %}
{% do assets.addJs('theme://js/singlepagenav.min.js') %}
{% if browser.getBrowser == 'msie' and browser.getVersion >= 8 and browser.getVersion <= 9 %}
{% do assets.add('theme://js/html5shiv.min.js') %}
{% do assets.add('theme://js/respond.min.js') %}
{% endif %}
{% endblock %}
{{ assets.js() }}
{% endblock head %}
</head>
<body>
<header class="main-header">
<nav class="main-nav">
<div class="wrapper">
<div class="logo"><a href="{{ base_url}}">MNMM</a></div>
<div class="search">
{% if config.plugins.simplesearch.enabled %}
{% include 'partials/simplesearch_searchbox.html.twig' %}
{% endif %}
</div>
</div>
</nav>
<div class="site-title">
<div class="wrapper">
<h1>{{ site.title }}</h1>
</div>
</div>
</header>
<section class="main-wrapper">
{% block content %}{% endblock %}
</section>
{% block footer %}
<footer class="main-footer">
<div class="wrapper">
<span class="credits">©<script type="text/javascript">document.write(new Date().getFullYear());</script> MNMM Grav Theme.</span>
<span class="icons">
<a class="button" href=""><i class="fa fa-facebook-square"></i></a>
<a class="button" href=""><i class="fa fa-twitter-square"></i></a>
<a class="button" href=""><i class="fa fa-google-plus-square"></i></a>
<a class="button" href=""><i class="fa fa-pinterest-square"></i></a>
<a class="button" href=""><i class="fa fa-linkedin-square"></i></a>
<a class="button" href=""><i class="fa fa-instagram"></i></a>
<a class="button" href=""><i class="fa fa-github-square"></i></a>
{% if config.plugins.feed.enabled %}
<a class="button" href="{{ feed_url }}.atom"><i class="fa fa-rss-square"></i></a>
<!--<a class="button" href="{{ feed_url }}.rss"><i class="fa fa-rss-square"></i> RSS</a>-->
{% endif %}
</span>
</div>
</footer>
{% endblock %}
{% block bottom %}
{{ assets.js('bottom') }}
{% endblock %}
</body>
</html>
BLOG.HTML.TWIG
{% embed 'partials/base.html.twig' %}
{% set collection = page.collection() %}
{% block content %}
<div class="blog-list-wrapper">
<div class="listing">
{% for child in collection %}
{% include 'partials/blog_item.html.twig' with {'blog':page, 'page':child, 'truncate':true} %}
{% endfor %}
<div class="pagination-wrapper">
{% if config.plugins.pagination.enabled and collection.params.pagination %}
{% include 'partials/pagination.html.twig' with {'base_url':page.url, 'pagination':collection.params.pagination} %}
{% endif %}
</div>
</div>
</div>
{% endblock %}
{% endembed %}
ERROR.HTML.TWIG
{% extends 'partials/base.html.twig' %}
{% block content %}
<div id="error">
<div>
<h2>{{ 'ERROR'|t }} {{ page.header.http_response_code }}</h2>
<p>
{{ page.content }}
</p>
</div>
</div>
{% endblock %}
ITEM.HTML.TWIG
{% embed 'partials/base.html.twig' %}
{% block content %}
<div class="blog-item-wrapper">
<div id="blog-item">
{% include 'partials/blog_item.html.twig' with {'blog':page.parent, 'truncate':false} %}
</div>
</div>
{% endblock %}
{% endembed %}
BLOG_ITEM.HTML.TWIG
<div class="blog-list-item">
<div class="blog-list-header">
<span class="blog-list-date">
<time class="date" datetime="{{ page.date|date("c") }}">
<span>{{ page.date|date("d") }}</span>
<em>{{ page.date|date("M") }}</em>
<em>{{ page.date|date("Y") }}</em>
</time>
</span>
{% if page.header.link %}
<h4 class="post-name">
{% if page.header.continue_link is not sameas(false) %}
<a href="{{ page.url }}"><i class="fa fa-angle-double-right u-url"></i></a>
{% endif %}
<a href="{{ page.header.link }}" class="u-url">{{ page.title }}</a>
</h4>
{% else %}
<h4 class="post-name"><a href="{{ page.url }}" class="u-url">{{ page.title }}</a></h4>
{% endif %}
</div>
<div class="list-blog-padding">
{% if page.header.continue_link is sameas(false) %}
<div class="post-content">
{{ page.content }}
</div>
{% if not truncate %}
{% set show_prev_next = true %}
{% endif %}
{% elseif truncate and page.summary != page.content %}
<div class="post-content">
{{ page.summary }}
</div>
<div class="meta">
{% if config.plugins.readingtime.enabled %}
<span class="reading">{{ page.content|readingtime }}</span>
{% endif %}
{% if page.taxonomy.tag %}
<span class="tags">
{% for tag in page.taxonomy.tag %}
<a href="{{ blog.url|rtrim('/') }}/tag{{ config.system.param_sep }}{{ tag }}">{{ tag }}</a>
{% endfor %}
</span>
{% endif %}
</div>
{% elseif truncate %}
<div class="post-content">
{% if page.summary != page.content %}
{{ page.content|truncate(550) }}
{% else %}
{{ page.content }}
{% endif %}
</div>
{% else %}
<div class="post-content">
{{ page.content }}
</div>
<div class="post-meta">
{% if page.taxonomy.tag %}
<span class="post-tags">
{% for tag in page.taxonomy.tag %}
<a href="{{ blog.url|rtrim('/') }}/tag{{ config.system.param_sep }}{{ tag }}">{{ tag }}</a>
{% endfor %}
</span>
{% endif %}
</div>
<div class="post-share">
{% if config.plugins.socialbuttons.enabled %}
{% include 'partials/socialbuttons.html.twig' with {'url':page.url} %}
{% endif %}
</div>
<div class="post-comments">
{% if config.plugins.jscomments.enabled %}
{{ jscomments() }}
{% endif %}
</div>
{% set show_prev_next = true %}
{% endif %}
</div>
</div>
{% if show_prev_next %}
<div class="post-pagination">
<div class="wrapper">
{% if not page.isFirst %}
<span class="lft"><a class="button" href="{{ page.nextSibling.url }}"><i class="fa fa-chevron-left"></i> Next</a></span>
{% endif %}
{% if not page.isLast %}
<span class="rgt"><a class="button" href="{{ page.prevSibling.url }}">Prev <i class="fa fa-chevron-right"></i></a></span>
{% endif %}
</div>
</div>
{% endif %}
CONTENT FILES
BLOG.MD
---
title: 'MNMM Grav Theme'
content:
items: '@self.children'
order:
by: date
dir: desc
limit: 5
pagination: true
feed:
description: 'Sample Blog Description'
limit: 10
pagination: true
---
# MNMM Grav Theme
ITEM.MD
---
title: The Urban Jungle
date: 17:34 07/04/2014
taxonomy:
category: blog
tag: [travel, photography, city]
---
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec ultricies tristique nulla et mattis. Phasellus id massa eget nisl congue blandit sit amet id ligula. Praesent et nulla eu augue tempus sagittis. Mauris faucibus nibh et nibh cursus in vestibulum sapien egestas. Curabitur ut lectus tortor. Sed ipsum eros, egestas ut eleifend non, elementum vitae eros. Mauris felis diam, pellentesque vel lacinia ac, dictum a nunc. Mauris mattis nunc sed mi sagittis et facilisis tortor volutpat. Etiam tincidunt urna mattis erat placerat placerat ac eu tellus.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec ultricies tristique nulla et mattis. Phasellus id massa eget nisl congue blandit sit amet id ligula. Praesent et nulla eu augue tempus sagittis. Mauris faucibus nibh et nibh cursus in vestibulum sapien egestas. Curabitur ut lectus tortor. Sed ipsum eros, egestas ut eleifend non, elementum vitae eros. Mauris felis diam, pellentesque vel lacinia ac, dictum a nunc. Mauris mattis nunc sed mi sagittis et facilisis tortor volutpat. Etiam tincidunt urna mattis erat placerat placerat ac eu tellus. Ut nec velit id nisl tincidunt vehicula id a metus. Pellentesque erat neque, faucibus id ultricies vel, mattis in ante. Donec lobortis, mauris id congue scelerisque, diam nisl accumsan orci, condimentum porta est magna vel arcu. Curabitur varius ante dui. Vivamus sit amet ante ac diam ullamcorper sodales sed a odio. Curabitur ut lectus tortor. Sed ipsum eros, egestas ut eleifend non, elementum vitae eros. Mauris felis diam, pellentesque vel lacinia ac, dictum a nunc.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec ultricies tristique nulla et mattis. Phasellus id massa eget nisl congue blandit sit amet id ligula. Praesent et nulla eu augue tempus sagittis. Mauris faucibus nibh et nibh cursus in vestibulum sapien egestas. Curabitur ut lectus tortor. Sed ipsum eros, egestas ut eleifend non, elementum vitae eros. Mauris felis diam, pellentesque vel lacinia ac, dictum a nunc. Mauris mattis nunc sed mi sagittis et facilisis tortor volutpat. Etiam tincidunt urna mattis erat placerat placerat ac eu tellus. Ut nec velit id nisl tincidunt vehicula id a metus. Pellentesque erat neque, faucibus id ultricies vel, mattis in ante. Donec lobortis, mauris id congue scelerisque, diam nisl accumsan orci, condimentum porta est magna vel arcu. Curabitur varius ante dui. Vivamus sit amet ante ac diam ullamcorper sodales sed a odio.
0 Reviews:
Post a Comment
If you have any doubts, Let me know, Please!