Hacker News new | past | comments | ask | show | jobs | submit login
Show HN: New GraphQL API for WordPress (github.com/leoloso)
65 points by leoloso on Jan 12, 2023 | hide | past | favorite | 27 comments

What real-life use-cases do you envison for a GraphQL API for WordPress? What does it solve that the existing REST APIs cannot? Why would you make a GraphQL API out of a CMS for (primarily, out of the box) blogs?

GraphQL supports schema stitching, so you can have one API endpoint request lots of different information from different services, and combine information seamlessly server-side. (e.g. Wordpress author -> user service -> posts on a different service)

Here's how we're using Wordpress and other GraphQL services at a smallish nonprofit: https://blog.codeday.org/how-graphql-helps-us-showcase-coded...

That page is powered by Wordpress over GraphQL, and you can try it yourself at https://graph.codeday.org/ (here's a sample query - query { blog { posts { nodes { title author { discordInformation { username discriminator }}}}}})

I think you missed a }

WordPress serves as kind of an ad hoc CMS for many different kinds of backends. Because it’s easy to extend and a lot of people are familiar with it.

When I worked at the CDC, the entire backend of cdc.gov was a heavily HEAVILY customized version of WordPress that did static publishing. I’d guess it’s still that way.

It’s why WooCommerce was so popular. Role your own eCommerce.

GraphQL is good because using WP headless is popular these days.

Using WP headed is a good way to become a 0-day.

One use-case could be to use Wordpress just for an e-commerce backend (WooCommerce API) and then use alternative services for headless CMS etc, stitching them together for frontends to use via this product?

The easy use case is to fetch data from a WordPress backend, and render your site using some JS library (React, Vue, Next.js).

But it can do much more than that (indeed, I like to think of GraphQL as the single tool to deal with any content-related task). These are some interesting use cases:

- Use a WordPress backend as an upstream server to manage all your data, and feed it to downstream servers/applications/websites

- Use GraphQL to extract information from 1 or more sources (such as users from the WordPress sites and the newsletter contact data from Mailchimp) and combine the data (and analyze it all together as a single dataset)

- Execute operations using GraphQL to adapt the content on your site, either as a one-off when installing a new site, or regularly. Eg: replace all "https://myoldsite.com" to "https://mynewsite.com" in the content after changing the domain or doing a migration, and execute queries to replace any "http://" to "https://" when a writer publishes a new blog post

- ETL (Extract, Transform, Load) of anything that involves content, whether stored in WordPress or external sources

- Interact with 3rd party services. Eg: Use GraphQL to connect to the Google Translate API and translate all the blog posts to a different language, or send a tweet after a blog post is published

- Send notifications (by email, Slack, etc) after something happened (a new post, comment, etc)

It can also be used with pipelines, and it can complement WP-CLI whenever it falls short of being able to do something. An example of this:

I myself use GraphQL via my plugin to connect to the GitHub API and fetch data from my releases, which can then be downloaded automatically and installed on my testing sites before running integration tests. I tried using WP-CLI directly for this and it fails, because the GraphQL API gives the .zip download file URL via a header, and this data needs to be extracted first. So I extract the header via GraphQL, and then inject it into WP-CLI, and the whole process is automated.

Many of these tasks, you can do them with dedicated plugins (such as for content migration). The beauty of GraphQL is that it's like a Swiss-army knife: you can write your own GraphQL query to execute many of these tasks, customizing it for your own needs, and avoiding to buy other plugins.

An example could be plucking data from related posts of different types that are related via Advanced Custom Fields.

What's the purpose of throwing GraphQL in front of a single API? I always thought of it as an API Gateway of sorts which fits better in a microservice type architecture and aggregates requests across multiple microservices. At least that's how I have seen it used. What is the need for GraphQL in the WordPress scenario?

Presumably its still useful as a standard mechanism for response field selection and preventing n+1 queries when trying to join data across multiple types of entities.

Check my response above to Kwpolska

A few ideas to improve the schema based on looking at the examples:

1. Make `globalId` part of a "Node" interface that all of the types implement. This will work better with tooling like Relay (used for refetching and caching). It will also let you add a `node` field that can be used to fetch any node in the graph.

2. Make the sort input an enum so that you have `sort: TITLE_DESC` instead of `sort: {by: TITLE, order: DESC}`.

