WordPress 2018: Growth

WordPress is growing. Growing is good. As WordPress becomes more ubiquitous, respected, cherished, we will all benefit, as long as we do not become complacent in light of our success and we continue to democratize publishing for the world. With the strength of WordPress, the software and the community, it is kind of puzzling that WordPress is not really in the cultural zeitgeist (maybe that is a good thing at the moment).

My family is all about Instagram, I don't use it personally, but they are really into it. Most people know about Instagram, Facebook, Twitter, but not many in my town seem to know about WordPress. WordPress is a much more valuable tool than Instagram, Facebook, Twitter, but it remains hidden in some ways. Many people I talk to are also familiar with Squarespace, Wix and Shopify; just not WordPress. 29.2% of the internet unknown to most. There is tremendous opportunity here, but how do we get the word out?

I read a comment on WP Tavern recently, that said something to the effect of: if you decide to use WordPress, you must also labor over maintaining and publicizing it. This is not true. No one expects anybody to help push the platform forward. The comment was made facetiously, or at least that was my interpretation, but from my experience, I can say the more I put into WordPress the more I get back.

Why? Well it's simple. WordPress the software, not the name, is mine. It is also yours, but it belongs to no one and somehow everyone. It's a weird concept that I still struggle to fully understand, but when you improve WordPress, you will benefit from that improvement.

It is easy to see products like WordPress.com and feel as though they benefit more from WordPress than everyone else, and for some reason this year I have noticed a lot of unwarranted resentment towards Automattic. I am new to the space, so I do not know the full history, but it is really hard for me to see things like WordPress.com as a detriment or vampiric presence to WordPress, quite the contrary in my opinion. Yes, I understand the naming thing between .org and .com. The situation is confusing, but most things in life are pretty confusing. I could easily imagine another scenario where WordPress.com was named XYZOMG. "XYZOMG is basically WordPress, why the fancy name? You aren't promoting your core product! Why should we work on WordPress, when Automattic doesn't even promote it?" This is purely hypothetical, and I don't want to mischaracterize people's opinion, but it often feels like a "Haters are Gonna Hate" scenario. At the end of the day it is just a name. WordPress is just a name. What it embodies is more significant: the powerful software, the passionate community, and the mission of bringing digital publishing to the world.

Although we do not own the name WordPress, we do own WordPress, and when we promote, maintain, and change WordPress, we inevitably change our own personal world too. I very firmly believe that from what I have put into WordPress, I have been given back so much more, and I know I am not the only one. So when I feel that WordPress does not have the recognition it deserves, I am not afraid to try and promote it further, because I believe it will benefit my family, and many others somewhere down the road. I won't feel as though I am cheated out of my time.

I am just a small voice, but collectively we really could help WordPress grow to do more amazing things than it already has. I have been able to help my clients make tens of millions of dollars this year alone, and have been blessed for my efforts. WordPress has helped so many gain economic freedom in a way that I am not sure many other things in this world have done. WordPress is a mission worth hitching your wagon onto. There is a lot work to be done, and a vast amount of opportunity ahead.

Growth Ideas

Calls to action

I really liked Aaron Jorbin's idea of the #GutenbergChallenge. It was a decentralized, yet coordinated way to promote and provide feedback for the new editor. It was a call for people to answer, rather than a post from Make, Post Status, WP Tavern informing us what is happening.

Running some sort of community driven promotional campaign seems like a cool idea that we could potentially leverage to have a more concentrated effort in promoting WordPress itself rather than a small aspect like the editor. I am not sure how successful the #GutenbergChallenge was or how we can even measure success of ventures like this, but it might be interesting to explore how to optimize these challenges, and get the most benefit out of them. I think overall the challenge helped start tipping opinion towards a more positive perception of Gutenberg, which was initially overwhelmingly negative.

The active engagement from the #GutenbergChallenge is the best part. If you participate, you use the new editor, and get to share your thoughts in a clearly written manner. Participating in comment sections, or on GitHub is great, but comments are rarely a good place to fully flesh out your ideas, and they can often degenerate into mixed messages and misunderstandings. So rather than a central post generating discussion via comments, a call to action creates commentary among a diverse collection of experience. The main hurdles to making this effective are collection and curation.

Story Platforms

HeroPress is another great idea. The essays really convey how WordPress has personally impacted the author's life. It covers stories from over the whole globe. The Hallway Chats are also another interesting addition to WordPress focused content. If you haven't checked The Hallway Chats out, they host conversations featuring someone from the WordPress ecosystem.

I like how HeroPress and Hallway Chats showcase individuals rather than organizations and they really add a great personal touch. The individuals may promote the organizations they are associated with, but it is really about the person and how their story has crossed paths with WordPress. It really puts into perspective how all of these people collectively create what WordPress is.

This was about growth though?

Right. Growth. I think there is a lot of room for growth in the WordPress space, especially when we consider trying to make the platform easier to use, and more friendly for new comers ( and current users ). A more difficult prospect is making WordPress more valuable in everyday life. I know many people who run a business that simply do not need a website, or a web presence. Even if they did, they would have to hobble through the nonintuitive portions WP Admin, themes, and plugins. However, almost everyone I know uses some form of messaging, or some form of social interaction via the internet. I wonder if there is space for WordPress to creep into that realm. It kind of is there, but it kind of isn't.

