Headless WordPress with Vue.js and Nuxt

Contents

Headless WordPress with Vue.js and Nuxt.js: An In-Depth Guide

In modern web development, decoupling the front end from the back end has emerged as a best practice for performance, flexibility and future-proofing. Headless WordPress paired with Vue.js and Nuxt.js offers a powerful stack: WordPress as a content management system (CMS) serving content over an API, and Vue/Nuxt as a fast, SEO-friendly front-end framework.

Table of Contents

  • What Is Headless WordPress
  • Benefits of a Headless Architecture
  • Choosing the Right API: REST vs GraphQL
  • Introduction to Vue.js and Nuxt.js
  • Step-by-Step Setup
    • 1. Preparing WordPress
    • 2. Installing WPGraphQL or using REST
    • 3. Configuring CORS and Authentication
    • 4. Creating Custom Post Types and Fields
  • Building the Nuxt.js Front End
  • Dynamic Routes Data Fetching
  • Performance, Caching SEO
  • Deployment Strategies
  • Best Practices Security Considerations
  • Conclusion

1. What Is Headless WordPress

Traditional WordPress couples content management with theming and rendering in PHP. A headless approach strips away the front-end rendering, exposing content via an API. Developers can then consume this content in any environment—single-page applications (SPAs), static sites or mobile apps.

2. Benefits of a Headless Architecture

  • Performance: Static generation or server-side rendering (SSR) provides faster load times.
  • Scalability: Decoupled services scale independently.
  • Security: Reduces attack surface by isolating WordPress to only content delivery.
  • Flexibility: Any front-end technology (Vue, React, Angular) can be used.
  • Developer Experience: Modern toolchains, hot reloading and component-based architectures.

3. Choosing the Right API: REST vs GraphQL

WordPress provides a built-in REST API. For more flexible queries, WPGraphQL offers GraphQL endpoints.

Feature REST API GraphQL
Data Fetch Granularity Fixed endpoints, potential over-fetching Exact fields, minimal payloads
Learning Curve Low (standard REST) Medium (GraphQL schema)
Extensibility Custom endpoints/plugins Schema stitching, custom resolvers

4. Introduction to Vue.js and Nuxt.js

Vue.js (vuejs.org) is a progressive JavaScript framework for building user interfaces. Nuxt.js (nuxtjs.org) builds on Vue to provide:

  • Server-Side Rendering (SSR) for SEO and performance
  • Static Site Generation (SSG) with nuxt generate
  • Automatic routing, code-splitting, and powerful module ecosystem

5. Step-by-Step Setup

5.1 Preparing WordPress

  1. Deploy WordPress on any PHP hosting or WordPress.com Business Plan.
  2. Ensure Permalinks are set to /post-name/ for clean URLs.

5.2 Installing WPGraphQL (Preferred)

  • In WP Admin, navigate to Plugins gt Add New.
  • Search for WPGraphQL and install from WordPress.org.
  • Activate and verify http://your-site.com/graphql returns the GraphQL Playground.

5.3 Configuring CORS Authentication

Add the following in your theme’s functions.php:

add_action(init, function() {
nbspnbsp header(Access-Control-Allow-Origin: )
nbspnbsp header(Access-Control-Allow-Methods: GET, POST, OPTIONS)
})

For authenticated requests (create/update content), use JWT Authentication (plugin).

5.4 Creating Custom Post Types Fields

  • Use Custom Post Type UI (plugin).
  • Use Advanced Custom Fields (ACF) to define custom meta fields.

6. Building the Nuxt.js Front End

  1. Initialize a new Nuxt project:
    npx create-nuxt-app headless-wp-vue
  2. Choose features: Axios, Vuex, ESLint.
  3. Install Apollo module for GraphQL (if using WPGraphQL):
    npm install @nuxtjs/apollo –save
  4. Configure nuxt.config.js:
  5. modules: [
    nbspnbsp@nuxtjs/axios,
    nbspnbsp@nuxtjs/apollo
    ],
    apollo: {
    nbspnbspclientConfigs: {
    nbspnbspnbspnbspdefault: {
    nbspnbspnbspnbspnbspnbsphttpEndpoint: https://your-wordpress-site.com/graphql
    nbspnbspnbspnbsp}
    nbspnbsp}
    }

7. Dynamic Routes Data Fetching

Use Nuxt’s asyncData or fetch to grab content at build time or on server render. For example, pages/posts/_slug.vue: