About Preaction CMS
In the late Fall of 2018, I began working on the project that would eventually become what I called Preaction CMS. I've been describing it as a "barebones, extendable CMS built on top of simple JavaScript libraries."
"Simple" could probably be replaced with "predictable". It is a hodgepodge of the most predictable javascript libraries that one might choose to build a CMS in the year 2018.
I'm talking: Node, Express, Sequelize, SQLite, React, Bootstrap, Axios, SASS, Webpack, Jest, ESLint, Prettier. The most usual suspects. It is also using the Quill editor for WYSIWYG editing.
One thing I've done to make things harder on myself is that I keep its dependencies updated just for the sake of it. If you could imagine someone trying to glue together a CMS "the Arch way", using the most milquetoast modern library choices, and making absolutely no promises for stability nor backwards compatibility, that's what I've tried to accomplish here. It's a CMS for the independent developer who likes to stay on the bleeding edge of software.
I just wanted a CMS that a modest developer like myself could wrap their head around entirely. It has been wildly successful. By that, I mean I'm fairly certain I am still the only person using it in production, but the fact that it hasn't failed me yet is a wild success. It has survived upgrades from Bootstrap 4 ➡ Bootstrap 5, React 16 ➡ 17 ➡ 18, and more. "Survived" as in the upgrade path wasn't daunting to the point of forcing my surrender (although there were some close calls).
It has some great features! ✨
- SSR by default
- Cached responses with automatic warming
- Optional Google Analytics
- EXIF data removal for image uploads
- Sitemap.xml generation
- Socket.io-induced automatic page reloading
- WYSIWYG editing
- Extensions for both backend and frontend
- Path-specific settings
- Redirect management
- Feature parity between desktop and mobile
- Support for non-empty root path
- Unit tests on both backend and frontend
- Database backups for every write operation, and a restore feature as well
- It's also an SPA, and it selectively reloads only the parts of the page that need to change when you navigate
Backend extensions are as simple as writing an express middleware function with the (request, response, next) signature. Frontend extensions are just React components. Custom style overrides can be done in SASS or just plain CSS.
Keeping in mind that there's nothing keeping you from writing an extension that does something really stupid, it's reasonably secure. It uses bcrypt password hashing. CSRF protection. Randomized admin PW by default. Signed cookies with a randomized cookie secret by default. Support for SAMESITE=secure. It also has a read-only mode, which disables all admin-required and CSRF-protected middleware.
It scores well on Lighthouse tests. The only category I would say could use improvement is on mobile performance. It doesn't score too well there, although I don't notice any performance issues in my personal experiences. When I view one of my sites on mobile, it works a lot faster than most other sites I visit. 🤷
There is good reason for that too. Like I said, it does SSR and pre-warmed cached responses by default, and does a fine job of delivering content to browsers without javascript. For the javascript itself, the main bundle delivered to users is just 133 KB gzipped. Accessing the administrator functions will give you bundles which amount to to less than 100 KB of additional gzipped javascript.
At work, I'm using this as a technical foundation to build support websites for Higher Ed institutions. The extensibility has allowed me to build a template site which the backend can use in combination with an internal database to have hundreds, potentially up to thousands, of client-specific sites all running from the same instance.
Anyway, this website, https://dougelkin.com, is a live instance of Preaction CMS. You can find the source on Github.
Building a CMS from scratch is not exactly something I want to do again, but I have found joy in this project. It has come a long way, and I think it still has plenty of potential. Follow me on Fosstodon to stay up-to-date on my thoughts of this project.
~ Doug