The new block editor will vastly improve the publishing process, and future iterations on that concept will make digital publishing exceptionally powerful and easy, but what about the distribution and discovery mechanisms we have in place for our content? For the most part we are at the whims of the Googles, Facebooks, and Amazons of the world. Don't get me wrong I think all of these companies do groundbreaking work, I just wonder if there is something better that could be created.

With the advent of blockchain, I think there is room to open things up a bit more, and start creating more meaningful connections. I have no idea where blockchain is going to go, nor do I fully understand it, but it seems very interesting, and this year I am going to start a project that will be a network of sorts where people can share their work and ideas with each other over a new distribution mechanism. I have no idea whether it is a good idea, it is probably terrible, but it has captivated my interest.

If the new Gutenberg editor radically improves the digital publishing world, which I hope it does, does it matter if the content we produce has to be distributed through mechanisms that we have minimal control over? The peer to peer nature of blockchain seems very appealing, but I don't know if it will be a good thing or not. I honestly don't know enough about it yet, or its ramifications, but the project will be an interesting project to work on, and hopefully it will be something positive. At the very least, hopefully it inspires similar ideas in others, because I think if we truly want WordPress to grow, we need to empower people to better connect with everyone else.

Social networks have not been figured out yet, or to my knowledge they have not. One of the largest problems in my opinion is something that I believe occurs rather naturally; echo chambers. My own social media interactions are purely web development oriented, with the exception of the incredible C. T. Fletcher. I could find new things, but there is an odd comfort in keeping to what you know, or where you think you belong. I naturally have created my own web development echo chamber without realizing it. One potential solution that I see, that could be very interesting, is to override our natural tendencies, and instead force random connections into our network, even if only temporary, reflecting more of how the real world works. Typically networks encourage you to go after what is already familiar and be highly selective, but I think there is opportunity to shake that up and create more random connections like you would pre-internet. Adding a little chaotic spice to the mix, I think could allow people of different backgrounds to meet connect with each other, even if it is uncomfortable.

Connections as a driver for Growth.

If we really want the ubiquity of WordPress, I think starting to brainstorm on how we can better connect with each other, and how we can bring more value to people's everyday activities will become a crucial piece to the WordPress Growth puzzle.

Gutenberg: WordPress needs You!

I have had the fortune of porting Gutenberg into interesting places lately. I am incredibly excited about the progress being made on it, and think the team involved is doing a stellar job! I really can not wait until this is ready for core, and I think it is a much needed improvement of the current WordPress experience. If you haven't tried it out yet head over to the plugin repository and try it out. It is still in early development, and should not be used in production. You may notice a lot of negative reviews and that is what I am going to talk about for a bit.

Negativity around Gutenberg

The project has received a fair amount of negativity honestly. Most of this is stemming from uncertainty around the project, and its implications for WordPress as a whole. The project is far off from a version 1 completion, or core readiness, but it is not as far as some might think.

The negativity in most instances is not necessary, and could easily be framed in more constructive viewpoints, but that should not be expected either. One of the biggest hangups around the project is meta boxes. Gutenberg does not support meta boxes yet, nor does it offer any support really for custom post types. Like was mentioned above, it cannot be stressed enough, Gutenberg is still in early development phase, and is rapidly improving week to week.

Meta Boxes, CPTs. Woe is me!

I see complaints about meta boxes, and custom post types, pretty much everywhere I look for information and critique regarding Gutenberg. It would seem like the meta box problem should be a no-brainer and easy to implement in Gutenberg. The reality of it couldn't be further from that. Gutenberg is more of a client side SPA style application compared to the typical server rendered request response approach that is widely used in WordPress. It runs pretty much entirely in JavaScript, where as typical meta boxes run mostly in PHP.

I could go on further explaining the intricacies and could also explain why we should not trash Gutenberg as some suggest, instead I am going to try to focus my efforts more towards showing people what can be done with Gutenberg.

Gutenberg is the future of WordPress

I had my reservations to begin with, but I am thoroughly convinced that Gutenberg is the future of WordPress, and it is going to be a boon to the WordPress ecosystem. Everywhere we look, we see useful ideas on what to do to improve Gutenberg, but not a lot of people are posting about what can be done with Gutenberg.

I am finding that people are having a hard time wrapping their heads around the "block first" concept, and what that means exactly. I am still wrangling with it myself. On the surface it seems pretty simple, and obvious, a lot like LEGO. LEGO are essentially just a modular building block with a set interface or inputs and outputs. When I look at a box of LEGO, I only see the blocks and their various colors, and need some instructions to help build something cool. Some people see them as a sculpting material and create amazing art.

"Yellow," by U.S. Lego artist Nathan Sawaya

LEGO are just an idea though, and have been reused in truly amazing ways. I think the same will happen with WordPress, we are only on the cusp of the new block based approach.

I hope to focus my efforts on trying to create some unique Gutenberg experiences, and share them with WordPress community, in hopes that people will be able to see how they can do the same in their projects. I want to help show off the incredible sides of Gutenberg, rather than be bogged down by its current shortcomings.

