Off With Its Head!
(Using WordPress as a headless CMS)
-
Treighton (@treighton1988)
-
Web Developer @ Page Design
-
3 years as a Developer
What I'm going to talk about
- What does Headless Mean?
- Why PDG decided to go Headless
- Let me show you how we did it!
- What we learned from losing our heads
What does headless Mean?
Typically a traditional database driven CMS with UI for adding content
Content is accessible through a web API
The front end of the site uses JS to fetch the data from the API, and renders it into a UI
Headless vs Monolith
Monolithic
Headless vs Monolith
Decoupled (Headless)
But why complicate things?
Future Proofing
Speed
Cross Platform Publishing
Developer Flexibility
Easier CI/CD
Losing our heads
The Original Stack
LAMP Stack Server => Web Server & Database
WordPress => CMS, Admin Console
Timber => Twig Templating engine for WordPress
Vanilla ES6, LESS, Babel, Webpack, Gulp =>
Frontend
So What's the Problem?
A lot of bloated AJAX calls on a single page
Fighting with / Working around the default templates
But in the end it all came together, and it works, but it's less than ideal
How do we fix it?
WP REST API
React + Next.js Frontend
Super sweet design
What We are Building
Some Code...
{
"id": 10,
"date": "2017-05-26T22:30:56",
"date_gmt": "2017-05-26T22:30:56",
"guid": {
"rendered": "http://pagedev.dev/headers-post/"
},
"modified": "2017-05-26T22:30:56",
"modified_gmt": "2017-05-26T22:30:56",
"slug": "headers-post",
"status": "publish",
"type": "post",
"link": "http://pagedev.dev/headers-post/",
"title": {
"rendered": "Headers Post"
},
"content": {
"rendered": "<h1>This Is An H1 Tag</h1>\n<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>\n<h2>This Is An H2 Tag</h2>\n<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>\n<h3>This Is An H3 Tag</h3>\n<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>\n<h4>This Is An H4 Tag</h4>\n<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>\n<h5>This Is An H5 Tag</h5>\n<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>\n",
"protected": false
},
"excerpt": {
"rendered": "<p>This Is An H1 Tag Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. This Is An H2 Tag Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed … </p>\n<p class=\"link-more\"><a href=\"http://pagedev.dev/headers-post/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> “Headers Post”</span></a></p>\n",
"protected": false
},
"author": 1,
"featured_media": 0,
"comment_status": "open",
"ping_status": "open",
"sticky": false,
"template": "",
"format": "standard",
"meta": [],
"categories": [
1
],
"tags": [],
"_links": {}
},
https://(domain)/wp-json/wp/v2/posts
WordCamp Plug
I'll see ya there!
Some More Code...
import React from 'react'
import Layout from '../components/Layout'
import Articles from '../components/Articles'
import fetch from 'isomorphic-unfetch'
const Index = (props) => {
return (
<Layout>
<Articles posts={props.posts} />
</Layout>
)
}
Index.getInitialProps = async function() {
const res = await fetch('http://pagedev.dev/wp-json/wp/v2/posts')
const data = await res.json()
console.log(data)
return {
posts: data
}
};
export default Index
Layout, Fetching JSON, and passing to Components
Even More Code...
import React from 'react'
import Article from './Article'
class Articles extends React.Component {
render() {
return(
<div>
<ul id="ideas" className="blocks">
{this.props.posts.map((post) => (
<Article key={post.id} id={post.id}
linkMask={`/p/${post.id}`}
link={`/post?title=${post.title.rendered}`}
title={post.title.rendered}
excpt={post.excerpt.rendered}
/>
))}
</ul>
</div>
)
}
}
export default Articles
The `Articles` Compontent
Seen Enough Code...?
import React from 'react'
import Link from 'next/link'
class Article extends React.Component {
render(){
return(
<div>
<li id={this.props.id} className="article">
<Link as={this.props.linkMask} href={this.props.link}>
<a className="block">
<span className="eyebrow"><b>{this.props.cat}</b> / Technology </span>
<h4>{this.props.title}</h4>
<p>{this.props.excpt}</p>
</a>
</Link>
</li>
</div>
)
}
}
export default Article
The `Article` Compontent
Ok, this is the last of it...
import Layout from '../components/Layout.js'
import Hero from '../components/Hero'
import fetch from 'isomorphic-unfetch'
const Post = (props) => (
<Layout>
<Hero title={props.post.title.rendered} />
<div dangerouslySetInnerHTML={ {__html: props.post.content.rendered} } />
</Layout>
)
Post.getInitialProps = async function(context) {
const { id } = context.query
const res = await fetch(`http://pagedev.dev/wp-json/wp/v2/posts/${id}`)
const data = await res.json()
console.log(data)
return {
post: data
}
}
export default Post
The Post Component / page
Lessons Learned
There are countless frontend options
Customizing REST endpoints
Decoupled CMS is a major paradigm switch
In Closing
WordCamp Sacramento 2017 - Off With It’s Head: Using WordPress As A Decoupled CMS For A Single Page Application
By Treighton Mauldin
WordCamp Sacramento 2017 - Off With It’s Head: Using WordPress As A Decoupled CMS For A Single Page Application
This talk will go into detail about when, why and how to use WordPress as a decoupled CMS backend with a React / Node frontend. This talk is equal parts tutorial, existential dive into when it is appropriate to use modern web application architecture, and lessons learned from my journey building a React SPA with a WordPress backend.
- 1,183