Merging my site and blog into Drupal and Vue.js with Druxtjs

woensdag 8 juni 2022 - 553 woorden, 3 min read

I've a plan: merging my website and blog into my favorite CMS and frontend framework!

Current situation

My current blog works with Gatsby and NetlifyCMS. In november 2020 I’ve worked out this technology stack and it’s working quite well. With Netlify I’m able to write my blog posts in Markdown format. Those posts are saved as Markdown files on the server. A Gitlab CD/CI integration takes over the deployment of these files as blog pages.

My website is seperated from my blog and is just a static site I’ve made with the Vue.js framework. Note: server side rendering (SSR) is not integrated.
I’m using this stack now for quite some time, but it’s time to move on and bring my website and blog together in one stack solution.

Desired situation

I would like to merge my website and blog in one technical stack, with the same benefits which Vue.js and NetlifyCMS are providing. This means that I would like to keep writing blog posts in Markdown format in an admin area (Drupal) and that all website + blog pages are generated by Vue.js. I will be using Drupal as a headless CMS solution and the Vue.js / NuxtJS application will be calling the content through the JSON:API provided by Drupal.

This is where Druxtjs comes in. For me this is really a sweetspot tool!

druxtjs stack sebastix 1

Drupal is my favorite tool for building sites with CMS and custom made solutions. It’s like a swiss knife which I can use for multiple purposes.

Vue.js is my favorite tool for building interactive sites and applications. It has some nice nifty features and extended frameworks like NuxtJS. I used NuxtJS multiple times last months to quickly build some nice looking, basic sites. It provides you a lot of out-of-the-box features so you don’t have to build these on yourself.

In May I started developing this new stack. What I’ve done so far:

  1. Made editable Markdown formatted content type like pages, articles and blog posts
  2. Made an editable navigation / menu from Drupal

This is how it currently looks:

schermafbeelding 2022 06 08 om 10 33 22

The editable blog content in Drupal:

schermafbeelding 2022 06 08 om 11 02 06

This application code renders the blog post page:

schermafbeelding 2022 06 08 om 11 49 01

<template>
  <div>
    <h1>{{ entity.attributes.title }}</h1>
    <code>{{ entity.attributes.created }}</code>
    <slot name="field_intro"></slot>
    <slot name="field_body_markdown"></slot>
  </div>
</template>

<script>
import { DruxtEntityMixin } from 'druxt-entity'
export default {
  mixins: [DruxtEntityMixin]
}
</script>

The blog post in the browser without proper styling:

schermafbeelding 2022 06 08 om 11 48 07

The blog post content type has three fields: title, intro and a body. The intro and body are text fields (provided by the Drupal Field API) with a Markdown formatter. Each field can be rendered in a custom Vue.js component. So the field_intro component could look like this:

<template>
  <component
      :is="wrapper.component"
      v-bind="wrapper.props"
  >
    <!-- Items -->
    <!-- eslint-disable vue/no-v-html -->
    <span
        v-for="(item, key) of items"
        :key="key"
        v-html="format(item)"
    />
    <!-- eslint-enable vue/no-v-html -->
  </component>
</template>
<script>
import { DruxtFieldMixin } from 'druxt-entity'
export default {
  name: 'DruxtFieldTextDefaultFieldIntroView',
  mixins: [DruxtFieldMixin],
  methods: {
    /**
     * Formats the item output.
     *
     * @param {object} item - The field item.
     *
     * @return {string}
     */
    format: (item) => item.processed
  }
}
</script>

Upcoming challenges:

  1. Migrate current blogposts (markdown files) into Drupal
  2. Migrate related media (images and audio files) into Drupal
  3. Deployment setup with Gitlab CD/CI

I will share more updates soon about this project how I tackled these challenges!


Sebastian Hagens @Sebastix
I work as creative webdeveloper & tech consultant and care about digital freedoms. Follow me:
or visit my contact page