Stay tuned!

If Gutenberg and the discussion around it has piqued some of your interest, or even if it has terrified you, follow my blog and hopefully you can get a taste for what is to come in Gutenberg. I was planning on posting things about Gutenberg that could be better, but instead I want to show the world how amazing it already is!

Gutenberg: A new way to WordPress!

The Gutenberg editor is really shaping up to be something great! The standard editor in wp-admin will most likely be replaced by project Gutenberg in the near future, but Gutenberg is much more than a wp-admin editor replacement. I think it is the future of WordPress, and will open up many new opportunities to bloggers, site owners, agencies, and product businesses. WordPress already powers a large portion of the web, and I think project Gutenberg will increase WordPress’ market share. This could be a victory for the open web, when lately, its obsolescence seems inevitable. Let’s look at some cool things you can do with Gutenberg.

Page Builder Style Editing & More

Below you can see this text being added into the page!

Pretty cool. Not too far off from the current WordPress experience. Let's add in something a little more interesting, that a basic WordPress install cannot do.

Adding A Cover Image!

What we did here is we added in a new cover image block from the inserter. This opened up the media library and we selected our image. We then added text and set the image to full width; oila! Here is what it looked like:

This is just one of the many things that can be done in Gutenberg, quickly, and enjoyably. What you are seeing however is not the standard Gutenberg experience. Instead you are seeing a front-end content building experience powered by Gutenberg. If you haven't checked Gutenberg out yet head over to the WordPress plugin repository and try it out! It does have a fair number of negative reviews, but this is a project in its infancy. There are a number of issues to be resolved with project Gutenberg, but it is largely the effort of a small team over a four month period; impressive.

To see the difference between the regular Gutenberg editor and the one you see running here check out the below image:

The font does not match my theme, nor the layout. This is the standard Gutenberg experience, which is great! As much as I love the standard Gutenberg editor, I would much rather live edit my content as it is going to look when I hit Publish. This has been a boon on some recent projects for me, as my clients are now much more easily able to visualize the final result, because they are creating the final version as they go. The block based building in Gutenberg brings more to the table than a nice user experience.

All hail blocks!

The sleek UI, and interface for Gutenberg will eventually become outdated, but I believe that blocks will remain. The "block first" approach being taken in Gutenberg is the most important aspect of the project. Content blocks have the potential to replace shortcodes, meta boxes, widgets, custom post types and unify them into one self contained entity. The Gutenberg editor can eventually even extend to become a theme builder of sorts. The possibilities are limitless, but I have already started building some practical solutions for my clients as blocks.

For one of my projects, I have created a quiz block. You can build out a quiz, with questions all right inside the editor screen, or use it to insert an already created quiz. In the past this would have required many meta boxes, shortcodes, and would be a jarring user experience. Now it is seamless and effortless.

The Future

I don't know what the future holds, and there is definitely a significant amount of tension surrounding this project, but I am rooting for it and going all in on it. How do you feel about Gutenberg?

Gutenberg: The New WordPress Editor Experience

There seems to be some tension in the air over the new Gutenberg editor for WordPress, which is good. I wish there was more attention and dialog on it. If you haven't tried it out yet head over to the plugin repository and download Gutenberg for your WordPress install. Some think it is utter crap, some think it is amazing. There seems to be very little in between. Some do not see the goal posts or incremental movement, and others realize the plan and understand the significance of Gutenberg.

Why does Gutenberg matter?

Platforms like Squarespace and Wix are offering a very compelling user experience for a very small price. They eliminate a lot of the headache involved in managing self-hosted WordPress. No plugin updates, no core updates, no random breakages between conflicting versions of plugins or core; bliss. The design templates for Squarespace are well crafted. In the hands of a professional designer, any Squarespace site could be molded to look fantastic, without touching any code. The same is not necessarily true for WordPress, unless you are using a tool like Beaver Builder.

If things continue on this path, it is not too unreasonable to imagine a large chunk of WordPress' market share to be taken up by these platforms. This would be a loss, as WordPress is open and serves a gigantic ecosystem, where small businesses and large enterprises can thrive. With a closed platform like Squarespace, outside tech services can only provide little to no benefit for each other. What does any of this have to do with Gutenberg?

WordPress needs to innovate to remain relevant and grow. Now is the time to do so as well, while WordPress still dwarfs any other platform. The Gutenberg project will be the driving force for innovation.

The Goal of Gutenberg as I see it

The goal is to "make adding rich content to WordPress simple and enjoyable". Extrapolating that goal leads one to a front end editing experience similar to Wix, or Squarespace and beyond, but the Gutenberg plugin only currently replaces the editor inside of WP-Admin.

Misunderstanding the goal of Gutenberg

A common question I see is, "If you want to compete with Wix or Squarespace, why not make a page builder?" WordPress could, but it would be missing a huge opportunity in unifying its content experience, and in the process would only try imitating Wix or Squarespace not supersede them. I think things are less about competing with a particular platform and instead are more focused around creating a superior product to any platform. By taking the "block first" approach, widgets, shortcodes, custom meta boxes, post content, et al. can become a block, which can then be added to content anywhere, dynamically, using a uniform interface. Once you can see this clearly, I think it is hard to argue that the direction Gutenberg is headed in is not a superior user, and developer experience.

