Sunday, November 25, 2018

Sanity static site generator

One thing that bothers me about most of the static site generators, is that they assume everyone knows how to use git. Git is a great way to maintain static files, because you can revert changes and see who made the changes. This makes it better than a database because a database has no changelog. The only way to revert with a database is to import a backup.

Github, Bitbucket and Gitlab, the three biggest git hosting providers, all have an api that allows developers to execute commit, push, pull and other git commands. This allows your application to stop burdening your users to learn git.

A few weeks ago I came in contact with Sanity. This is a content administration solution. They use CMS sparingly because most of the popular ones also take care of the data output. Sanity doesn't care about the data output. It only provides a query interface, much like a regular database.
This makes it perfect to build solutions on top of it.

Sanity configuration

The default sanity backend configuration provides three columns. In the left column you have a list of document types. In the middle column you see a list of the documents from the type you selected in the left column. And the right column is the document editor.
But you can change that layout. From now on i'm going to call document types page types, this is closer to the naming people use with static site generator solutions.
To create my sanity driven static site generator I had to think in pages because the static site generator needs to know which pages to create.
Most sites have one homepage and then one or more types of pages.

From line 11 to 18 is the configuration to show Homepage in the left column. And the editor of the homepage in the middle column.
Line 19 to 20 adds all the page types, except homepage, to the left column. This is almost like the default layout.

Now that the backend layout is created, it is time to create the page types. To create the body of the page types I'm going to use a collection of rows with columns. Sanity calls the configuration schema. In that schema there is a schemaTypes section which holds page type part and the page type configurations. To make it more readable it is best that the schemaTypes are split up into a file per schemaType.

Lets build the page type parts, row and column.

On line 4 you see the type of column is object. This allows the schemaType to be used in other objects and documents.
From line 5 to 7 you see the configuration of a fieldset. The name of the fieldset is added to the fields, as you can see on lines 32 and 38.
Lines 41 to 45 configure which field value is visible when the schemaType is in a collection.

On line 28 you can see how the column schemaType is used in this object.

Page types are almost the same, but instead of type object they have type document.

The main diffrerence between the page types is that the common_page type has a path field

This is the end of the sanity configuration. Now you can do two things, run the sanity backend, called studio, on your local computer or deploy it to sanity.io.

The static file generator

I read the Indexing in Agolia using serverless functions article. And the use of a scheduled webtask function gave me the idea to get the data from sanity, transform it to html and push it to a git hosting provider.

It is a lot of code. The two big parts are setting up the sanity and bickbucket connections. And transforming the page data to html.

From line 45 to 57 is the sanity query for both the page types. The thing that is missing from the query is the check for the timestamp that only gets the pages that are changed after the previous run of the webtask function.
Lines 90 to 105 commits the changed pages to the repository.

Next steps

At the moment the html tranformation doesn't add css or javascript to the pages. A real world application would also have navigation and forms.

The git hosting providers have a download the repository button and that allows you to place the html on the server of your choice.

Sanity has a third option for the backend, it allows you to create a static file version of the studio, and can also go on your public server. The imitation of common CMS solutions makes the step to a static site generator setup easier.

Monday, September 25, 2017

Drupal 8: options to manipulate the main part of the page

The body of a Drupal page, or any other CMS, started out as one block of html.



The problem with this approach is that the editors needs to know how the css grid of the themes work to give structure to the content.

Most css grids are row based with different column widths. This makes content manipulation a case of creating rows with column content. The options I'm going to show in this article are all about this way of structuring content.

Paragraphs

The first Drupal specific solution is paragraphs. The paragraph as an html tag is in fact a row, so the name captures the intention. 

The way it works is to create all the different types of paragraphs, or rows, the editor will need.  Each paragraph type has a template to place the fields, or columns. These paragraph types can be added to a content type with the paragraph field.


The good

  • The single block of html is cut up 
  • Editors don't need to know how the css grid works
  • Simple to set up
