high voltage - building static sites with wordpress-managed content
TRANSCRIPT
Further separation of concerns
• Users enter content using a GUI
• Programmers create templates that utilize the user-entered content
• Web pages generated on demand
It’s not
• With (pretty much) any CMS:
• Wrangling together templates and data is complicated
• The process is demanding and involves needless work
“The stack” stacks up
HTTP Accelerator (Varnish)
Web Server (Apache)
Application Server (WordPress/PHP)
Database (MySQL)Object Cache (MemCached) File System
Build a solution
• We have the tools:
• Static site generators
• Rapid application frameworks
• APIs
• CMSs / Writing rooms
Why static sites• Fast
• Secure
• Scalable
• Simple themes and integrations
• Own conventions, languages, and tools
• Excellent version control story
The generators help!
Build
HTML
JS SVGCSS
GIF JPGPNG
Source
HTML
COFFEE SVG
TWIG ERB
SCSS
GIF JPGPNG
JSON YAML MD
Productivity, performance, security, scalability paid for with slow resource intensive build
processes
More hosting options open up• Shared hosting
• VPS
• GitHub Pages (https://pages.github.com/)
• Dropbox (https://pages.github.com/)
• Google Drive (https://www.google.com/drive/)
• Amazon S3 (http://aws.amazon.com/s3/)
There are drawbacks
• Particularly with the concept of keeping content in flat files
• Hard to contribute (knowledge of Git)
• Hard to collaborate
Writing rooms to the rescue
• Contentful (https://www.contentful.com/)
• Prismic.io (https://www.prismic.io/)
• Pull in data through the API into a static build process
However…
• Subscription services
• Potential for vendor lock-in
• Lack of mature, open source alternatives
WordPress as a pure CMS
• WordPress can be used as an alternative to writing rooms like Prismic.io and Contentful
• Content authors use WordPress to manage content and collaborate; not to build web sites
• Content pulled out of WordPress and injected into static build process
WP REST API
• Popular plugin that will be integrated into core
• Provides an HTTP REST API
• Extensive API for CRUD operations on comments, media, meta data, posts, taxonomies, and users
• http://wp-api.org
Advanced Custom Fields Pro
• Popular plugin that allows for rapid creation of custom fields
• Supports many field types, including text, number, image, map, links, and post references
• Rich ecosystem of extensions including repeaters
• http://www.advancedcustomfields.com
WP REST API Custom Fields
• Adds custom fields defined with ACF Pro to JSON output
• Inserts an object into the meta key with all your fields
• http://wordpress.org/plugins/wp-rest-api-custom-fields
Putting the backend together• A 15-minute REST server with multi-user support, roles and
permissions, and an admin interface
1. Enable the aforementioned plugins
2. Setup friendly permalinks
3. Create custom post types if necessary
4. Setup custom fields if necessary
5. API accessible at /wp-json
Choosing a static site generator
• Comes in pretty much any language: C, C++, Java, Go, Haskell, Erlang, JavaScript, Ruby, Python, PHP, etc.
• Choose a language you a comfortable with and enjoy working with
• Choose a system that is mature
• Choose a system that lets you work with many different types of inputs, including remote content for maximum flexibility
Key Features• HTML, Markdown, YAML, and JSON format
• Templating language
• Asset pipeline
• Live reload
• Development server
• Common preprocessors and concat/minify out of the box
Useful Extensions
• Deploy
• Blog
• Pagination
• SVG Fallback
• Full list: https://directory.middlemanapp.com/#/extensions/all
Directory Structure• Data
• Lib
• Source
• Images
• Javascripts
• Layouts
• Stylesheets
• Pages, posts, etc
Source
index.html.md
/about
Build
Data
/css /js/img
layout.html.erb logo.svg all.scss
_header.scss
_footer.scss
all.js
menu.coffee
feed.js
_header.html.erb
/layouts
Dynamic Files
• Data is made available to our templates
• Useful for creating menus, lists, directories, etc.
• Pages can also be dynamically generated from data
Dynamic Pages
In config.rb
people.each do |person| proxy “people/#{person[‘name’]}.html”, “layout/person.html”, locals: { person: person } end
Data Source LibraryIn lib/wordpress.rb
class WordPress include HTTParty
def initialize(uri) self.class.base_uri uri end
def posts @posts ||= self.class.get(‘/posts?type=post’) end end
Dynamic Pages from Data Source
In config.rb
@wordpress = WordPress.new(“http://supersecret.dev/wp-json”)
@wordpress.posts.each do |post| proxy “/blog/#{post[‘slug’]}/index.html”, “templates/post.html”, locals: { post: post } end
Use Data Source in Templates
In source/blog/index.html
<% wordpress.posts.each do |post| %> <div> <h3><a href=“/blog/<%= post[‘slug’] %>/”><%= post[‘title’] %></a></h3> <div><%= post[‘excerpt’] %></div> </div> <% end %>
Nicer than this!<?php if (have_posts()) { while ( have_posts()) { the_post(); ?> <div> <h3><a href=“<?php the_permalink(); ?>”><?php the_title(); ?></a></h3> <div><?php the_excerpt(); ?></div> </div> <?php }}?>
There’s a plugin for that
• Hookpress
• Turns internal hooks into web hooks
• Recompile your site when content is updated
• https://wordpress.org/plugins/hookpress/
Middleman-WordPress Example
https://github.com/knicklabs/middleman-wordpress-example