By unifying the content system into individual blocks first, a page builder would become much more trivial to create. It would also open up other possibilities that other platforms do not have, like collaborative editing (similar to Google Docs). So why the focus on the editor first?

If the front end editing experience was made first, well it would pretty much break the current editor, making it unusable, anyways. If you are editing content as blocks on the front end, then go back to editing in the classic WordPress editor, you will most likely break all of the block content you just created on the front end, because it is no longer there for you to edit in wp-admin. Building the editor first in a new "block first" approach is the correct choice, as opposed to trying to build a page builder on top of WordPress.

This all sounds pretty good, maybe this Mullenweg fellow does understand a thing or two about leading a project forward, so why all the hate on Gutenberg?

Innovation, Fear, Uncertainty, Doubt, and Context

New innovation always will bring about a certain amount of Fear Uncertainty and Doubt, which is totally healthy and good. I have many reservations about the Gutenberg project myself, but I think on the whole it will be a giant net benefit to WordPress. The reviews on the plugin repository are extremely polarized, and although the plugin claims to be in beta, it is really, in my opinion, more like alpha software. It is important to understand that the Gutenberg project is not ready for core yet. It's barely even ready to use on your blog and I would not recommend using it, unless you understand the technical side, but it is also not as far off as some people think.

For developers like myself who have invested countless hours building custom metaboxes and custom TinyMCE buttons etc., it can be somewhat disheartening to see that effort seemingly go to the wayside. You need to get over that feeling quickly. That time spent has hopefully served you well up until this point and now it is time to move on to something that I find is a lot better, and your clients will find a lot better.

My own experience

I have recently started converting a lot of the custom meta boxes and custom TinyMCE buttons for a client into blocks and running Gutenberg ( with tweaks ) in production ( yes, I am crazy ). My client is able to do much more than they ever could, and they have a full front end editing experience already, today, which they are thrilled about. Rather than trying to dig my heels in, I am embracing the future direction, because it seems like in the long run, it will be better for me, my clientele, and WordPress.

Backwards Compatibility

Shortcodes, meta boxes, and widgets aren't necessarily going anywhere, but if you want to come along the journey of where WordPress is going, you should start creating blocks and get involved to help shape them. You might find that the previous experience was a pain to work with. Learning new things can be daunting, but I think the direction of Gutenberg is a good path to follow.

#GutenbergChallenge

This post has been a part of the GutenbergChallenge, which I will be writing about twice ( failed 😉 ) a week now until the end of the year. If you haven't tried out the Gutenberg editor yet check it out, and share your thoughts on it as well.

WordPress with GraphQL. Finding a good fit.

Hey everyone!

I am super excited about the progress being made on WP GraphQL; a plugin that enables a GraphQL API for your WordPress install. If you haven’t already checked it out, head over to the WP GraphQL GitHub repository, or the WP GraphQL documentation site.  Let me know if you stumble on anything, or have trouble setting the plugin up. DO NOT SET THIS UP ON A PRODUCTION SITE; it is not production ready and exposes all data without any security checks. The plugin is targeted towards developers. If you want to learn more about GraphQL, check out GraphQL.org.

Why GraphQL for WordPress, isn’t there a REST API?

The WordPress REST API is very good and has made developing engaging experiences with WordPress a lot more tangible. I deeply appreciate all of the blood sweat & tears put into that project, and have learned an immense amount from it. I have the utmost respect for the team leads of the WP REST API and the many contributors. I will still contribute to the WP REST API when I can. The list of good things to say about it could go on for a very long time. However, in working with the WordPress REST API on some of my projects, I found the experience to fall short of the grand vision laid before me.

The promise of being able to create better user experiences, was met with immense technical hurdles, that I took for granted.  Not that any of these problems are not solvable, but the ever impending reality for me is that GraphQL fits WordPress a lot better.  REST focuses on resources, and I believe firmly that WordPress is not just a collection of siloed resources. WordPress to me is more about relationships.  The relationship between a post and its comments. The authors of those comments, and the author of the post. Think about the impact of our words and the relations that WordPress creates between people who are worlds apart.  WordPress is an ever growing web of relationships in all aspects, the community, the codebase, and most importantly the impact WordPress as a product has, and its reach.

No single aspect of WordPress functions independently. These relationships are key to WordPress itself and should be embraced rather than isolated. GraphQL is all about relationships, REST is about resources.

The power of querying with WP GraphQL!

The name GraphQL stems from Graph Theory. On its basic level, Graph Theory just describes relations between different things. It deals with two concepts; nodes and edges. Nodes are the individual entities, and edges are the relationships between entities. Edges can go one direction or both directions. Let’s think about this in WordPress world.

A single post can be considered a node. The post has various properties like content, title, etc. That post also has an author, which is another node. There is a bi-directional edge/relation between the post and the author; the post has a relation to it’s author and the author a relation to that post. WP GraphQL exposes these relationships.

If you want to grab a post’s title, content and the author’s name, you would use the following query:

