Blog

I write on blua.blue, dev.to and others

Static content pages - still the fastest web-experience

In the constant battle of visibility, SEO and speed are important factors. Too often do we neglect these points due to our love for the dynamic web, slick SPAs and client-heavy gimmicks. Next to accessibility, static pages solve for many of these problems while our static site generators are usually monsters of their own.

Today, let's look at a "micro generator" that helps us to manage content dynamically while delivering static HTML pages.

Video-version of this tutorial: YouTube

The concept

The idea is rather simple: let's use the webhook capability of a headless CMS (here blua.blue) to receive content and write/update static HTML files. Next to what we want to achieve, this is a solution for additional challenges:

 - it enables us to omit any API necessities

 - it enables us to run our CMS locally or within a private network

In this POC, we will use the following folder structure

/assets/

/assets/template.html

 /assets/menu.json (not used in the article, but in the video and gist)

/assets/script.js (not used in the article, but in the video and gist)

 /assets/style.css

/blog/

receiver.php

.htaccess (if apache)

 

Preparing the CMS

For development reasons (when you develop locally, you will find yourself having trouble sending webhooks to localhost), I installed blua.blue locally. However, you can develop online (e.g. via FTP) to avoid a bigger setup. Whatever the case, setup your headless CMS to send webhooks to your endpoint. In my case, that was http://localhost/static-blog/receiver.php and using a baerer token for security.

Tip 1:

In blua.blue, you can set webhooks in "Manage" -> "API"

Tip 2:

When using Apache, be sure to include the following in your .htaccess


RewriteEngine On
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]

 

receiver.php

Our receiver should account for the following tasks:

1. Validate calls to ensure the received call is legitimate

2. Account for various events (create, update etc)

3. Write/update static pages

4. Generate a menu

 

Let's start:

First, let's create our class that we can later initiate with new Receiver('our-webhook-secret');

class Receiver
{
   
    function __construct($mySecret)
    {
        if (isset($_SERVER['HTTP_AUTHORIZATION']) && substr($_SERVER['HTTP_AUTHORIZATION'], 7) == $mySecret) {
            // valid call -> do things
        }
    }
}

Next, we want want to grab the payload of the call:

    private $data;
    private function fetchData()
    {
        $data = file_get_contents('php://input');
        if (!empty($data)) {
            $this->data = json_decode($data, true);
        }
    }

We now have the data available as associative array in the property $data. At this point, we should know that the blua.blue call is structured like this:

{
    "event": "created",
    "payload": {
        "name": "article-name",
        ...
        "content": [
            {
                ...
                "content": "<p>Content</p>"
            }
        ],
        ...
    }
}

So let's make sure we have that information available in our instance and create a switch-case for the possible events
 

- created

- updated

- deleted

in our constructor:

function __construct($mySecret)
    {
        if (isset($_SERVER['HTTP_AUTHORIZATION']) && substr($_SERVER['HTTP_AUTHORIZATION'], 7) == $mySecret) {
            $this->fetchData();
            switch ($this->data['event']) {
                case 'created':
                case 'updated':
                    // here, let's write to a file
                    $this->writeToFile();
                    break;
                case 'deleted':
                    break;
            }

        }
    }

You might wonder about the method "writeToFile" as we don't have it yet. but first, we need to account for two prerequisites:

- template-rendering

- template

Using composer, let's include neoan3-apps/ops (composer require neoan3-apps/ops) and remember that we need the autoloader available (require_once __DIR__ . '/vendor/autoload.php';) in our receiver.

For now, the template is a primitive HTML file in /assets/template.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>[[name]]</title>
    <link rel="stylesheet" href="../assets/style.css">
</head>
<body>
<div class="container" id="blog">
    <blog-menu>
        <ul>
            <li n-for="links as link">
                <a href="[[link.link]]">[[link.name]]</a>
            </li>
        </ul>
    </blog-menu>
    <h1>[[name]]</h1>
    <div class="content-part" n-for="content as contentPart">
        [[contentPart.content]]
    </div>
</div>
</body>
</html>

Ups... blua.blue and dev.to have some issues with parsing this template. The hard brackets should be curlys!

The markup should be intuitive, but feel free to head over to the documentation at: https://packagist.org/packages/neoan3-apps/ops

 

