
Running a self-hosted blog has its challenges - and I bumped into some of those eventually. Well, rather than running out of ideas / motivation or time to come up with new articles, I eventually had some technical problems: Updates & Security - being the most important one ? ?.
If you’re using a self-hosted blog, you eventually will need to do constant updates. The more popular engine you’re using - the more risks of being hacked and the more up-to-date you have to be (especially if you’re running on Wordpress). I am kinda lazy, so eventually I skipped some big updates and my hosting got hacked. And this happened many times.
Many hacking waves are automated - they just crawl the web, identify Drupal websites and try commonly known exploits on them (that are documented everywhere), and if you’re not up-to-date, they breach-in. You can leave it hacked - but eventually someone will sell access to your hosting on the black-market and some shady things will start happening - in my cases I had some websites popping up on my VPS (I used DigitalOcean VPS) - and after making a backup of my website, I had enormous pleasure of destroying the Droplet with all the weird websites it had on it.
In modern days, there are ways one can automate this process, in example:
However, to me, these options are way overkill - I don’t want to pay extra for Pantheon, nor I want to write a CircleCI (or Github Actions) script or a crontab + shell script. Also I don’t want to constantly run updates locally and then deploy those (that’s why I got hacked in first place).
Also, other than CMS’s vulnerabilities, there are also PHP’s vulnerabilities, Apache/Nginx’s vulnerabilities, ssh vulnerabilities - so you’d have to update the operating system itself and all the packages, then restart nginx, php-fpm, mysql and hope for the best.
Eventually I decided that I want to have a static front - running on a static engine, and the outputs of it can be hosted for free - either on some CDN, Github’s static pages, Netlify or even Amazon’s S3 Bucket.
Static front won’t have any need for updates (at least no security related needs), can’t be hacked, and I don’t have to worry about operating system updates, packages updates, etc.
So to sum up, it comes with a lot of advantages, and even some extra bonuses:
Many developers will be happy uploading simple markdown files and images directly to Gatsby.js (or any other static site engine) - but I want to have the experience of a CMS. I’d like to create / edit / delete content via UI, tag content, upload images, sort things via drag and drop, etc. For that purpose I decided to go with a combo of Drupal 8 (headless) and Gatsby.JS as a static front.
Using a CMS in a headless way, that feeds a static front, has many advantages (I like bullet points, I guess):
I eventually settled on Drupal 8 and Gatsby.JS.
Why Drupal? Well, we know that Drupal is amazing, and the 8th version seems to be pretty solid. Also the 9th version is just polished off (minus the deprecated code) version of the Drupal 8. I also worked on manual migration of Drupal 7 to Drupal 8, I didn’t use the automated ‘upgrade’ path as I didn’t want to have half of the modules or other junk (plus, maybe there were some back-doors in old DB that I didn’t spot).
Why Gatsby.JS? Well, because it’s based on React and GraphQL, it’s super fast, it’s popular, it’s modern, it has a built bridge to Drupal 8, etc. I wanted to start learning React for a long time and Gatsby.JS was my introduction to it
Gatsby.JS has many advantages and features, I won’t list or cover all of them, but I’ll just list some that were important to me:
Migration process, in my case, consisted of 5 parts:
Before I dive into each step in a bit more details, I’d like to mention this repo - https://github.com/docksal/boilerplate-drupal-gatsby
I used it for my personal blog and it does make things a bit simpler - it’s a boilerplate that uses Docksal (docker containers) to spin-off an environment with a running Drupal + Gatsby.JS (and the bridge between them).
This is not my first Drupal 8 + Gatsby.JS implementation, earlier I did this setup myself but having this repo saved me some time and probably will save you ⌚ as well.
This part probably went hand-in-hand with the 3rd part - picking a theme. I have analyzed various themes and the structure that I had in Drupal 7. I’ve picked the content-types and fields that I wish to have in Drupal 8 and created those - they differ just a bit from old implementation. Then I settled on an administrative theme (to manage my Drupal content in), picked some contrib modules and was ready to do the data migration.
In my case it was fairly simple - as my blog had a relatively simple structure. I wrote a custom Drupal 7 to Drupal 8 migration module to handle the data migration. I’ve run migrations and rollbacks until I was happy with the final result and seen all my data living in the Drupal 8 shell.
Just a note here - if you’re not happy with the standard Drupal 8’s “upgrade path” - you can just re-use its Drupal to Drupal migration classes.
In example, you can migrate Drupal nodes by using the d7_node source plugin, like this:
id: old_nodes
label: Old Nodes
migration_group: blog_posts
migration_tags:
- Drupal 7
source:
plugin: d7_node
node_type: article
key: legacy
process:
# Node things you want to migrate.
nid: nidIn this example ‘key’ is the database connection key used to connect to the old Drupal 7’s database. This way the migration process automatically figures out what is a Node, and a Node of the specific content-type and it also knows how to fetch the fields and their values, etc - magic :)
You can build your own theme, but it will cost you some time - to design it, slice it, code it, etc. I wanted to look for something ready and responsive, so I will get it off the ground fast enough.
There are several options:
In my case - I found the theme I liked on the JAM Stack Themes - https://jamstackthemes.dev/theme/gatsby-flexible/ with the source code as follows - https://github.com/wangonya/flexible-gatsby
However I still had to adapt it to my liking - I also wanted to have tags, adjust the pagination a bit, have proper SEO snippets in-place, etc.
Also, this needs to fit into the Drupal infrastructure - what does this mean? This means that I had to create graphql queries, that know how many static pages to create, how many file-versions to create, how many tag-pages to create, etc.
Some of the highlights that I had to implement:
I also was inspired by the Alexei’s code - and created GraphQL fragments to simplify my queries - but I still didn’t fully understand how these work, even though I spent quite some time on them:
import { graphql } from "gatsby";
// Document all fragments for paragraphs here.
//
// Include this file at least once so that webpack can pick it up, it's important to be picked up by Gatsby
// during the build process so Gatsby can process all the fragments.
export const query = graphql`
fragment MediaField on media__image {
file: relationships {
field_media_image {
localFile {
preview: childImageSharp {
fluid(maxWidth: 600) {
...GatsbyImageSharpFluid
}
}
full: childImageSharp {
fluid(maxWidth: 1400) {
...GatsbyImageSharpFluid
...GatsbyImageSharpFluidLimitPresentationSize
}
}
}
}
}
}
fragment NodeCover on node__article {
relationships {
field_cover {
...MediaField
relationships {
field_media_image {
localFile {
ogFB: childImageSharp {
fixed(width: 1200, height: 630, quality: 100, cropFocus: CENTER) {
...GatsbyImageSharpFixed
}
}
}
}
}
}
}
}
fragment NodeTags on node__article {
relationships {
field_tags {
name
path {
alias
}
}
}
}
fragment NodeImages on node__article {
relationships {
field_media {
relationships {
field_media_image {
localFile {
childImageSharp {
fluid(maxWidth: 300, maxHeight: 200, quality: 100, cropFocus: CENTER) {
...GatsbyImageSharpFluid
}
original {
src
width
height
}
}
}
}
}
}
}
}
`;This allows you to use sexy queries like this:
export const pageQuery = graphql`
query blogPageQuery($skip: Int!, $limit: Int!) {
site {
siteMetadata {
title
}
}
articles: allNodeArticle(limit: $limit, skip: $skip, sort: {order: DESC, fields: [created]}, filter: { status: {eq: true}}) {
edges {
node {
internalId: drupal_internal__nid
drupalId: drupal_id
title
created
body {
summary
processed
}
fields {
slug
}
...NodeCover
...NodeTags
}
}
}
}
`Anyway, it’s a bit out of the scope of this article ?, I’ll prepare another blog-post with a bit more tech details and a published public repo so you can fork it or play with it as you wish ?
A fast static website ?, that’s pretty flexible and dynamic to both its end-users (visitors) and to me - as an editor. It’s fast to get up and running, and also free to keep in running - as Netlify, Algolia and other services that I use are free.
If Netlify’s build time is not enough for your website or project, you can also use CircleCI (it offers more free build-time and the build process is a bit faster than Netlify) and you can publish the build from CircleCI to Netlify via Netlify CLI tool.
I’m planning to polish a bit my existing code and will release it as an open-source repo on Github, so you can play with it, or launch a similar looking blog if you want to.
Planning to dive a bit more into details on how to make the Drupal to Gatsby Bridge (and how to debug things with GraphiQL), what are the fragments and how to use those, how to create the components, how to use off-the-shelf react packages, and I’m also planning to release the CircleCI example on the build process (or in other words - how to have more “build minutes” and still use Netlify, for free).
If you’re interested - place a “?” reaction below, leave a comment, or just stay tuned ? for part 2.



