Home
Blog
CV
Projects
Patterns
Notes
Book
Colophon
Search
RESTful CMS
I chose to implement this in Go and PostgreSQL because a nice side effect of that tool choice is that once you have PostgreSQL running you can deploy everything by simply copying the cross-compiled go binary to the machine, having cron run the binary every minute in case it crashes. Migrations can be handled as part of the start-up process.
What worked:
- Pretty much everything, it is a very nice, simple system that has automatic, inbuilt caching because of the dependency management.
- I use PostgreSQL users for HTTP logins, rather than having a separate users table
- Fully RESTful with correct status codes and responses returned in JSON or HTML based on the
Accept
header
- Silk for markdown-based HTTP testing (a few rough edges with it)
- A wrote a Python script to parse my old site and populate the database with HTML content as well as static files, handled via their sha1-hash.
- Go's built-in HTTP/2 support and TLS
- Using an INI flags library so that command line flags can be put into a config file if there are too many
- Supporting a name and path for each site rather than just a URL, and
- The automatic tracking of page moves and the HTTP redirects
- The automatic 304 etag caching
- Full text search and results highlighting based on PostgreSQL
- Having an
-etagPrefix
option to prepend to all etags to force all browsers to forget content during testing, even if the underlying data hasn't changed
Decisions I made that I'd change if building again:
- Having all foreign keys to a parent table in a single place - I thought this might make the PostgreSQL triggers simpler, but it doesn't really, and it confuses other tools that you might use directly with PostgreSQL.
What would I recommend now instead?
- Unless there is a particular need for having a full revision log or full dependency tracking, I don't think the cache benefits alone make this useful enough. You can just use Varnish and purge it whenever you guess something might change. Most use cases can handle 10x the extra requests you might make anyway. For a use case where the dependency tracking is important, and where you genuinely want a REST API rather than just JSON over HTTP, this works really well.
In other words, this is a simple, elegant solution, but might not be the easiset option for most common use cases on the web.
Are any companies now doing the same thing?
- Contentful is building a CMS as a service, so yes.
There are also some standard docs I like to put in place:
- https://bitbucket.org/thejimmyg/cbl/src/fb3869c1df0ee7d4c40a9718aee11c31e0a92476/docs/business/?at=master
- https://bitbucket.org/thejimmyg/cbl/src/fb3869c1df0ee7d4c40a9718aee11c31e0a92476/docs/technical/?at=master
As I'm sure you know, I've been building web sites for years (decades almost), and I enjoy playing with all the tradeoffs different designs have.
As an experiment I wanted to see if I could build a CMS with the following properties:
- Very thin application layer, all important things handled in the database
- Every page knows its dependencies in their various tables so that it knows when it has changed
- Etags returned for every page since we know when any page has been revised as a result of its dependencies changing
- Tracking of the hostname and URL path of every page so that if pages are moved, and nothing replaces them, the user can be redirected to their new location
- Full JSON revision stream of all changes so that external systems can be notified