VaporCMS
The greatest content management system that will never exist
Overview
WordPress is a huge success but could it be done better? Maybe being more opinionated would help with consistency and / or simplicity. I don't really like PHP so that's gonna go. This initial sketch is going to use Python / Go but it's just a PoC. PostgreSQL is going to be the database (no ORM, but will have a storage facade). All state lives in the DB, nothing lives on the file system (stateless web servers, caching will play a role). In general, HTML rendering will be handled by the server.
Design
The core system is nothing more than a bare-bones set of relationships between the primitives described below. The expected "baseline" functionality of the CMS will be implemented as a set of pre-defined plugins that ship with the system. This ensures that the plugin design is flexible enough to meet most requirements. The page builder, plugin manager, user manager, etc will all be implemented as plugins.
Wouldn't that create a chicken and the egg problem? It would if these baselines plugins didn't ship with the application. They can always be replaced by others if desired (a diff page builder, for example). These are some intense dog-fooding goals but I think they are critical to get right. This project strives to achieve a similar level of design efficiency and orthogonality as the level design in Dark Souls 1.
Primitives
These are super important and should be selected with great intention. In no particular order:
- Page
- flexible
- open-ended
- what combo of HTML / CSS / JS?
- how can they refer to other "partial" page templates?
- how do you link up the jinja template data?
- default set + custom models as needed?
- page "types" like django? DetailView, ListView, etc? map to a model?
- Form
- represents data to be sent to the application
- independent of a particular design / layout
- just the field names, types, etc
- Route
- maps URLs to Pages
- Model
- Record type of data that the site cares about
- User, page, form, route, etc (defined by core plugin)
- Relationship as separate primitive? Or defined within models?
- Should I leverage an ORM based on this? SQLA? Peewee? GORM?!?
- Plugin
- allow for near-arbitrary customization of appearance and behavior
- can be dragged and dropped in as a bundle (like WP)
- written in Python / Go
- can contain static files (HTML / CSS / JS)?
- can plugins define pages at all? or just models / behavior?
- isolated: separate / sub process? container w/ a REST API?
- require Dockerfile / plugin.yml to be in repo root?
Plugin API
Super rough sketch:
GET /
- Return plugin metadata: name, version, models, implemented endpoints, etc
Model API
This is based on Kong's DAO concept. Each custom model definition will generate the following endpoints:
POST /
- Create a new record/ GET /
- Get all records/ GET /
- Get a record by primary key/:id PUT /
- Update an existing record/:id DELETE /
- Delete an existing record/:id
References
asyncpg
starlette
uvicorn
Docker SDK for Python
Django-based CMS
Kong Plugin Structure
Kong Plugin DAOs
Kong Plugin DAO API
Kong Plugin Basic Example
Setup
This project uses PostgreSQL for persistent storage. To develop locally, you'll an instance of the database running somehow or another. I find Docker to be a nice tool for this but you can do whatever works best.
The following commands start the necessary containers and define environment variables that the app will look for:
docker compose up -d
export VAPORCMS_DATABASE_URL=postgresql://postgres:postgres@localhost:5433/postgres
You'll need to run the initial migrations, too:
psql $VAPORCMS_DATABASE_URL < create.sql
These containers can be stopped via:
docker compose down