{
  post(id: 2) {
    content,
    title,
    author {
      name
    }
  }
}

The response would look like this:

{
  "data": {
    "post": {
      "content": "Wow this is a really cool post I made.",
      "title": "Insert meme here.",
      "author": {
        "name": "Greg Quincy Love"
      }
    }
  }
}

I like how concise the queries are in GraphQL and how the response matches the request. There is definitely something to be admired in the simplicity of GraphQL syntax.

I can already do that in WordPress. Who cares?

The above example is basic and does not fully expose the possibilities of GraphQL. Let’s look at this query:

{
  post(id: 10) {
    title,
    content,
    author {
      name,
      avatar(size: 96) {
        src,
        width,
        height
      },
      posts(first: 3, not_in: [10]) {
        title,
        exceprt,
        featured_image {
          src
        },
        comments(first: 1) {
          content,
          author {
            name,
            avatar(size: 48) {
              src,
              width,
              height
            }
          }
        }
      }
    },
    comments(first: 20) {
      content,
      date,
      author {
        name,
        avatar(size: 48) {
          src,
          width,
          height
        }
      },
    }
  }
}

(disclaimer: WP GraphQL does not fully support all of these capabilities, but is suprisingly close)

Pretty neat right?  This would grab a post with an id of 10. The response will include the title and content for that post. Here is where things get intersting. We will also grab the author of that post, their name, their avatar, and their 3 most recent posts! The three most recent posts of the original post’s author will contain the title, the excerpt, featured image (not yet supported) and the most recent comment. The most recent comment on these recent posts will feature the content, and the author of that comments name and avatar; at a smaller size!

Woah, think about what this opens up for UI/UX design, imagine having a clickable accordion/tab that will toggle featuring the author’s three most recent posts and some nice information about them. GraphQL will liberate our defining of relations from the conventional way.

There was more to that query above, it also fetched the first 20 comments on the original post, each displaying the content date, along with the author’s name and small avatar. Anybody who has designed a UI/UX knows the pain of not having the data you want, and the burden of getting too much data. GraphQL solves both of these issues at once. You get only the data you want and it will follow the relationships you define. WordPress is pretty post centric at this time, what if we could make WordPress more people centric? GraphQL would make this more easily doable.

WordPress multisite installs could become even more network oriented, as GraphQL could become the glue binding each site. Projects like BuddyPress would make an exceptionally great fit for WP GraphQL as well. Social interactions, in something like BuddyPress, can be viewed as relationships between two entities. This is where something very important needs to be considered.

With great power comes great responsibility.

The age old saying fits this perfectly. GraphQL has the ability to expose relations that we currently cannot easily handle or grasp. Anybody who is in tech should understand that each node and edge is much more than data. Each node could be a story, a joke, a human being; each edge a relation, a secret, a friendship. We are here to protect and make the web better. Privacy and taking a sensative approach towards it, will be paramount in the success of WP GraphQL as a project. If you are interested in helping out, head over to the WP GraphQL GitHub repo and introduce yourself!  What are your thoughts!?

Demystifying the WordPress Rest API Endpoints – Part I

This post has been revised to reflect the merging of the core endpoints into WordPress 4.7

The WordPress REST API is a very ambitious project that will not only benefit the WordPress ecosystem, but ultimately, the entire web. This guide will focus on the structure of core endpoints, which were merged in WordPress 4.7, and will dive into registering and writing endpoints of your own. This guide assumes you have a basic understanding of why you would want to use the WordPress REST API. Let’s briefly break down where the WordPress REST API project currently stands.

What is the WordPress REST API?

The WordPress REST API is an attempt to expand and modernize how people consume and interact with WordPress. The project is largely spearheaded by Lead Developers Ryan McCue, and Rachel Baker, along with contributing developers Daniel Bachhuber, and Joe Hoyle. There are many more contributors to the project as well. The project is comprised of two parts: infrastructure and endpoints.

The WordPress REST API infrastructure was merged into WordPress core in version 4.4 and the core endpoints were merged in WordPress 4.7.  The core endpoints are registered via controller classes and at first glance, they can be somewhat daunting to comprehend. This guide will hopefully demystify confusion and bring clarity regarding the flexibility the API endpoint design provides.

Endpoint Development

It’s hard to say what the major adoption point of the WordPress REST API will be, given its incredibly flexible nature; akin to WordPress. Registering your own endpoints is incredibly powerful, but there are some key concepts to understand before diving in too deep. There are three important endpoint components: routes, schema, and controllers.

Routes