The bad
  • When there is a lot of content on a page it can be hard to find a specific piece as editor
  • Paragraph type content can't be shared with other pages
  • To provide as much choice as possible a lot of paragraph types are needed

Bricks

The second Drupal specific solution is bricks. This is the newest of the Drupal specific solutions. It is so new it depends on experimental modules from Dupal 8.3. 

The idea is to define the content that can be placed in a column, this is called a brick. The rows are created with a *.layouts.yml file and template files in a module or theme.  The easiest way to create the bricks is to install the eck module. This module adds forms to the backend to create an entity with different bundles. The entity is added to the content type with the bricks field.



The good
  • Because the rows are split from the column content less configuration is needed
  • The editors can create content structures developers didn't think of
  • Brick content can be shared with other pages
  • A specific piece of content can be found easy when there is a lot of content, because the form display is a tree like menu items.
The bad
  • An experimental dependency which has the potential consequence to remove content by a future breaking change
  • Harder to set up
  • Naming bricks to be descriptive for the content can be hard

Ckeditor widget

The ckeditor widget is the only solution where the single body field stays. Widgets are predefined pieces of html that are added by buttons in the toolbar. I linked to the first part of the how to create a widget tutorial.

Like bricks you can define row types and column content types with widgets.

The good  
  • It is CMS independent
  • Content looks as it would on the site
  • Rows are not the only content structure that can be added, freedom is good
The bad 
  • Content can not be shared with other pages
  • Rows are not the only content structure that can be added, too many possibilities can create problems
  • A big toolbar to provide the editor as much choice as possible
  • Toolbars per content type are harder to set up
Conclusion

If the editors are used to work with html I recommend the ckeditor widget solution because it is writing html with shortcuts like the emmet plugin for desktop editor en IDE applications.

if the editors are not used to work with html I recommend bricks because it provides the most flexibility while being easy to use.

The only case in which i recommend  the paragraphs solution, is when the editors want a limited amount of choices and most of the content is short.  






Friday, March 03, 2017

Making a file based cms

This is my mandatory one post per year. 

 I've just made a github repository where if you follow the commits you can see how a basic file based cms gets build.

If you see changes in the composer.json file you need to run composer update .

In the Conversation #5 commit I had to add a code change because i forgot brackets. But for the rest the code will run before you go to the Coversation commit.


Sunday, May 01, 2016

Multi dimensional array manipulation in php

This week I wrote some code that got the following reaction of a fellow coder; when we need to change this code it will be a hell for us to understand.

The code looked like this, but with even more loops and manipulations.

The fun starts on line 17 where i begin with the nested loops. I know that looks ugly from the start. At the time I couldn't think of another way to handle this.

PHP has a lot of array functions, but most functions only handle one dimensional arrays. There are a few functions that can handle multi dimensional arrays by using recursion but they come with their limititations.

Array_walk_recursive applies a callback on each element of the array. But the problem is that any key that holds an array will not be passed to the function. When you want to manipulate arrays that is a bit of a problem.

Array_merge_recursive is out of the picture because it doesn't manipulates arrays. If the arrays you want to merge have the same numeric key the second array value will be appended.

Array_replace_recursive is the function that shows the most promise, if it wasn't for a separate code to build the replacement array.

That is why I have decided to create an array manipulater that works with callbacks based on the depth of the array and/or array key.
I have written it as a drupal module you can find here

The code from before will look as follows:

The benefit of this class is that the nesting of arrays is kept to a minimum, and that the manipulation of the array you want is contained to the array itself. In the code above I needed to use the full array keys to know if there where manipulations (lines 25 and 42).

The class still has some warts in the form of needing to force a key for a certain depth and nested field keys in a complex array, but i'm going to fix that in future versions.

Update

I have updated the class after a tip from the same developer who made the first remark.

Sunday, May 31, 2015

Preparing for drupal 8

Why now?

