As someone who works in tech, I'm often asked to "build a website".
When asked this question, I always try to learn a bit about what they expect the website to do.
What a non-tech person means when they ask this question is usually:
- Someone types a url into a browser, and sees something special that works as well as other websites but looks more unique and personal than something like a template.
- The content on this website follows some common patterns. There's an about page or similar, a listing page containing a potentially infinite, but realistically quite small, list of objects. Maybe they're posts, photographs, or items for sale.
- Search, if it exists, is quite small. It's not often that someone asks for their content to be globally full-text searchable.
- Being able to update the content whenever they like is imperative. They don't want to learn a complicated system, they would prefer that it were as easy as posting to Facebook.
I've spent a lot of time, in short durations but over a long period of time, trying to build a system that satisfies these requirements, but is neither expensive to maintain nor complex to use.
This blog is one of the attempts - and in this case, I attempted to delegate as much as possible to an existing, maintained system (docusaurus). However, the approach I used here requires fairly strong familiarity with github and markdown, but passes the cost and simplicity requirements with flying colors.
One approach I took to this was quite involved, and used the following setup:
- Parcel to build the frontend
- Hasura (running on Heroku) for the database (which is Postgres under the hood), API, and authentication layer
- GraphQL queries for CRUD between the frontend and the database
- Docker Compose for running Hasura & Postgres locally
- Netlify as a CDN, for DNS management, and for serveless functions, which are primarily used for generating JWTs.
The goal here was to leverage a shared db to scale this model fairly cheaply, but still has the downside of authenticated transactions on every load. Scaling this could be potentially problematic at the DB level (although realistically, I'd expect the audience of this product to be relatively small). But most of all, it just felt very heavy weight for something that was supposed to be small. It's an interesting idea for something maximally complex, but I realized that the core interaction needed by the person adding content to the website is just the ability to organize lists, add objects to the list, and update content on static pages.
This blog has nearly the same interaction, but since it's built on docusaurus, has a bunch of unrelated and difficult to modify features.
After deciding the above approach was too complex for the problem it was solving, I started thinking about a much simpler CMS that follows some common yet new patterns in the industry. It would be composed of the following pieces:
- The website would be entirely contained in a git repo. All content would be represented by static files in a human-readable format.
- When the content changes, a CI job (Github Actions) would compile it to a static website.
- Netlify would act as a CDN, and handle DNS.
This is how this blog works, for the most part. The DSL is markdown, and this site isn't very flexible in terms of object types. Pretty much only blocks of text are supported. And it still has some problems:
- You have to know how to use Docusaurus to modify the layout, which leaks to React, Babel, and Webpack knowledge.
- You have to be able to confidently edit the content in a git repo (alongside the source) and generally understand git to update it.
So, I think the simplest CMS would add two personas to the stack:
- The site would define one or more editable schemas that define an object type.
- The site would define one or more simple html layouts and a page layout. The simplest and/or most common templating language should be used here.
- The site would provide a dedicated interface for adding new files to folders corresponding with the schemas defined at the site level. These would produce the listed objects that the above talked about.
- The site would provide a dedicated interface for editing page-level content.
When complete, the goal of this project would be to allow a person with mid-level knowledge of html and git to create a website that was completely custom, with simple schemas. This allows for maximal flexibility while still keeping things relatively simple.
If the site is set up in a standard way, a single desktop/mobile client or website will be able to connect to this git repo using Github OAuth or standard ssh/https git authentication, and edit any website built this way. It would simply edit the schemas defined by each website, and central documentation would track the available scalar types for each of the schemas.
The HTML would simply layout and render the content of the schemas based on their scalar types, but the scalar types can expand to be quite complex, for instance media players or observable notebooks could be embedded using simple definitions.
The build step could be centrally developed and versioned, allowing the boilerplate for this type of website to be very cheap.
Finally, since this repo will be a simple static website, it can be deployed to any of the myriad static website hosts that are available, making administration of some of the harder parts of DNS and CDN quite manageable to someone with little knowledge of the underlying systems.
It's possible that I won't build this. But if I do, I'll need to choose some initial parameters:
- Which static site host to target first (probably Netlify)
- Where to run the shared generation code (probably Github Actions)
- Which html templating language to use (unsure)
- How to build the client (Web tech with WASM bindings for shared business logic if it gets complex)
- What scalar values to support
- Where/how to build the docs (probably just use the same tech as the CMS)
If and when I make progess, I'll update this blog.