Let’s talk routes! The WordPress REST API provides a way to interact with WordPress internals solely over HTTP (hopefully you are using S!). What does that mean? Basically, you send an HTTP request to an endpoint route, let’s say GET https://example.com/wp-json/wp/v2/posts/1 and you are returned a post object as JSON. Magic. Now we can break up the example endpoint route into smaller components.

  • Protocol: The https:// represents the protocol that is used to make the request.
  • Domain: The example.com/ portion is the desired domain.
  • API Index: wp-json/ is the index endpoint where the WP REST API lives. Accessing this index exposes the available namespaces, routes, methods and arguments that can be used to communicate with WordPress through the API. This endpoint becomes a source for programmatic access to each WordPress installation, allowing clients to see how unknown sites have configured their WP REST API. The process of utilizing the index data is known as discovery. Super neat stuff. Discovery opens up all kinds of possibilities. The API index provides a machine readable blueprint of your WordPress install, enabling external apps to integrate more easily with WordPress and on the flip-side it enables your WordPress install to more easily digest content from other platforms by using a common communication interface of HTTP; all automatically configured for you. Note: there are not currently many auto discovery client libraries built yet, but the possibility is there.
  • Namespace Index: The wp/v2/ portion represents the namespace index. This endpoint does all of the same things as the API endpoint but for a specific namespace. Each namespace is registered via register_rest_route(), which we will get to later.  For good form you should be registering your endpoints in a namespace other than wp/v2/
  • REST Base: The posts/ portion represents the rest base for the route. Typically each rest base route serves as the endpoints for collections and creating new resources; i.e. GET example.com/wp-json/wp/v2/posts, will return a collection of posts. Likewise, POST example.com/wp-json/wp/v2/posts?content=OMG&title=RESTAPIisAwesome, will return a newly created post. You may be wondering if anyone can just come in and make a post on your blog? Thankfully, no. The WordPress REST API can use many different Authentication/Authorization methods to make sure certain actions and data are only accessible to particular users. Auth is outside the scope of this guide, but we will touch on it here and there.

Let’s reflect. As you can see the URI structure has endpoints tacked onto endpoints, in an intuitive fashion. The namespace and rest base serve as a way to separate different branches of what your API can do and what resources are available.

All responses from the API are returned in JSON formatting. JSON is an open standard format of human readable data. This seemingly minute detail, in tandem with the use of HTTP, is what makes the API so powerful. Now, WordPress can be more easily consumed by different programming languages and application infrastructure, helping spread the awesomeness of WordPress to a much broader audience, which in turn will diversify and enrich the WordPress community with new ideas and people. Rather grandiose for such a simple thing.

Let’s dig into routes a little bit more. RESTful infrastructure is based around HTTP. Originally, in HTTP 1.0, there were three methods: GET, HEAD, and POST.  POST ended up becoming a catchall of sorts for many kinds of requests. HTTP 1.1 introduced a number of more descriptive methods, often referred to as HTTP verbs, which enable us to have a more semantic way to interact with APIs via HTTP.  The WordPress REST API makes use of POST, for creating, GET for reading, PUT for updating, and DELETE, which is self-explanatory. OPTIONS requests will return a very special kind of data; our schema.

Schema

Before we write our own endpoints, it is important to understand schema and its significance. Schema is metadata. It describes the current resource. An OPTIONS request to the posts endpoint will spit back the namespace, allowed HTTP methods for endpoints and most importantly the schema. Schema data is currently provided via JSON Schema, so we have JSON telling us how our other JSON data is structured. Kind of silly, but extremely important.

Let’s take a quick step back. The WordPress REST API in some ways can be viewed as taking SQL data and transforming it into JSON. MySQL, and other RDBMSs by default provide data with schema.  Each column has certain criteria that describes what its content can be.  Most Primary Key columns are INT NOT NULL AUTO_INCREMENT or something similar.  That information tells us and the database that the data for that column is supposed to be an integer within a certain range of values, can’t be an empty value, and in each row the value will automatically increment, creating a unique ID for each row. Schema adds constraints. Why does that matter?

You may have heard all the rage about MongoDB or other NoSQL databases, but there are many, many drawbacks to them and the endpoints that we create also suffer from similar problems.  Obviously NoSQL has its merit, and when implemented properly, it is incredible, but that is an entirely different discussion (the more I learn about NoSQL the less I want to use any SQL).

Without schema we have no way to understand any of our data. Let’s take a simple JSON object.


{
    "shouldBeString": 3,
    "shouldBeArray": "LOLz you need schema.",
    "shouldBeInt": ["I","is","array"]  
}

This is perfectly valid JSON and any parser will continue along as if there is no problem. There is really no way for us, let alone a machine, to tell what the structure of the data should be in the object above. It is arbitrary (even the key names). We can’t validate our data or form logical relations in our application without schema. Well you can, sort of, not really, not recommended, but schema just makes it a whole lot easier and more practical. Reading more about the JSON schema draft 4 spec is highly recommended.  For a friendly JSON schema intro check this out.

This hopefully outlines the basic importance of schema, which should be created for every endpoint. How do we add said schema? The best way is to follow the structure of the controller classes for the WordPress REST API.

Controllers

Each core endpoint in the WordPress REST API uses a controller class to manage its functionality.  By following the patterns presented in the controller classes, you will be taking advantage of a lot of foresight regarding the usability of your endpoints. First lets talk about some of the WP REST Controller methods.  There are quite a few and it can be quite confusing what exactly their relevance is at first.

WP_REST_Controller Methods

public WP_REST_Controller::__construct()

This is the object constructor method for an endpoint controller class.  For most use cases, you will only do two things in the constructor: set $this->namespace to your desired namespace, and set $this->rest_base to the desired rest_base of your endpoint. If you are doing an endpoint for a custom post type you can register $this->post_type or potentially just do this WP_REST_Posts_Controller( 'my-cpt' ). If you are working with custom post types I highly recommend just extending WP_REST_Posts_Controller and overwriting what methods you need to. The constructor should just set up some basic properties that will be used throughout your endpoints.

