What are the key differences between KeystoneJS and Strapi as tools to create CMS-driven apps?

Not to familiar with KeystoneJS but from the look of it they are very similar. Strapi looks like it has a more extensible API but overall its the same concept. I have used Strapi for several projects and it's fast to work with, you can have Strapi up on Heroku with a fully built schema in less than an hour.

One thing between the two is GraphQL support, Strapi is making a significant push to get involved in GraphQL world, I believe in-order to keep up with Tipe.io.

Setting up GQL + Strapi + Nuxt / Next is wonderful for creating a SSR application.


I've been enjoying working with KeystoneJS v5 for over a year on multiple projects. I had the same question as you and I picked Keystone over Strapi (even when git stars and community were higher) because I was looking for a simple file based Backend Generator.

This line express it: schema => ({AdminUI, GraphQLApi}).

I needed to quickly define (and later easily modify) the Information Arquitecture of my backend, and seen it reflected automatically in a CMS and the API.

(Strapi users, correct me if I'm wrong) I saw that Strapi had more focus on building a Drag and Drop (no code) way of building this backend. I couldn't find a straight forward way of using Strapi with files and get the CMS and API I was looking for. Seemed to me that was built for people that wanted a backend, but didn't wanted to write code.

I rather use my code editor functions (find/replace, multicursor) to define and modify my schema than a Drag and Drop components on the browser. Also use previous projects as my based code to build new ones.

My keystone projects get a really simple file structure where most comes out of the box and making custom mutations, AdminUI components, hooks, and data seeding was really simple.

Here is an example:

├── index.js  // imports entities, hooks, initial-data, submodules
├── initial-data.js // imports seed/index.js and orchestastes how to create data 
├── entities // for each entity (list): field types, access control, hooks, adminUI configs
│   ├── index.js
│   ├── Users.js 
│   ├── Books.js
│   ├── Loans.js
│   ├── Authors.js
│   ├── ...
│   └── Categories.js
├── extendGraphqlSchema // pretty easy to add new custom Graphql types, mutations and queries  
│   ├── index.js
│   ├── types
│   ├── queries
│   └── mutations
├── hooks 
│   ├── index.js
│   ├── user_beforeUpdate.js
│   ├── book_validateInput.js
│   ├── ...
│   └── loan_afterDelete.js
├── keystone-media-server // submodule I use on many Keystone projects
│   ├── adapters
│   ├── fields
│   ├── lists
│   ├── resolvers
│   └── seed
└── seed // list of functions to create a complete data example to test
    ├── index.js
    ├── createUsers.js
    ├── createBooks.js
    ├── createLoans.js
    ├── createAuthors.js
    └── createCategories.js

At the time of this writing (nearly a couple years after this question was posted), Keystone 5 is oriented around graphql, so that is no longer a prime differentiator between the two. Keystone 4 is still being maintained as a REST-first framework.

Strapi is GQL-first now and has a larger community.