
Introduction
At Seattle startup studio Pioneer Square Labs, we choose pragmatic stacks for our SAAS startups monthly. I’ve been a proponent of the NERP stack, since Javascript (in particular React) is a common feature of the stacks we’ve seen in 2020. We are establishing best practices with Javascript client and server development, and also evaluate “low code” options where it makes sense to go fast.
One key requirement is an admin editor to allow business users to edit select data in the primary database. Strapi is appealing because – while it is intended as a headless CMS – it uses an extensible Node stack with just the right amount of complexity. Strapi has a good feature set for creating schema, hosting media files, and providing an API. The investigation below attempts to figure out how much or how little we should use Strapi’s features in our default NERP SAAS stack.
As of this writing, we are still trialing Strapi on an internal app. We haven’t deployed it with a startup yet, but we likely will in the near future.
Should we consider Strapi as part of our default stack?
Pros
- Strapi is NERP stack (Or, as they’d prefer: JAMStack)
- There’s decent documentation, some light plugins, and active community
- $10M in funding so will hopefully have support for a while
- Customizable using React + Javascript with a small commitment to learning Strapi and its APIs.
- Setup was easy, the tools seem to work decently for defining & deploying schema.
Cons
- It’s not TypeScript (not sure if adopting typescript is on Strapi’s roadmap)
- It’s primarily a headless CRM, not an admin panel or an app building framework, so… its feature set may drift over time. However, given the funding, I’m guessing they’ll head in a broader “no code” app platform direction.
- The Strapi docs while complete, are a bit out of order, and could use some love.
Will CTO’s hate us for using Strapi?
I don’t think so, subject to answering the architectural questions below in the simplest way possible.
Pros
- The all-node stack (and skillset) is consistent for engineers to learn
Cons
- Strapi is not ubiquitous (nothing is ubiquitous in the JS world), so it will be new to most CTOs & employees.
Should we use Strapi to define schema?
Pros
- It’s easy for developers to create new tables, columns, and relationships via the Strapi UI (in the dev environment)
- Strapi will replicate those schema changes in whatever environment its deployed to
- Has support for JSON columns
Cons
- Still requires a developer
- Strapi will intentionally not delete tables or columns
- Will not produce migrations
- UI a little clunky around relationships
Should we adopt Strapi to edit data (using admin web site)?
Pros
- Easy for any user to enter data, decent modern interface.
- Customizable (with some effort)
- User-configurable support for calling webhooks when data changed by admin
- Has funding, sufficient docs
- Once configured, should handle uploading content images
- Strapi supports social login with Google, Facebook, and others.
Cons
- Email integration lacking (eg. can’t automatically trigger an email when something added without writing code)
- No built in BPM features (just need to learn the simple Strapi project to hook in your own).
- UI a little complicated around identifying related data (not as slick as something
- Customizing the UI (for example replacing the logo) requires effectively ejecting each file (or function?) that you want to customize one-by-one. Which is a reasonable approach, just seems like it could incur tech debt as Strapi evolves.
- Strapi doesn’t seem to allow non-nullable foreign keys. An insert via the admin interface appears to require two steps: first insert the row, then fill in the primary key. I had an issue creating data via admin in a related table that I created outside of Strapi. This is a feature we should request.
Should we use the Strapi API from our React client (instead of our own API)?
Pros
- Strapi provides User table and secured login APIs
- Stapi’s default generated APIs offer a more robust set of parameters (for example _limit, _start, _contains on every GET request) than we’ve yet implemented in our boilerplate NERP project.
- We could get rid of our “shared” models project (since server models unnecessary)
- Can extend Strapi’s bookshelf models as necessary
- Uses the bookshelf ORM (Knex based), so at least data access pattern is established
- Strapi also supports GraphQL if you’re into that
Cons
- If we commit to using Strapi (and simplify by removing our own server code), then need to fully learn & review Strapi stack for stability, security, and extensibility.
- The main Strapi user table has a less than ideal name since the functionality is provided by a Strapi plugin (users-permissions_user). The Strapi model name is just “User” though.
- Strapi API returns data fields with names exactly as they are in your database. This is reasonable, but if you prefer snake case field names in the database, and camelcase names in the API, it’s not supported as far as I know.
- Weird/hard to use both custom + Strapi endpoints from client because authentication paths are separate. Maybe we should customize Strapi’s JWT validation to support an API token https://strapi.io/documentation/v3.x/guides/api-token.html#introduction that either the client or server can use (could proxy request through).
What other alternatives did we consider?
Forest Admin looked to be just the ticket for what we needed, but after getting it running, the nagware to upgrade (starting at $250/month) was a real turn off. There were hooks into the installation requiring a user account with ForestAdmin.com, so it didn’t feel like actual open source software at all. Hopefully Strapi doesn’t follow suit.
Ghost JS is a mature node-based publishing platform with lots of plugins. Think WordPress but with Javascript. If you had a strong requirement for publishing web content, Ghost would be a good choice. While it’s very extensible, I couldn’t find documentation on how to add custom tables without writing custom code. So, it makes a great page editor, but doesn’t satisfy the generic admin requirement.
Airtable is another choice with an excellent UI for defining and editing data, then retrieving it via an API. However, you’re then committed to using Airtable as the primary database, and it gets expensive once you store a significant amount of data.
Google Sheets is another tool we frequently integrate into low-code solutions. But a spreadsheet isn’t a database.
Summary
Here’s my current workflow for exposing data for admins to use, and React to access via an API.
- Create a Knex migration in our custom node server project.
- Create matching client, server, and shared models.
- Our current boilerplate project provides very basic generic REST API endpoints for server models, but you can add custom controllers as desired.
- Optionally, define Strapi content types for the tables you want admins to edit. This can either be done in code in code, or via the Strapi Admin UI running in development mode.
If you want to go very fast – using Strapi for schema and API is a viable option. You can skip migrations, and use Strapi as your API server. However, if you want more control (envision Business Process Management requirements, or interesting scripts) and typescript built in it is probably best to write a separate Express server and just use Strapi as an admin.