public WP_REST_Controller::register_routes()

This is an extremely important part to writing the controller class for your endpoint. This is where we will be calling register_rest_route() for each of our routes. For a collection it would look something like this.

register_rest_route( $this->namespace, '/' . $this->rest_base, array(
    array(
        'methods'             => WP_REST_Server::READABLE,
        'callback'            => array( $this, 'get_items' ),
        'permission_callback' => array( $this, 'get_items_permissions_check' ),
        'args'                => $this->get_collection_params(),
    ),
    'schema' => array( $this, 'get_public_item_schema' ),
) );

The first parameter is the namespace where the endpoint lives. We defined the namespace in our constructor method. Next comes a leading slash concatenated to our rest base, which we also defined in our constructor. If we had a digitized library of books maybe these first two parameters would make something like this: library/v1/books. library/v1 is our namespace and books is our rest base. Now, we need to know what can happen at /wp-json/library/v1/books. In register_rest_route() the third parameter can either be an array of options for the endpoint or an array of arrays of options supporting different HTTP methods.

In the above example we are registering an endpoint route that supports GET, HEAD, and OPTIONS requests. The first array provides the options for our collection endpoint. It supports the GET method. Any GET request to this route will trigger our permission check and $this->get_items() callback. We can pass special arguments to this endpoint, which will be documented in $this->get_collection_params(). Last the schema is registered to the route, so when an OPTIONS request is made, the schema is exposed.

public WP_REST_Controller::get_items_permissions_check( $request )

This is a permissions check for the collection endpoint we have created. You can use logic like.

if ( ! current_user_can( 'edit_posts' ) ) {
    return new WP_Error( 'rest_forbidden', esc_html__( 'Sorry, you cannot view this post resource.', 'my-text-domain' ), array( 'status' => rest_authorization_required_code() ) );
}

This enables you to restrict access to the collection based on whether the authenticated user has the edit_posts capability. Returning a WP_Error in the permissions check will trigger an error to be returned to the client, preventing unauthorized access. In cases where Auth is involved it is a best practice to use rest_authorization_required_code() to get either a 401, or 403 status. 401 is for non authenticated users, in the API’s eyes no one is logged in. 403 is for unauthorized users, meaning a user is logged in but doesn’t have the proper privileges.

public WP_REST_Controller::get_items( $request )

This is the callback that is triggered to produce our desired response. It will typically return a collection of resources. The context parameter can be used to expose different data in the collection. Currently the context parameter supports view, edit, and embed contexts. The context should be registered in the schema for the property and can be automatically filtered using $this->filter_response_by_context(). It is important to note that for other actions there will be a corresponding callback and permissions callback so instead of get_items there can be get_item, create_item, update_item, delete_item, and whatever floats your boat. We will get into this more in part II, where we create a mock custom endpoint.

public WP_REST_Controller::prepare_item_for_database( $request )

This method is used to prepare a resource for the database after either being created or updated. The arguments passed in should already be sanitized and validated by this point but additional processes can be done to map the request to an actual object that is stored in the database. prepare_item_for_database() should be called directly before the resource is created or updated.

public WP_REST_Controller::prepare_item_for_response( $item, $request )

WordPress can have strange naming conventions for many resources. Using this method we can create a mapping of better naming for the resource. We want our response to match the schema and this is where all of that logic goes. After we have created a resource that matches our schema, we want to also call $this->add_additional_fields_to_object and $this->filter_response_by_context(). By calling these two methods we will add extra fields registered to our endpoint via register_rest_field() and then filter the entire response based on the provided context. We then wrap our data in a rest_ensure_response() and add any relevant links. We will get into links more in part II, they are used to create relationships between resources.

public WP_REST_Controller::prepare_response_for_collection( $data )

When creating a collection in our get_items() method we would do something like this:

$collection = array();
foreach ( $items as $item ) {
    $data = $this->prepare_item_for_response( $item, $request );
    $collection[] = $this->prepare_response_for_collection( $data )
}

Because $data is supposed to be a WP_REST_Response object, we need to make a collection of the responses data wrapped in a WP_REST_Response object, as opposed to a collection of WP_REST_Response objects. Kind of confusing, but important to understand the difference. For the most part, I don’t think this method will ever need to be overridden so just call it whenever you are creating the collection and let the magic happen. This method will be directly inherited from the WP_REST_Controller class.

public WP_REST_Controller::filter_response_by_context( $data, $context )

This method is pretty straightforward and should be called within prepare_item_for_response(). Basically filter_response_by_context() takes the response data and the request’s context parameter and filters it based on the schema. If a property has a context set to edit in its schema, then it will only show up on requests where the context param is set to 'edit'.

public WP_REST_Controller::get_item_schema()

We have talked a lot about schema. Finally, we are at the method where it is defined for our endpoint. Lets take a look at a basic schema object.