Finally, let's address our missing function:

private function writeToFile()
    {
        // let's ignore the article if it is a draft
        if ($this->data['payload']['publish_date']) {
            // account for \Neoan3\Apps\Ops routing
            if(!defined('path')){
                define('path', __DIR__);
            }
            $destination = path . '/blog/' . $this->data['payload']['slug'] . '.html';
            $content = \Neoan3\Apps\Ops::embraceFromFile('assets/template.html', $this->data['payload']);
            file_put_contents($destination , $content);
        }
    }

That's it! We can now generate our first static article by using the blua.blue backend.

Now, there is a lot of functionality missing (like delete, menu etc.). Some of it is addressed in the video and you can find a little more advanced version here: https://gist.github.com/sroehrl/c81a1d90a8db87b55307ea7f791c1de7

image

Stop learning what you think is relevant

Still learning react, laravel & co? You better plan ahead!

image

How to use JWT in the neoan3 PHP framework

Many things have changed since I last addressed implementing JWT & stateless authentication & authorization.

image

Rapidly build your own stateless REST-API with neoan3

One of the most common tasks for a web-developer is interacting with an authenticated backend. While a plethora of possibilities are available, the way neoan3 handles things is not only convenient, but also fast and reliable.

image

Generating Phaser Game assets: Planet spritesheet generator

Ever needed to automate a process and all of a sudden you built a tool?

image

Do you even write?

Using the blua.blue webhook in order to track your writing.

Install PHP 8 on Ubuntu

PHP8 has finally been released and it is FAAAAST! Time to update.

image

6 Technologies to look at in 2021

2020 wasn't the best year humans can look back to. but what does 2021 bring for coders?

image

CSS Grid or CSS framework - are they really exclusive?

Grid-based or framework - there are many articles about this choice. But why is that even a thing?

image

Scaffolding REST APIs with JWT authentication

Ever had the need for your own backend while developing your web-app?

image

What is composer?

Composer has become PHP's package & dependency manager. Why you should use it.

image

MySQL: ERROR1364 fix

The painful realization of why people use containers.

image

Cyber wars: Defending your server

Maintaining your own server can be a thrill. High security standards can protect you from data leakage, injection attacks and DDoS attempts. But what about adaptive brute force?

Git: globally change GitHub-remotes from git@ to https

Does your IDE or composer set remote repositories to ssh rather than https? Or are repositories you are using set up that way? You are not alone. Let's fix it once and for all!

VueJS & neoan3: a love story.

Setting up neoan3 to play nice with Vue isn't hard. Here is how the two frameworks are combined to support fast, dynamic and rapid development.

image

MySQL in PHP - how to deal with databases

How I handle MYSQL database transactions in PHP

Install PHP 7.4 on Ubuntu

Finally PHP 7.4 is out! You have read about the new features, you have followed externals, you have gathered ideas on how new capabilities will save time. Let's get it running.

How to install global npm packages without sudo on Ubuntu

Running npm on a server can be painful. Privileges are there for a reason, and so is sudo. Running npm with sudo is not the solution.

image

Static content pages - still the fastest web-experience

Tutorial: How to utilize blua.blue to generate static content for your website.

image

Cross publishing to dev.to

How to publish your content to dev.to from blua.blue - hopefully

The Uselessness of Pre-Assessment

After almost two decades in the industry, new jobs will still ask you for "assessment tests". A little rant...

image

SEO strategies for blua.blue

How to get your content listed where you want it to.

image

How to Build an Express App in Node That Reads From a Headless CMS

A headless CMS lets you design your own front-end, sometimes your own back-end. Let's set up a small application to get us started. Beginner friendly. Approx. 20 min. to reproduce / follow along

Transformer - falling in love with PHP's magic methods all over again

PHP's magic functions have been around for a long time. But there were always good reasons to avoid them. Transformer is a practical and reliable way to make use of the most common operations we program: CRUD operations.

image

Help us document neoan3

Over 4000 brave developers are exploring the framework on their own.

image

When politics kill innovation

How misunderstood diversity killed the PHP Central Europe Conference for good.

image

blua.blue PHP SDK

Create your own blog.

image

dev.to plugin for headless CMS blua.blue (part 2)

A solution to supplying plugins to blua.blue