What is the problem to solve?
Drupal Core's JSON:API module and the related JSON:API module ecosystem has experienced strong adoption among those building decoupled Drupal sites. There has also been substantial growth in JavaScript community projects that depend on Drupal's JSON:API implementation. While those projects differ in a variety of ways, they all share at least one common need - easily interfacing with Drupal's JSON:API endpoints. This has resulted in many different implementations solving this need with large amounts of overlap, and very few shared solutions.
A non-exhaustive list of projects that include some form of client-like functionality for interacting with JSON:API includes:
- Druxt - https://www.npmjs.com/package/druxt
- Next For Drupal - https://github.com/chapter-three/next-drupal
- Drupal State - https://www.npmjs.com/package/@gdwc/drupal-state
- Drupal JS SDK has https://www.npmjs.com/package/drupal-js-sdk
- https://www.npmjs.com/package/nuxtjs-drupal-ce
- https://github.com/jsdrupal/js-client
- https://gitlab.com/VoidE/drupal-sdk
- Almost certainly more - please add your project in the comments :)
And this list doesn't even include specific decoupled site builds, many of which have at least some custom code to interact with JSON:API.
There have been previous attempts to solve this problem, and semi-recent discussions about renewing efforts to address this (much of this proposal is inspired by previous discussions with @deciphered.) I believe it is time to make new concrete steps to solve this problem.
Who is this for?
There are two primary audiences:
1. JavaScript developers who are consuming Drupal's JSON:API endpoints and would prefer to use a sanctioned Drupal solution to make this process easier. Of specific note within this audience are JavaScript developers who may not have deep existing experience with Drupal or the JSON:API spec.
2. Project maintainers within the Decoupled Drupal ecosystem who would prefer to spend less time re-solving common problems and more time pushing Decoupled Drupal forward.
The Result
Assemble a team of interested contributors who commit to developing a JSON:API client will be published under the @drupal namespace on NPM. This project will be able to be used as a dependency both for specific decoupled builds, and other decoupled ecosystem projects that interface with Drupal's JSON:API.
How will we know the desired result is achieved?
Downloads of this package reported on NPM would be a metric that indicates adoption. Strong adoption would also hopefully result in this package being listed high in the results when searching for Drupal on NPM. If this project is successful, there should be a reduction in projects that develop bespoke solutions to communicate with JSON:API, although this will likely be a more difficult metric to measure.
Why Now
I believe there are a number of reasons that make now the right time to renew these efforts.
- Accelerating innovation in the Decoupled Drupal JS ecosystem - If this effort can provide a desirable solution for interfacing with JSON:API, developers can focus more time and effort on the things that make their particular project unique.
- Prior art - reaching consensus on the functionality and format for this client will be difficult, but common patterns in projects that implement client-like solutions should help support decision making.
- Developing a repeatable pattern for 'official' JavaScript projects maintained by the Drupal community. The decoupled menus initiative and specifically the creation of the general project type has has an important impact on the the ability to create Drupal-adjacent community projects, but the path to any of these becoming 'official' Drupal projects (think more core, less contrib) still feels undefined. Most projects that fit this classification are either used by, or directly related to Drupal Core. A clearer path here could inspire more formal community efforts. Imagine an official collection of React utilities, or an official GraphQL client, etc.
- Sending a strong signal to the JS community - I continue to worry that Drupal has a perception problem with the JS community at large. While it is clearly not the only indicator, I think that searches on NPM tell a story here. Searching for Drupal results in a somewhat confusing set of packages, and it is unclear what if any are provided by the Drupal project. Those who know to look for the Drupal organization will only see two narrowly focused packages. A search for WordPress results in a client, and many packages under the @wordpress namespace. I'd imagine much of this is driven by the block editor, but it still could provide the perception that WordPress is serious about JS. Searching for Contentful provides a clear set of utilities, including packages to help consume data from Contentful. Contentful may not be a fair comparison here, since it is a completely headless CMS, but that doesn't change the fact that JS developers familiar with Contentful may have the expectation that any CMS they work with should have an official set of packages for them to take advantage of. I believe that offering more packages under the Drupal NPM namespace will help provide the signal that Drupal is JavaScript friendly.
Thoughts on potential approach
Determining the approach would primarily be the responsibility of the initiative if this moves forward, but here are a few concepts that I consider important:
- This package should be framework agnostic so that it can be used with any JavaScript framework or none at all.
- It should be possible to use both on the client and server.
- It should make underlying utilities available so that they can be adopted individually or incrementally without requiring the entire client.
- The client should provide a default solution for fetch, but it should be possible to provide a compatible alternative.
- The client should provide a default solution for storage / state management, but it should be possible to provide a compatible alternative.
- The client should be written in TypeScript, but it should be possible to use the client without using TypeScript.