It look like the drupal 8 betas are going to end soon. Last month there still were 40 critical bugs, it looked like there was no progress. But with beta 11 the critical bug count got cut in half!

This was a sign for me to get up to speed with the last developments. For that i'm using the great talk by Larry Garfield at last years drupalcon in Amsterdam.

Going through the motions

I have downloaded beta 11 on my windows machine and i'm using xampp to run it.

He said a controller can return a string, this seems not true anymore. I got an error the return should be a Response instance.

Installing modules aren't mentioned in the talk, but I got a strange error enabling the custom module. It appears to be a mysql setting issue.

In the routing.yml file he doesn't quote the path value, but it seems a lot of other modules do. So I guess it is a best practice to do so.

When he makes the module themeable, he uses the template folder. This generates an error saying you have to use templates.

This must be an oversight, the BlockBase class is in the Core folder.

Observations

Drupal 8 is major evolution for the platform. As Larry mentioned even drupal 7 is based on php4 practices, when it is almost ten years ago that php5 came out. It is my biggest gripe and drupal 8 wipes it out.

I'm not that found on the mix of yaml files and annotations for configuration, but splitting up the configuration is a developers dream after the hooks for everything way.

In drupal 7 it would have been more difficult to find the errors, but with the modern architecture errors made it easy to get to the problem and fix it. Goodbye common.inc, we won't miss you.

They didn't only modernized the architecture, they also added new default modules and an improved way of doing things, that make it an amazing content management platform.

With the mordernized architecture come great tools, instead of the devel module people have ported the web profiler from the symfony framework.

Questions from great readers

Why don't you use drush?

It looks like drush has still a long way to go to support drupal 8 on windows.

You need to use drush 8 to have drupal 8 support. There are a lot of articles that say drush 7 supports drupal 8, but drush 7 mentions otherwise.

When you install drush 8 with composer, the only way at the moment, the drush command doesn't work in the command prompt because it has linux syntax. The drush.bat command doesn't work either of the same reason.
The drush.php.bat command seems to work if you use it without parameters, but once you use it with parameters it can't find the tasks.

There is an alternative, drupal console. It works on windows.

Why can't I uncheck the custom module, once it's enabled?

It seems like a security measure to prevent a compromised data integrity. You can uninstall modules, so the unchecking hasn't disappeared.

Saturday, May 30, 2015

Code doesn't care who wrote it

Only people care

Computers just don't care.

I just saw a github conf post, and I was as thinking who cares?

My view

For all I know the code could have been written by an alien from starcluster 5574564, if it's code that is readable or at least has a predictability I love the programmer(s) that wrote it.

I know programming looks like it is a boys world, but I'm almost 40 so I am not a boy and I still surprise the boys at my current firm.
It isn't all about knowledge if you are a real programmer. You have to analyse problems and translate that into code.

I can understand the sociological aspect of hiring a programmer as HR but that it is human nature. You hire the people you can connect with. A more technical person comes in to evaluate that aspect. And when it is all smoothied you get the conclusion.

Small victory

While I'm not against focusing on groups that are statistically are under represented in the programming community. But showing that there are amazing people out there that need to get hired is great.

I believe people who do good things will get noticed. I am a cook/waiter if you only follow my school education. I work in IT for a little than 10 years now. I always improved my knowledge and sharpened my problem solving skills.

I will always try to improve myself, it has nothing to do with work. it has to do with the person I want to be, better stronger faster smarter, until the day I die.

Sunday, May 24, 2015

PHP 7 spaceship operator

Wait what?

The spaceship operator isn't a name for a language that wants to get enterprise credibility.

Take a pause, and look at it for a distance

The operator probably solves a problem many php developers face.

stackoverflow

Instead of only having a boolean check, it is a ternary check without the logic you need to write yourself.

One thing php as a language was always good at is solving real world problems, sometimes with flawed implementations, but they make it easier for others to understand the code.

epilogue

Don't be square and make your code php 7 compatible as soon as possible.