3. Implement the connection spec instead of returning a list of items: https://relay.dev/graphql/connections.htm. This will let you add pagination data to the field and other useful info like totalCount.

4. Spin up a postgraphile instance with the `@graphile-contrib/pg-simplify-inflector` and `postgraphile-plugin-connection-filter` plugins and copy everything they do.

1. I do already have the `Node` interface, but it's called `IdentifiableObject` as I cannot follow the convention, because the interface has 2 fields:

- id: the actual WordPress ID

- globalID

And the convention says that Node can have only a single field: https://graphql.org/learn/global-object-identification/

2. It's better to keep it as an Input Object as it's more extensible by plugins, which may have their own fields to sort by. Also existing resolvers can be reused, instead of having to create a dedicated enum for each single type every time. I think it's more elegant than using enums.

3. You have the totalCount field already for every field. Eg: there's `posts` and `postCount`, `users` and `userCount`, etc.

I could implement connections, and maybe I will in the future, but I need a compelling reason to do it: It was needed by Facebook for their never-ending feed, but as WordPress sites are naturally paginated, I believe it's not a real need.

And connections also bring some pain: I know that WPGraphQL has had many issues with it, maybe even ongoing, with some edge cases where it doesn't work well, and if I'm not mistaken it needs additional DB calls.

4. The plugin already attempts to provide all the filtering supported by WordPress. Check out all the `filter` inputs (in fields `posts`, `users`, `comments`, etc)

(In addition, I'll be releasing extra functionality via directives some time in the future)

And it uses the "oneof" input object to simplify fields, so you have `post(by: {id: 1}}` and `post(by: {slug: "some-slug"}}`

This is cool, but I'm curious to know what took 16k commits. The projects that I've been on with more then ten thousand commits had many dozens or hundreds of folks working full time. And to crank that out in 1.5 years! That's 22 commits per day, every day. That's a fairly meaty engineering org's cadence. Is there some complexity that needed to be overcome that the post doesn't get into?

A lot of one word typo fixes, commits to fix one blank line, and automated package rewrites. Each release is about 3-4 commits of the same thing (bumping versions, etc) with 1-4 releases a day. So to fix a one word typo ends up being about 3 separate commits.

check my response above

For comparison, the WordPress REST API was about 4k commits over ~4 years or so (prior to us merging it into WordPress itself): https://github.com/WP-API/WP-API

(That said, commit count is a pretty useless metric.)

There was a lot of rewriting stuff to make the engine GraphQL-first. Before, the engine received a different spec as input, and GraphQL worked behind an adapter. Now, the engine speaks GraphQL language.

Then completing the GraphQL schema, fully complying with the spec, and adding all the new features. That was quite a bit of effort.

Yes, there were many "typo" commits, changing simply one word. But there were also plenty of commits with dozens of changes and, in the initial rewriting stage, even hundreds of changes.

It really took 16k commits. I'll write a blog post on graphql-api.com and provide some more info (maybe sometime this weekend?).

How does this compare to WPGraphQL https://www.wpgraphql.com that's been around for quite some time (https://github.com/wp-graphql/wp-graphql)

Did you find shortcomings with that plugin?

I will not say why this plugin may be better as I'm naturally biased, but you can check the features from both plugins (mine under https://graphql-api.com/features/) and see how they compare.

I haven't tried, but I believe that you can actually install both plugins side by side (using WPGraphQL's single endpoint, and my plugin's Custom Endpoint under a different route), and using the same GraphQL queries to test them, check their speed, usability, security mechanisms, configuration, extensibility, and anything else that could be relevant for your project.

I did use wpgraphql with worddpress but it is also good to see something new popping up. I will give it shot in my future projects.

Why is the years of development or the number of commits relevant? It feels like there is an unstated incentive at play here? Are you trying to get hired?

I think it's an attempt to convey the level of effort involved? Seems like an even worse measure than lines of code.

It's the kind of metric I'd use if I wanted to convey how much time was wasted on something.

> I think it's an attempt to convey the level of effort involved

Exactly this.

Also it's a way to point out that I took no shortcuts. When you have a deadline with a client, you start dropping features out, and adding @todos to fix something sometime in the future. Since this is my own project, I took the decision to do it well, at the cost of needing extra time and effort (eg: adding hundreds of tests, making services injectable and reusable, etc). The payoff will come in the future as the codebase proves to be more sustainable, and I require drastically less effort to maintain it.


Why be like this

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact