How to use the WordPress REST API with Nuxt 3 and Tailwind CSS
WordPress is a great for building websites (breaking news). However, in my opinion, it isn’t the most enjoyable experience when it comes to theme and plugin development. But now we have the WordPress REST API available to use, that has all changed! The WordPress REST API allows us to use WordPress as a content management system only, and use our own frontend to display our WordPress content. This makes development much more enjoyable as we can use Javascript frameworks, such as Nuxt.js, to display our content! In this guide we will do just that. Create a WordPress REST API by installing WordPress with a Headless theme. Then create a Nuxt 3 project to pull in our data from the WordPress API. Then style our Nuxt 3 components using Tailwind CSS. It’s going to be a lovely experience.
Create Headless WordPress theme
If you haven’t already, create a new WordPress installation. I am doing this on a live server using Hostinger but you are free to do this on localhost and will get the same result. Once your WordPress installation is ready, we can build our headless theme. I am going to FTP into my website as I am doing it on a live server. If you are on localhost, open your installation in your development environment and go to the themes directory.
We need to create the directory for our new theme. So create a directory called ‘headless_theme’.
Files required for the Headless WordPress theme
In your newly created ‘headless_theme’ directory, create the following files: index.php, functions.php and style.css. Include the following in each file.
index.php
<!-- index.php -->
<script type="text/javascript">
window.location = 'https://front.websitegoblin.com';
</script>
functions.php
<?php
if (!defined('ABSPATH')) {
exit;
} // Exit if accessed directly
// Remove p tags from content
remove_filter('the_content', 'wpautop');
style.css
/*
Theme Name: Headless
Author: John
Author URI: https://codingoblin.com
Description: headless theme for using WP as a REST API only
Version: 1.0.0
*/
Settings and plugins
To avoid headaches down the line, you need to sort out your permalinks settings. Go to ‘permalinks’ in the WordPress settings menu and select the ‘Post name’ option. Remember to save the changes. I would now recommend installing the ‘Classic Editor’ plugin. This makes life a lot easier.
Test the WordPress REST API endpoint
We are now at a point where we can test our WordPress API by hitting an endpoint. To do this, go to
Nuxt 3 project setup
The next thing we need to do is get a new Nuxt 3 project setup.
Install Nuxt 3 Project
Instructions for this can be seen on the Nuxt docs.
Install Tailwind CSS
We now want to install Tailwind CSS. The guide to do this can be seen at the Tailwind CSS docs.
Install Tailwind UI dependencies (optional)
If you are using Tailwind UI, remember to install the relevant dependencies. These can be seen in the Tailwind UI docs.
Sort out our Nuxt 3 project
At this point we have everything we need installed. We just need to make a few adjustments to out Nuxt 3 project before we get going. We want to make it so that we can use layouts, pages and components. Start by heading to your app.vue file and make the following changes:
<template>
<div>
<NuxtWelcome />
</div>
<NuxtLayout>
<NuxtPage/>
</NuxtLayout>
</template>
Now you want to create the following directories in the root of your project: ‘layouts’, ‘pages’ and ‘components’.
In your newly created ‘layouts’ directory, create a ‘default.vue’ file, paste in the following:
<template>
<div>
<slot />
</div>
</template>
Fetch data from WordPress API using Nuxt 3
Right, we are getting there! We are now ready to fetch some data from our WordPress API from within out Nuxt 3 project. In your newly created ‘pages’ directory create a file called ‘[…slug.vue]’. This file name looks a bit weird but it will all make sense. Paste the following code into your […slug.vue] file:
<script setup>
import { ref } from 'vue'
const route = useRoute()
const slug = ref('')
if(route.params.slug) {
let lastIndex = route.params.slug.length - 1
if(!route.params.slug[lastIndex]) {
slug.value = route.params.slug[lastIndex - 1]
} else {
slug.value = route.params.slug[lastIndex]
}
} else {
slug.value = 'home'
}
const { data, pending, error, refresh } = await useFetch('https://<yout-website>/wp-json/wp/v2/pages', {
query: { slug: slug.value }
})
</script>
<template>
<div>
<Header :title="data[0].title.rendered" :subtitle="data[0].content.rendered" />
</div>
</template>
What is happening in the […slug.vue] file
There are a couple of bits going on here, so let’s take a look in closer detail.
Unusual file name – Nuxt 3 Catch all route
The first thing that may look strange to you is the file name itself. This allows us to use a ‘catch-all route’, which you can read about here on the Nuxt website. You will also see that we have a ‘route’ const that is assigned to ‘useRoute()’. This object contains all the data for the current route. Importantly it contains a params property. This params property will contain an array with all params in the route. For example, the path ‘
Assigning the params to a const
You can see that we assign the last param in the params array to our ‘slug’ const. This allows us to then use this value as a query param to fetch data from the specific page that we want. If there are no param, we set the slug’s value to ‘home’. This is so we fetch the home page data from our API like what would happen if we visited the route path for a normal WordPress website.
The useFetch function
The useFetch function is then used to query out WordPress API endpoint. The ‘query’ object allows us to get the data from the specific page that we want by entering using the slug for that page.
Create a component
We now want to pass the data object, that we have fetched from our WordPress API, to a component. So we need to create a component. In your components directory (which we created earlier), create a new component called ‘Header.vue’. In this new Header.vue component, paste in the following:
I have videos too!
If you found this post helpful, please consider subscribing to the @codingoblin YouTube channel 😀
<template>
<div>
<div>
<h2>{{ title }}</h2>
<p>{{ subtitle }}</p>
</div>
</div>
</template>
<script setup>
const props = defineProps({
title: String
subtitle: String
})
</script>
I am using a pre-built Header component from Tailwind UI so am unable to show the classes as they are paid for. However you are free to use any Tailwind CSS classes that you like to style this component.
Testing your project
Everything should now be working. If you visit ‘