Table of contents

WordPress API Nav Menu

How to get nav menu items into Nuxt 3 through the WordPress REST API

WordPress API Nav Menu

How to get nav menu items into Nuxt 3 through the WordPress REST API. This can seem difficult at first. But trust me, once you know what you are doing it will all make perfect sense.

Add menu theme support

Check if we can create menus

The first thing we need to do is make sure that we have the ability to create menus in our WordPress backend. Hover over the “Appearances” menu item in the left hand sidebar. A sub menu will appear. If you do not see the “Menus” option in the sub menu, you will need to enable theme support for them. If you do see the “Menus” option skip to the Create a menu part.

No menu item visible in submenu
No menu item visible in submenu

Enable theme support for WP menu

To enable theme support for menus, we need to edit the functions.php file in our theme. Open the functions.php file and add the following code:

<?php
if (!defined('ABSPATH')) {
    exit;
} // Exit if accessed directly
// other stuff
// add menu support
add_theme_support( 'menus' );

Save your functions.php file. Now hover over the “Appearances” menu item again and you should see the “Menus” option in the submenu!

Menu item now present in submenu
Menu item now present in submenu

Create a WordPress menu

We are now at a point where we can create a menu. So click on the “Menus” option. Give your menu a name then click the Create Menu button. It is important that we remember the name of this menu as we are going to use it to reference the menu later. Add some items to the menu and save the menu. I am adding the home and about pages to my menu and naming it ‘top-nav’.

Top nav menu creation in WordPress
Top nav menu creation in WordPress

Create WordPress API endpoint for nav menu

We now need to create an API endpoint for our WordPress nav menu. This is so we can retrieve the items from the menu via the WordPress API. Head back to your theme’s functions.php file. Add the following code:

<?php
if (!defined('ABSPATH')) {
    exit;
} // Exit if accessed directly
// other stuff
// add menu support
add_theme_support( 'menus' );
// Return formatted top-nav menu
function top_nav_menu() {
    $menu = wp_get_nav_menu_items('top-nav');
    $result = [];
    foreach($menu as $item) {
        $my_item = [
            'name' => $item->title,
            'href' => $item->url
        ];
        $result[] = $my_item;
    }
    return $result;
}
// add endpoint
add_action( 'rest_api_init', function() {
    // top-nav menu
    register_rest_route( 'wp/v2', 'top-nav', array(
        'methods' => 'GET',
        'callback' => 'top_nav_menu',
    ) );
});

Let’s take a look at the code we just added to our functions.php file.

WP rest_api_init action hook

we can see that we hook into the rest_api_init action. When the rest_api_init action runs, it executes the callback function defined within. This callback function then calls the register_rest_route function which registers a new endpoint in our WordPress API. You will see we pass 3 parameters to the register_rest_route function:

  1. $route_namespace (string)

    This is the first URL segment after core prefix. In our case it is ‘wp/v2’.

  2. $route (string)

    This is the base URL for route. In our case it is ‘top-nav’. This can be named anything you want. But it makes sense to use something related to the previously created nav menu.

  3. $args (array)

    This is an array of options for our endpoint. In our example we have set the method to ‘GET’ and the callback to ‘top_nav_menu’. This means that when we hit our endpoint we will execute top_nav_menu().

Structure menu items with register_rest_route callback function (top_nav_menu())

We have also created a top_nav_menu function. This function runs when we hit our endpoint! If we take a look at this function we will see that it fetches our nav menu using wp_get_nav_menu_items. This is where we pass the name of our nav menu that we created earlier. We then loop over each menu item, adding only the properties that we want to return. We are only interested in the title and url of each menu item. I have assigned these to a ‘name’ and ‘href’ property in an array on each iteration, which are then pushed to a $results array. Finally the $results array is returned.

Set Site Address (URL) in WordPress

We now need to set the site address (url). Go to ‘General’ settings in WordPress. We need to set ‘Site Address (URL)’ to the location of our frontend. In this case it will be the location of our Nuxt.js application. This is currently http://localhost:3000 if you are on localhost. Or if not, it will be whatever the address of your frontend is.

Set site address (url) in WordPress
Set site address (url) in WordPress

If we forget to do this our url’s from the menu items will point to our WordPress backend, which will break everything! Double check if your frontend is http or https. In my case I am using http for localhost:3000 (http://localhost:3000). Make sure you click Save Changes.

Create nav menu component in Nuxt 3

We are nearly there! Now we need to create our nav menu component in our Nuxt 3 application. You can style this how you like, but make sure you have the following code in your component:

<template>
    <div>
      <a v-for="item in navigation" :key="item.name" :href="item.href" :aria-current="item.href === current ? 'page' : undefined">{{ item.name }}</a>
    </div>
</template>
<script setup>
const route = useRoute()
// Replace 'http://localhost:3000' with your frontend location
const current = 'http://localhost:3000' + route.fullPath
// IMPORTANT
// If your frontend is http then use http
// in your useFetch endpoint
// If it is https then use https 
// Replace 'http://wp.websitegoblin.com' with your backend location
const { data: navigation, pending, error, refresh } = await useFetch('http://wp.websitegoblin.com/wp-json/wp/v2/top-nav');
</script>

Fetch WordPress menu API data with useFetch()

In our nuxt.js nav component we use the useFetch() nuxt.js function to fetch our WordPress menu items from our custom endpoint. We then loop over the array that is returned and create our nav links using the data from our WordPress menu.

Http / Https gotcha!

If your frontend is using http, you must also fetch data from your endpoint using http. Even if your WordPress Address (URL) is https. For example: I am using https://wp.websitegoblin.com for my backend (notice it is https). I am using http://localhost:3000 for my frontend (http). This is how I would have my useFetch function:

// Using http eventhough backend is https
const { data: navigation, pending, error, refresh } = await useFetch('http://wp.websitegoblin.com/wp-json/wp/v2/top-nav');

Check you fetch request. If your frontend is HTTP you must make your fetch request to HTTP even if your backend is HTTPS

If you get this wrong your url’s will point to the wrong pages. Basically whatever you use in the endpoint fetch request (http or https) is what will be used in the url’s that are returned from the WordPress API.

So there you have it. That is how you create a nav menu in WordPress and pull it into Nuxt 3 using the WordPress REST API!

John

I have videos too!

If you found this post helpful, please consider subscribing to the @codingoblin YouTube channel 😀

Super fast hosting
for your WP API & Nuxt 3 website

Host your backend WP API and frontend Nuxt 3 app on Cloudways. They make it so easy, even Grandma could deploy a website!

Cloudways screenshot

Want updates when I release something interesting?

Sign up for my newsletter to stay up to date.