So a few months ago I purchased a Synology NAS device. Primarily for personal projects and as a means to store and be a medium to backup my development projects. Having a more robust local development environment at my house I wanted to setup a kind of intranet for my house. At my previous job they had a simple intranet page that listed current projects, a note taking application and tools to create or backup websites. This is similar to a Start Page in Google Chrome. In fact, many weeks ago I saw great examples of startpages on Reddit’s /r/startpages. So — all these factors actually made me want to create a simple 1 page website with links and embedded tools within it. After an initial simple attempt at this I decided to take a stab at developing this in GRAV — a flat-file CMS.
Initial Work
So after finding a startpage/intranet design that appealed to me I kinda yanked it’s markup and filled my own sites. I ended up with something that looks like this and additionally uses a bit of PHP.
On this startpage the whole content is literally 1 HTML page with some PHP enabled for processing 1 HTML form. I use the HTML form to perform a Wake On Lan request to my newly purchased NAS. For the purposes of this blog post I will not be going further into the PHP usage or FontAwesome usage I simply want to a show a simple 1 page PHP page I want to move to GRAV.
GRAV Basic Information
Grav has pretty GREAT documentation at learn.getgrav.org. All you need to understand the basic structure of a GRAV site can be found in the online docs.
If you want to install GRAV in the /grav directory of your Arvixe website simply follow these directions within the Hosting directions of the getgrav site.
I will add my own initial observations here (bear in mind I’ve only been playing with GRAV for about 24 hours, part of which I was asleep :D):
- Upon install the Problems grav plugin said my caching directories could not be read. Assure your webserver can read/write the cache and subdirectories therein.
- If you want to develop your own plugins for the GRAV CMS then understanding its Event Hooks system will be key in the GRAV Lifecyle for a page request.
- Your content is placed page files as Markdown or other supported markup formats. Your content is wrapped by a GRAV Theme which can apply to your whole site or simply a page. Plugins can act upon and interact with the page building and viewing process.
A Custom GRAV Site
So on my local box I downloaded and installed GRAV from it’s Core zipfile to a custom domain called ak.ira in my Hosts file. I strive for “bright”, “intelligent” and “clear” code :D. Hence the site name.
I then created a custom GRAV theme for my website and altered my Users site.yaml file accordingly. Creating a theme is simply a matter of:
- including a folder with the proper name in the Themes folder, in this case akira.
- providing the requisite yaml files that describe your theme to GRAV
- choosing a toolchain or writing simple custom css files to either /css or /css-compiled directories. I installed SASS locally and use SCSS to generate compiled CSS to the css-compiled folder.
- providing the default template file for your site and any needed TWIG partial files.
Here is an example screenshot of my website folder structure (remember GRAV is a flat-file based CMS, there is no database!):
As you can see I have created the required folder structure to create my own site theme.
A few examples of my GRAV files are:
/themes/akira/blueprints.yaml
This file informs GRAV that my theme exists.
name: Akira version: 1.0 author: David Gurba url: http://davidgurba.com description: This is a simple basic theme using SASS and Flex layout for a startpage.
/themes/akira/akira.yaml
This file tells GRAV that this directory structure is read-only (a security measure):
streams: schemes: theme: type: ReadOnlyStream paths: - user/themes/akira
Lets look at 3 files that are more interesting:
default.html.twig
{% extends 'partials/base.html.twig' %} {% block content %} {{ page.content }} {% endblock %}
- This file builds the structure of any page of your website whose page name is default.ext. For example the default home page of your site is at /pages/01.home/default.md. The default name implies that the default template will be used for rendering. Other templates could be json or xml for example.
- Note at the top of the file there is extends ‘partials/base.html.twig’ this means that the structure of this page is to come from the base template and any block in this template file (content) is replaced by the page.content value. If this sounds confusing it’s because blocks as replacements and placeholders for content at the same time. This is discussed in the Twig documentation.
base.html.twig
<!DOCTYPE html> <html lang="en"> <head> {% set theme_config = attribute(config.themes, config.system.pages.theme) %} {% block head %} <meta charset="utf-8" /> <title>{% if header.title %}{{ header.title|e('html') }} | {% endif %}{{ site.title|e('html') }}</title> {% include 'partials/metadata.html.twig' %} <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"> <link rel="icon" type="image/png" href="{{ url('theme://images/favicon.png') }}" /> {% block stylesheets %} {% do assets.addCss('http://fonts.googleapis.com/css?family=Oxygen:400,300,700', 99) %} {% do assets.addCss('http://fonts.googleapis.com/css?family=Roboto:400,500,700,400italic,500italic', 99) %} {% do assets.addCss('http://fonts.googleapis.com/css?family=Roboto:400,500,700,400italic,500italic', 99) %} {% do assets.addCss('theme://css-compiled/akira.css', 103) %} {% do assets.addCss('theme://css/font-awesome.min.css',100) %} {% if browser.getBrowser == 'msie' and browser.getVersion >= 8 and browser.getVersion <= 9 %} {% do assets.addJs('theme://js/html5shiv-printshiv.min.js') %} {% endif %} {% endblock %} {{ assets.css() }} {% block javascripts %} {% do assets.addJs('jquery',101) %} {% do assets.addJs('https://cdnjs.cloudflare.com/ajax/libs/modernizr/2.8.3/modernizr.min.js',100) %} {# do assets.addJs('theme://js/akira.js') #} {% endblock %} {{ assets.js() }} {% endblock head%} </head> <body id="top" class="{{ page.header.body_classes }}"> <div id="sb-site"> {% block header %} <header id="header"> <div id="logo"> <h3><a href="{{ base_url == '' ? '/' : base_url }}">{{ config.site.title }}</a></h3> </div> <div id="navbar"> {% block header_extra %}{% endblock %} {% block header_navigation %} {# include 'partials/navigation.html.twig' #} {% endblock %} <span class="panel-activation sb-toggle-left navbar-left menu-btn fa fa-bars"></span> </div> </header> {% endblock %} {% block body %} <section id="body" class="{{ class }}"> {% block content %}{% endblock %} </section> {% endblock %} {% block footer %} <footer id="footer"> <p><a href="http://getgrav.org">Grav</a> Akira Theme.</p> </footer> {% endblock %} </div> {% block bottom %} <script> $(function () { $(document).ready(function() { // No op. ; }); }); </script> {% endblock %} </body> </html>
This file describes the major structure of any given HTML page and blocks within it which can be passed values if extended. By and large I copied this file initially from the default Antimatter theme provided with Grav.
- Note in this file I can link Google Fonts css really easily. Or link directly to my compiled SASS generated css code as needed. This is enabled by the Assets plugin provided by GRAV.
akira.scss
$config: ( colors: ( // http://www.somacon.com/p142.php plantation-white: #FFFFFE, far-horizon: #ECF1EF, ubuntu-red: #D95F69, ), font-family: 'oxygen', maxWidth: 800px, columns: 12, margin: 15px, breakpoints: ( xs: "(max-width : 480px)", sm: "(max-width : 768px) and (min-width: 481px)", md: "(max-width : 1024px) and (min-width: 769px)", lg: "(min-width : 1025px)" ) ); // https://gist.github.com/jlong/8760275 @function map-deep-get($map, $keys...) { $value: $map; @each $key in $keys { $value: map-get($value, $key); } @return $value; } body { font-family: map-deep-get($config, 'font-family'); background-color: map-deep-get($config, 'colors', 'plantation-white'); } hr { // http://stackoverflow.com/a/6382036/1491507 border-color: map-deep-get($config, 'colors', 'far-horizon'); } h1 { color: map-deep-get($config, 'colors', 'ubuntu-red'); }
I provided my own SASS file to GRAV. My end goal is to write SASS to leverage the new CSS3 flexbox layout system to make a responsive intranet site. The GRAV documentation explains that how you design your site, what CSS tools you use to create your theme is up to you. Installing SASS is really easy as it’s a RubyGem.
- I use PHPStorm as my IDE and with it I can create a File Watcher command to easily regenerate the compiled CSS whenever I make a change to my SASS code. I simply added a Watcher with the following Arguments:
If you dont want to read that image the important Argument values to scss is:
--no-cache --update $FileName$:$ProjectFileDir$/user/themes/akira/css-compiled/$FileNameWithoutExtension$.css
With all these pieces in place my functional GRAV site now is slightly less butt-ugly and appears as:
I clearly am not quite up to the single PHP page I had made before but I’ve laid the groundwork to finish building out my intranet/startpage using GRAV. My future goals are:
- Re-implement the Wake On Lan feature of the PHP page.
- Implement flexbox layout of related links.
Watch for future updates on GRAV as I work through these remaining goals (Let’s hope I get to them, this is simply a personal project).