In late May, Adam, the CEO at Omeg8.cc, pinged me on Twitter and asked me if I was available to apply in a job which requires to port a ThemeForest theme to Grav CMS.

I accepted the job and I arranged the details with him. The most important step of this phase was explaining him that the best option for the porting, was to use shortcodes, though this falls in a higher price.

Why shortcodes

Shortcodes are a bridge to handle complex sections of content using markdown. Just give a look at this page section:

That kind of content is usually handled in a Grav's page header section, using yaml. A real example could result in a page which ends like this one:

---
features:
  0:
    title: Web Design
    icon: desktop-mac
    delay: 1
    content: We at Caliber design and create brilliance at work in a uniquely stylish process.
  1:
    title: Hosting
    icon: server-network
    delay: 2
    content: We at Caliber design and create brilliance at work in a uniquely stylish process.
  2:
    title: Photoshop
    icon: desktop-ma
    delay: 3
    content: We at Caliber design and create brilliance at work in a uniquely stylish process.
  3:
    title: Web Design
    icon: desktop-mac
    delay: 1
    content: We at Caliber design and create brilliance at work in a uniquely stylish process.
  4:
    title: Hosting
    icon: server-network
    delay: 2
    content: We at Caliber design and create brilliance at work in a uniquely stylish process.
  5:
    title: Photoshop
    icon: format-paint
    delay: 3
    content: We at Caliber design and create brilliance at work in a uniquely stylish process.
---

# Lorem ipsum
Lorem ipsum

Next, the page.header.features variable must be handled in the twig template, to render those entries.

That approach works fine, but introduces some minor, sometimes annoying problems:

  • If you want to add some markups to yaml content you cannot use markdown and you must fall to HTML.
  • You loose continuity from the content you are writing and the section handled in yaml.
  • When you require to reply that section, you must repeat the same logic through pages.

Handling that section using shortcodes ends as follows:

---
# other parameters
---
# Lorem ipsum
Lorem ipsum

[o8-feature name="features"]
    [o8-feature-item title="Web Design" icon="desktop-mac" delay="1"]
        We at **Caliber** design and create brilliance at work in a uniquely stylish process.
    [/o8-feature-item]
    [o8-feature-item title="Hosting" icon="server-network" delay="2"]
        We at Caliber design and create brilliance at work in a uniquely stylish process.
    [/o8-feature-item]
    [o8-feature-item title="Photoshop" icon="format-paint" delay="3"]
        We at Caliber design and create brilliance at work in a uniquely stylish process.
    [/o8-feature-item]
    [o8-feature-item title="Web Design" icon="desktop-mac" delay="1"]
        We at Caliber design and create brilliance at work in a uniquely stylish process.
    [/o8-feature-item]
    [o8-feature-item title="Hosting" icon="server-network" delay="2"]
        We at Caliber design and create brilliance at work in a uniquely stylish process.
    [/o8-feature-item]
    [o8-feature-item title="Photoshop" icon="format-paint" delay="3"]
        We at Caliber design and create brilliance at work in a uniquely stylish process.
    [/o8-feature-item]
[/o8-feature]

Using this approach, they easily can reuse the [o8-feature][/o8-feature] shortcode everywhere in their site, without dealing with page headers variable and twig templates.

Porting the templates

The very first operation, after the theme structure creation, was to add the base template, starting from the Theme Forest html file. Each template inherits from this one and contains all the common template sections.

All theme assets have been adapted to be loaded by Grav:

{% block stylesheets %}
    {% do assets.addCss('theme://css/pace-loading-bar.css', 103) %}
    {% do assets.addCss('theme://css/animate.caliber.css',102) %}        
    {% do assets.addCss('theme://css/animate.css',102) %}
    [...]
{% endblock %}
{{ assets.css() }}

fixed metatags have been removed and handled into a separate template:

<title>{% if header.title %}{{ header.title|e('html') }} | {% endif %}{{ site.title|e('html') }}</title>
{% include 'partials/metadata.html.twig' %}

Body contents have been splitted in three sections:

  • Header
  • Content
  • Footer

each one defined by a Twig block:

{% block header %}
{% endblock %}

{% block content %}
{% endblock %}

{% block footer %}
{% endblock %}

The main navigation menu

They do not require to populate the main menu from site pages, so I created a global navigation site variable to handle the main navigation:

