Review of Wordpress and Vue.Js: Router Edition

Headless WordPress, or Head-ish WordPress?

I tried explaining a WordPress Theme’s code to a non-nerd (yeah, the girlfriend). Analogies I tried: A blended smoothie, minestrone soup, and a zombie. Zombies won. Here goes:

Wordpress has 2 parts: life & death blended together. It’s a zombie, kinda slow, and not very smart, not very clean. Chaos, really.

Lately, all the cool kids are separating life & death, as they should be. No more zombies: Just the Living (React/Angular/Vue) and Dead (Wordpress REST API data).

“Headless” is trending.

Headless WordPress is a lot of work. Tossing in the site navigation? Better recheck routing. Added a plugin? You might have to rewrite the whole thing. You basically have to recreate the list of Template Tags with API equivalents. Most of your time will be spent developing in Javascript what WordPress already does out of the box.

Pantheon has a great summary: there are more than 2 options out there.

I’ll be running with Pantheon’s “Hybrid” approach. I’m still using WordPress to build each URI as it normally would. This is of course unnecessary outside of robot crawlers. My goal is to have a reasonable overlap where any URI in Vue is also able to be handled by WordPress. Consider it a paranoid approach, with WordPress as a catch-all.

Eventually, Vue will perhaps eclipse the WordPress theme, completing the full SPA approach. For now, I need the security of providing functionality of large-scale plugins like WooCommerce and Event Ticketing.


Wordpress has its own internal routing. If you’ve been more than knee-deep in Wordpress it’s easily missed, so here are a few reminders:

  • The .htaccess file: There is only an index.php file. Everything else is virtual.
  • Permalink Structure: Using get_the_permalink($post->ID) instead of manually typing a link.

Wordpress’ Rewrite API basically covers everything in the Template Hierarchy:

The Wordpress Template Hierarchy

Post-Types: Posts, Pages, Attachments, etc

Archives: Author, Date, Taxonomy-Terms

One-Offs: Search, 404, Front-Page.

So what does VueRouter Cover?

Initially, not much. VueRouter has a <router-link> tag equivalent to get_permalink().

But to use that tag, you’ll have to add in every URI path format yourself. Most Vue-WordPress themes get pretty stingy when it comes to URI paths. Your router implementation starts looking like this from Michael Soriano, at best:

But this is using a non-standard URI prefix for posts and pages, and other implementations use too many IDs instead of slugs. These “pretty permalinks” are much more common and SEOy:


The only automated approach I saw stuck to listing out all posts and pages. Valiant effort by Gilbert Pellegrom for a simple, first-round kick-off 2 years ago.

But what about Categories? Custom Taxonomies? ..and what if I install a plugin for events or galleries? Those will use more custom taxonomies and post types. I’m not going to manually enter in each.

Enter: A Drop-in WordPress-Vue Route Builder.

Believe it or not, I’d actually came up with a similar approach as Mr. Pellegrom by the time I came across his code. I had already coded up over half of the WordPress Rewrites, so I’m starting with his simple theme (updated for Vue2) as a demo.

The fundamental approach lies in rolling out what is known (category slugs, parent pages, etc). Otherwise, “Category” could be confused as a parent-page, and a parent-page could be a taxonomy, or term!

Routes created using the Theme Unit Test. Still fast with over 300 routes!

The only truly “manual” entries are the WordPress default paths for Search, Author, and Date Archives. I lifted those straight from a WP Rewrites dump.


  1. The only routes you need to mod are your own custom ones.
  2. Supports common Component Names: Page, Blog, Home, Archive, Post, Search, Author, ArchiveDate. What you attach to these is up to you.
  3. Pulls in Page Template names as Component Names for the page using it.

Resolvable URIs

Archive by Date:
Single Post:


High Level

Have a WordPress Install? Know NPM? Give a go!

Medium Level

If you’ve got your own WP Theme using Vue, basically, just toss in the vue-router.php file, and check the integrations:

PHP: functions.php

$wp_vue= new WP_Vue_Router_Context();wp_localize_script( 'rest-theme-vue', 'wp', 
'root' => esc_url_raw( rest_url() ),
'base_url' => $base_url,
'components'=> $wp_vue->get_components(),
'routes' => $wp_vue->get_routes(),

JS: rest-theme/src/main.js

var router = new VueRouter({  mode: 'history'});for (var key in wp.routes) {    
var route = wp.routes[key];
router.addRoutes([ {
path: wp.base_path + route.slug,
component: Vue.component(capitalize(route.type)),
props: {default: true, postId:}

Closing Thoughts

I’m not yet sure whether I just created a crutch, or laid down a first paving-stone. Either way, I plan to extend this basic theme into something I can use for client sites with lots of plugins, as well as building it out to handle caching, etc like Bill Stavroulakis PWA site.

If you’ve got routing problems on your present WP Theme using Vue, I’d love to hear your issues.

Next Steps

There are a handful of routes that are still missing. I declined to handle Post-Attachments and Comment-Paging, since they are often handled in other ways. I also will defer to WordPress for per-category RSS feed handling.

  • Right now, I’m pulling a list of Components; I’d like to feed it a list of registered Vue Components, instead of unsetting and re-adding.
  • Options for which object-types, or categories.
  • I’ve yet to test this with various plugins.

Pull Requests are now open!

(Front|Back|Web) × (Developer|Ops) @WierStewart

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store