Quickly develop static websites with VueJS, a headless CMS and GraphQL
Static websites are awesome! But what is a static website actually? It’s quite simple: a website that’s built only with HTML, CSS and JS without any server behind (yet it’s able to talk to an API via Ajax requests). However I don’t want to waste time talking about what a static website is and why it matters, there are enough resources on that, e.g. the article The Static Web Returns.
- Basic ES6 knowledge
- Basic VueJS knowledge (I personally recommend these books for newbies and for advanced)
- Basic GraphQL knowledge (Read this book first if you are not familiar with GraphQL)
VueJS is overkill for static sites
Of course it is! You can start a static website without any tools at all, just upload an html file to your server and you are done. Although there are few problems you will be facing sooner or later:
Talking to APIs, state management, animations and so much more is very easy to achieve with VueJS.
SEO and performance
If you are new to VueJS and the world of static websites, I guess this will be the first question you are asking. Yes there might be SEO problems when only using VueJS on the client side. To address these issues our website will be generated with NuxtJS upfront and then uploaded to our server. That means we will have plain HTML files on the server. And I can tell you.. performance will not be a problem if you do it right. The user will first see the pregenerated HTML files and all JS files including VueJS plus some other packages will be loaded afterwards.
Setting up your project
To start your project we will simply use the NuxtJS starter template. You can find a very good documentation about setting this up on the NuxtJS documentation, but I will go through this very quickly.
You will first have to install vue-cli if you didn’t already. Then let’s initialize our project using the starter template and the vue-cli with
$ vue init nuxt-community/starter-template <project-name>
Then you will have to
cd into your project and run
npm install . Using
npm run dev you can already start a development server and open your project in the browser.
Great! That’s the first part. With
npm run generate you can now create a static site made with VueJS! Super easy.
Managing the content
The next question might be “How can I manage contents?” or even “How could my clients manage contents?”. Until today most static site generators require you to edit your contents on a flat file basis. That means you have a content directory inside your project source where you have something like markdown files or whatever. I am not really a fan of that. It’s easy for you as the developer but you cannot give this to a client. Markdown is not that easy for many non-techie people and there is no content validation or anything like that. The solution is a headless CMS.
A headless CMS, wtf?
A headless CMS is simply a decoupled system. That means you can query contents via an API like REST or GraphQL. And that in turn means you can use almost any frontend framework and even spread your whole frontend via a CDN and still access the same content. You can also query the same data from a website and a smartphone app at the same time. Do some research and you will see there is a booming market on headless CMSs and that for good reason.
Preparing our contents on DatoCMS
This should not be a detailed tutorial on how to use DatoCMS, because they have an excellent documentation on that, but let’s go through it quickly. If you log in to your dashboard you will see the admin panel is divided into Content, Media and Settings. Go to Settings > Models, create a new model “Post”.
Next we need fields to manage our content. Let’s add them.
In this case we will add a title (single line string), text (multi line string) and a slug (single line string).
Next head over to the API explorer of DatoCMS (which uses GraphiQL). Paste your read only API token and there you go. If you dont know GraphiQL you can simply start by typing curly brackets and then pressing
CTRL+Space to get auto complete suggestions for the fields you can query from the database.
What we need here is “allPosts” and “post”. But I will show you the exact queries later. If you choose
allPosts for now and enter our fields you will see something like this.
allPosts shows and empty array. Why is that? Simple because we didn’t create any post! To fix that go to the “Content” tab in your admin panel and create a new post.
Make sure to save your post! Then go back to the API explorer and hit
CTRL+Enter to refresh your query. Now you will see your first post!
Getting the content into your static files
Next question: How to receive the content from DatoCMS and using it in our NuxtJS application? We need Apollo to query a GraphQL API! Fortunately there is also a NuxtJS plugin for apollo. To install this module you first need to add it to your project with
npm install --save @nuxtjs/apollo . Next we have to register the plugin in our
and then configure it (in the same file):
getAuth: () => 'Bearer XXXXXXXXXXXXXXXX'
Important: You must replace XXXXXXXXXXXXXXXX with the API key from DatoCMS. You can get it under Settings > Site Settings > API Tokens.
Running queries on a page
Alright! Everything is installed and we still don’t have any content in our page. Let’s create two files in our
pages/blog directory. The first one will be the
index.vue which will list all blog posts that we have and the second will be called
_slug.vue and is responsible for a single blog posts detail page. The
index.vue will look something like this:
Let’s quickly go through it:
apollo will be configured as a property in our
VueComponent . We are fetching all posts with the
graphql-tag query syntax and for each post we are requesting the fields
slug . We will need the slug to navigate to a single blog post.
Now let’s have a look at a blog post detail page, which is a big more complex, because we need to find the right blog post in our database.
Do you see the difference? Our apollo property is now split into a
query , a
prefetch and a
variables property. In the
query we define the
$slug as a variable to pass into the
filter parameter. This
$slug comes from the
variables (client side) and
prefetch (server side, when generating the files). Those methods get the
slug from our router parameters. If this is too much magic for you, have a look at the router documentation of NuxtJS.
Deploying our new content automatically
So the next thing you might think “And now I need to run
nuxt generate every time I updated content and upload the files to my server again and again. Well, you could do that of course, but I recommend to setup a Continuous Deployment Pipeline to do that automatically. It’s not that easy to do so but with DatoCMS you have a Netlify integration built-in.
Do you see the little button “build site” on the top right? Press this when you are done editing your contents and your website will be automatically rebuilt on Netlify. Besides that your website will be generated again on each commit you push to a specific branch!
It’s not possible to send mails from a static website
Not true! It’s possible! You can use a serverless computing plattform like AWS Lambda. Fortunately this is already built-in with Netlify Functions. See my next article:
How to submit forms on a static website with VueJS and Netlify functions
I have already shared my setup to develop static websites with VueJS, DatoCMS and GraphQL. I recommend you read this…
That’s it, any questions?
Let me know in the comments! Don’t forget to clap if this was helpful to you!