navigation:
    left:
        home:
            label: Home
            url: /
            sub:
                0:
                    label: Home 1
                    url: index.html
                1:
                    label: Home 2
                    url: home-2.html
                [...]

        pages:
            label: Library
            url: library
            sub:
                0:
                    label: Services
                    url: index.html
                [...]
    right:
        blog:
            label: About
            url: about-us
            sub:
                0:
                    label: Medium Alternate
                    url: index.html
                [...]
        contact:
            label: Contact
            url: #

The navigation has been splitted in two separates collections, left and right, to correctly handle the respective part of the navigation menu. Each item is represented by a collection entry, defined by three parameters: label, url, sub.

When they need a menu without any sub-item, they simply avoid to use the sub parameter, as did for contact menu item.

In a second step, they asked to use the parallax menu style: that means I would have to change the menu, throwing away the job I already did, but it would be a pity and, worse, they would have lost a chance to use a complex menu in the future.

For those reasons I decided to try to implement both the menu styles, because they are defined by a very similar structure.

That was quite easy to do just with a little effort, introducing a new parallax variable defined in the site.yaml and used as follows:

{% set parallax = (site.parallax is defined and site.parallax == false) ? false : true %}
{% if parallax %}
    {% include 'partials/navigation_parallax.html.twig' %}
{% else %}        
    {% include 'partials/navigation.html.twig' %}
{% endif %}

When the parallax variable is defined and it is set to false, the normal menu is rendered, otherwise the parallax menu is used.

Contents titles

Title sections, you can see in the picture below:

are defined by a quite complex markup:

<h1 class="heading">Why Choose Us</h1>
<div class="headul"></div>
<div class="subheading">
<p >Lorem ipsum dolor sit amet, consectetuer adipiscing elit enean commodo  eget dolor aenean massa eget dolor aenean massa</p></div>

As you can see that markup has a title, a div deputed to render the separation line and a subtitle section. Markdown is not enough to render a section like that, so I decided to handle whole title sections with shortcodes. The shortcode that renders the markup I'm talking about, is the following one:

[o8-centered-section title="Why Choose Us"]
    Loream ipsum dolor sit amet, consectetuer adipiscing elit enean commodo eget dolor aenean massa eget dolor aenean massa.
[/o8-centered-section]

Another kind of title is the one in the picture below:

which is defined by the following markup:

<h1 class="heading text-white left-align">Services</h1>
<div class="headul white left-align"></div>
<div class="subheading text-white left-align"><p>Features & Specifications</p></div>
<p>Nam quam nunc, blandit vel, luctus pulvinar, hend lorem. Maecenas nec odioet ante tincidunt tempus luctus pulvinar, hendrerit id, lorem.</p>
<p>Maecenas nec odio et ante tincidunt tempus natoque penatibuset magnis dis parturient nascetur ridiculus mus.</p>

and this is the shortcode I defined the handle that title:

[o8-left-section title="Made For You"]
    Asunt in anim uis aute irure dolor in reprehenderit in voluptate cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cun proident, sunt in anim id est laborum. Allamco laboris nisi ut commodo consequat. Aser velit.

    Maecenas nec odio et ante tincidunt tempus natoque penatibuset magnis dis parturient nascetur ridiculus mus.

    [g-link url="#" attributes="class:btn btn-primary" menu="Know more"][g-link]
[/o8-left-section]

Next, I started to implement the home page modules and the footer section, adding other shortcodes to handle the company competences list, the blue/black card and the price card.

Adding internal templates was a quite easy task, because the hard job was made developing the home page. I reused several shortcodes to handle the internal pages, saving a lot of time.

The only real challenge here was the internal menu implementation, because it would have had to display the internal pages' taxonomy, instead of the pages themselves. In fact, when a menu item is clicked, the list of pages that defines the selected taxonomy, would have been rendered in the main content section.

Fix theme bugs

Adam found some bugs in the Theme Forest theme so, to fix them, I suggested to add a new stylesheet to keep the original one intact, where we could add bug fixes and new styles.

In this way, if Theme Forest will update the theme, the custom changes will be safe.

Conclusion

I really loved to apply this job which gave me a lot of personal satisfaction. I tried to focus hard on the details, giving Omega8.cc the easiest tools to handle the contents of their new website. At last, I'd like to thank Adam because he was a very kind customer and it was really a pleasure working with him.