I decided that I want to have my own blogging platform that I feel comfortable writing on. It should have these properties:
- Simple and clean.
- Both public and private spaces. Sometimes I don't really want to share a post with the public but only people who are interested in a specific topic - so a private space is necessary.
- Interpretable data. My content should belong to myself, be stored in a human-readable structure and interact well with existing tools. Relational database is an option, but I like Git more.
- Topic-centered, or "idea-centered" content organization.
- Collaboratable. When I work on ideas with my friends we want to share a common place to write.
Although maintaining my own infrastructure is fun, its complexity mismatches with the goal to keep the system simple. I would have to deal with infrastructure security/stability/scalability issues myself, and that's time-consuming work.
Fortunately this year is 2021 and we have nice serverless and SaaS platforms. I decided to use as many of them as possible:
Hosting: Frontend on Cloudflare Workers, submission control service on AWS Lambda.
Storage: GitHub as the single source of truth for all online data, DynamoDB for content hold by the submission control service, and Workers KV for caching.
Discussions: Cusdis.
Email: Sendgrid for receiving and Mailgun for sending.
Profiles: Gravatar.
Managing content
To make a blogging platform useful there needs to be a way to add, edit and delete content, and the submission control service is my solution to the problem. Instead of building yet another Web CMS , why not just put together all the awesome things we already have?
- Email works well as a control channel. Today's email clients are fairly good at sorting and classifying information, and existing applications integrate well with emails through attachments and sharing.
- Markdown is a nice language for writing. It keeps you focused on the actual content instead of formatting, and there exists many awesome Markdown editors.
I use Typora and Taio to write in Markdown, and when I want to publish it's as simple as sending the .md
file to topic-name@x.univalence.me
. Then Sendgrid parses my email and notifies the submission control service on Lambda through a webhook.
The service then checks and renders the post, and replies with a link to the preview.
If the preview looks okay, I reply to the preview with /we publish
. The service then commits the post: call the GitHub API to create a commit. After the commit is pushed a GitHub workflow is automatically triggered, notifies the frontend service on Workers to update its cache, and sends notification emails to subscribers.
The stack
- marked is integrated to the submission control service to render Markdown content to HTML. The HTML is then rewritten on the edge to support features like preview spellchecking, link-to-reference conversions and LaTeX.
- On the frontend custom CSS rules are applied to produce the visible output. The styles are heavily inspired by the wechat-format project!
- The system is mostly implemented in TypeScript, and esbuild is used to build all the three JavaScript bundles for Workers, Lambda and Workflow.
- Handlebars templates are precompiled into JavaScript and evaluated on the edge to build pages.
- Rust and WebAssembly are used to process emails, validate input and minify pages.
- LaTeX content is rendered through the Math API service.
Modern frontend?
I avoided using frontend JavaScript unless necessary. Pages will work with JavaScript disabled except these features:
- Subscription. Confirmation emails can be used to spam people, so Recaptcha is used to verify that a real user is sending the subscription requests.
- Code highlighting. This is implemented with highlight.js currently, but I want to render the highlights on server side eventually.
- Discussions. I use Cusdis to manage comments and the service requires JavaScript.
Open Source?
The system is not yet open source, since it's a bit dirty - hardcoded strings, tightly coupled logic across Workers and Lambda, etc. I'm looking forward to making it open source when everything is ready!
Discussions