← Back

Creating a Nuxt 3 Website with Headless WordPress

I've used Nuxt 3 with Storyblok and searched for a more flexible alternative. Since also it can get expensive and my customers prefer to use WordPress as a backend. It's easy to setup a Nuxt 3 project and connect it to a WordPress backend. We will do it with GraphQL for a few extras like TypeScript typing, but it can be done even more easily with the REST API WordPress provides out of the box.

Nuxt 3 Logo with green elements

From thecodest.co

Let's get started!

How? So basically, we will enable a GraphQL API that queries all the WordPress Data. We will use Vercel to host a Nuxt Page. So the “old” frontend the WordPress page is shipping can just be disabled.

Setup WordPress

First off, we need any kind of WordPress installation on a server. You can install it on your own or just create an account on those WaaS platforms, where you get everything for a few $s a month.

First, install those plugins:

WP GraphQL

Used to generate a GraphQL API endpoint and to have a Playground where you can try it out.

WP GraphQL Gutenberg

Used to generate additional endpoints to make the GraphQL API work well with Gutenberg. You get JSON data from Gutenberg blocks instead of the rendered WordPress HTML.

Do read the quick start of the GraphQL Plugin to get an idea of what it is and what you need to configure (not much!)

Setup Authentication

To query all fields and the schema, you have to first setup an Application Password. This will ensure that the password you use is only used for your nuxt app.

Your token will be in the format Basic XXXXX.

You can generate it with this token generator, it is basically only your username + the new application password combined as a base64 string. Remember this token somewhere for later.

(Optional) – Issues with Wordpress Authentication?

On some hosters (those who serve PHP as CGI), you have to do additional configuration for the Authorization header. Try out if it works without.

When not, continue:
Add a wp-content/plugins/auth-fix/index.php into the WordPress Server and add this:

<?php
	/*
	Plugin Name: Auth Fix
	Description: Fixes `MISSING_AUTHORIZATION_HEADER`: https://github.com/WordPress/application-passwords/issues/95#issuecomment-571586359
	Version: 1.0.0
	*/
	add_filter('application_password_is_api_request', function ($api_request) {
		if (empty($api_request)) {
			return strpos($_SERVER['REQUEST_URI'], '/wp-json/') !== false;
		}
		return $api_request;
	}, 10, 1);

Now activate the plugin in your UI and you are ready to go. You now have enabled secure access to the GraphQL Schema API.

Setup Nuxt

To get started quickly, create a new nuxt project with the getting started guide in the official Nuxt Docs. I'll wait here, I promise. Nuxt is great, so it won't take more than 2 mins.

What do we need?

After that, we need a library to do the GraphQL querying and maybe type generation for us. Let’s use nuxt-graphql-client for it. But could be any other.

This is how your nuxt.config.ts should look like:

export default defineNuxtConfig({
	typescript: {
		shim: false,
	},
	modules: ['nuxt-graphql-client'],
})

You'll have to create a .env file in your project root:

GQL_HOST="https://your-wordpress-instance.com/graphql"
GQL_TOKEN="Basic xxx"

Everything else is fully automatic with this package. You are now querying your GraphQL endpoint as an authenticated user.

Your first query

Now basically you're already done with the basics! You can try to query your data.

Create a gql query file, e.g. queries/posts.gql

query Posts {
	posts {
		nodes {
			id
			title
			date
			slug
			excerpt(format: RAW)
		}
	}
}

Everything will be automatically generated, so you can just create a new page, e.g. pages/index.vue:

<template>
	<div class="container">
		<h1 class="text-4xl">Welcome to your page!</h1>
		<div v-if="data">
			<pre>{{ data }}</pre>
		</div>
	</div>
</template>

<script lang="ts" setup>
	const { data } = await useAsyncGql({
		operation: 'Posts',
	})
</script>

And voilá, you have a list of your WordPress posts in Nuxt. Awesome! 🎉

Next Steps

Now, you can investigate in further what you are trying to build.

Since the goal is to have a headless experience, you may have seen that the content you get from WordPress (the content data entry) is basically a long html string. When you are using Gutenberg as editor, you may have recognized that it uses blocks for content. Which is exactly what we need to render our own components for headlines, sections, etc.

This is where the WP GraphQL Gutenberg plugin we already installed comes in.

This allows you to write queries like:

query SinglePostBySlug($slug: String!) {
	postBy(slug: $slug) {
		id
		title
		blocks {
			attributesJSON
			name
			innerBlocks {
				attributesJSON
				name
				innerBlocks {
					attributesJSON
					name
					innerBlocks {
						attributesJSON
						name
						innerBlocks {
							attributesJSON
							name
						}
					}
				}
			}
		}
		date
		slug
		excerpt(format: RAW)
	}
}

You now have your Gutenberg Blocks as a JSON schema, just like you would expect it from a real headless CMS. Nice!

From now on, what I did is created small richtext resolver components to display and loop through this JSON. Since this part is highly optionated and I only implemented what I need, the best is if you do the same.

Conclusion

It's actually easier than I thought to use WordPress as a Headless CMS. I am planning on building a Batteries Included Nuxt Layer to easily get started with WordPress Headless. In the meantime, some things that would be needed to be implemented:

  • Render the Gutenberg Blocks as Richtext Elements

  • Optimizing the images coming from WordPress with nuxt/image

  • Rendering both pages and posts (+ custom types) as nuxt pages.

  • Creating a sitemap

  • Add custom menus and query/render them.

  • Add SEO Meta tags (image, twitter, ...)

See also

  • You can install fuxt-backend, which is a theme to disable the regular website and enables some features like menus. Perfect for our usecase. fuxt is a nuxt 2 frontend for headless WordPress.

Questions, Issues, Suggestions?

If you need more help or have any questions, I can offer you a consulting session where we go through your code, analyze issues or build new features. Or do you need some custom Vue/Nuxt plugins, composables or modules specifically for your project? Feel free to contact me for more details, I would love to help you build great Nuxt applications.