$schema = array(
    '$schema' => 'http://json-schema.org/draft-04/schema#',
    'title'      => 'example',
    'type'       => 'object',
    /*
     * Base properties for every example.
     */
    'properties' => array(
        'id' => array(
	    'description' => __( 'Unique identifier for the object.' ),
	    'type'        => 'integer',
	    'context'     => array( 'view', 'edit', 'embed' ),
	    'readonly'    => true,
	),
    ),
);

Our schema defines what should be returned in the response. If we make a request to our collection endpoint then each item would only have an id property. The schema follows JSON Schema, which we talked about above. The root part of our schema contains $schema, the spec of our schema, title, the title of the resource, type, the type of resource, and properties. Since the schema is an object itself we set its various properties. Our first and only property is id. We specify a human readable description, type, context, and whether it is a readonly property. At the very end of get_item_schema() you will want to add this statement.

return $this->add_additional_fields_schema( $schema );

By adding this statement we will allow any schema registered by register_rest_field() to be added to our endpoint. The title property in our root schema serves as the object, which register_rest_field() uses, so it is important to keep that unique per namespace. We used 'example' as our value.

public WP_REST_Controller::get_public_item_schema()

This is what you want to call for schema when you are using register_rest_route(). It will strip out any arg_options you have specified for properties in the schema. This way you end up with a very clean schema, which presents information that is only useful to clients. arg_options can be specified for a schema property so that the schema can easily be transformed into request arguments, when creating or updating by using $this->get_endpoint_args_for_item_schema(). We will get to that a bit later.

public WP_REST_Controller::get_collection_params()

get_collection_params() should start with something like the following:

$params = parent::get_collection_params();
$params['context']['default'] = 'view';

The call to the parent classes get_collection_params() will bring in any previously registered collection parameters. If you are just extending WP_REST_Controller then this will add the context param, page param, per_page param, and search param. We have already touched on what context is used for. page and per_page are pagination parameters and probably offset should be a part of this group too, but is currently not. search can be used to search through the collection. If the resources you are exposing do not make use of WP_Query then you will have to write custom pagination and search functionality.

public WP_REST_Controller::get_context_param( $args )
This allows for a consistency across endpoints in regards to the context param. You won’t really have to worry about it too much. In part two, we will see where this plays a role.

protected WP_REST_Controller::add_additional_fields_to_object( $object, $request )
This registers the additional fields registered in register_rest_field() for the response. Phew, that’s a lot of registering. Basically if you call this in $this->prepare_item_for_response() your registered fields will now magically work.

protected WP_REST_Controller::update_additional_fields_to_object( $object, $request )
This does pretty much the same thing as above, but there is a small difference. It will register the update_callback portion of register_rest_field(). $this->update_additional_fields_to_object() should be called before $this->prepare_item_for_response in the create_item and update_item callbacks.

protected WP_REST_Controller::add_additional_fields_schema( $schema )
When using rest_register_field() you will want to register schema for the field. Inside of $this->get_item_schema() at the end return the call $this->add_additional_fields_schema( $schema ) and any registered schema will now appear.

protected WP_REST_Controller::get_additional_fields( $object_type = null )
An internal method to handle any additional fields registered by rest_register_field() for a particular object type.

protected WP_REST_Controller::get_object_type()
An internal method that will get the object type of a schema, which is the title property in our schema root.

public WP_REST_Controller::get_endpoint_args_for_item_schema( $method )
get_endpoint_args_for_item_schema() is a pretty cool method that I have mixed feelings about. Basically it will take our schema we established for a resource and transform it into data that can be used as request arguments. Let’s expand on our $this->register_routes() example above for library/v1, to add an endpoint for creating books.

register_rest_route( $this->namespace, '/' . $this->rest_base, array(
    array(
        'methods'             => WP_REST_Server::READABLE,
        'callback'            => array( $this, 'get_items' ),
        'permission_callback' => array( $this, 'get_items_permissions_check' ),
        'args'                => $this->get_collection_params(),
    ),
    array(
        'methods'             => WP_REST_Server::CREATABLE,
        'callback'            => array( $this, 'create_item' ),
        'permission_callback' => array( $this, 'create_item_permissions_check' ),
        'args'                => $this->get_endpoint_args_from_item_schema( WP_REST_Server::CREATABLE ),          
    ),
    'schema' => array( $this, 'get_public_item_schema' ),
) );

We have now set up our route to run on POST requests. When a POST request is issued it will trigger $this->create_item_permissions_check() and $this->create_item(). The request arguments will be generated by $this->get_endpoint_args_from_item_schema(). Any schema specified as required will become required request parameters for creating and any defaults will be used. Schema properties marked as readonly will not be turned into request arguments because this aspect of the resource should never be modified by a request. A great example of a readonly property would be a resource’s id.

Wrapping Up.

As you can see, to truly get the most use out of your endpoints there is a lot that goes into it, and following the conventions laid out in WP_REST_Controller will go a long way towards making your endpoints usable, extensible, and secure. In part II we will focus on the actual coding of an endpoint. In the meantime I recommend reading Daniel Bachhuber’s guide to unit testing and WP REST API Endpoint development. Stay tuned for part II. If you would like to help contribute to the WordPress REST API, head over to Trac on WordPress.org. The project is in need of your contributions.