Anything worth doing...
I’ve been wanting to blog more, but it’s always seemed like such a hassle. I appreciate the speed and flexibility of statically-generated sites, but the authoring experience around them isn’t that great. On the other hand, the authoring experience on hosted solutions (like Wordpress or Medium) is fantastic, but you lose a lot of the speed of a static site, and the ownership becomes more murky.
When I sit down to write a blog post, I don’t want to think about all the minutiae that goes in to keeping my blog up and running; instead, I want to be thinking about the content of the post.
What I really want is an authoring experience that gives me native Mac (and ideally, iPad) apps, but that works with my static site files. I’m willing to do the odd git commit
and git push
commands to actually publish the content, but I still want things like spell checking, drag-and-drop to embed media, and so on.
For a long time, it seemed like there was never a happy medium, and it’s something that occasionally rears its head and results in a frustrated tweet:
It’s that time of the year again where I’m discontent with my blogging setup and nothing out there seems like a good solution.
— Dave DeLong (@davedelong) June 13, 2020
This time around, I had an idea and decided to run with it.
First, I’m a big fan of indie software and in particular, I’m a long-time user of Daniel Jalkut’s great app MarsEdit. Yesterday I was poking around in the app and I had one of those ideas that seems crazy enough to actually work.
MarsEdit has support for a bunch of standard kinds of blogs, like WordPress and Tumblr, etc. But the real power behind it is that it’ll work with any blogging system that uses one of a few standard kinds of APIs. These APIs tend to be of the “XML-RPC” variety.
This got me thinking… what if I exposed my Jekyll blog via an XML-RPC interface? Then I could add it in MarsEdit and write and edit posts there. I’d get all of the features of the MarsEdit authoring experience, but the benefits of a static site that I rather enjoy.
So, the past 36 hours have been a frenzied coding storm of me writing a Swift package that implements an XMLRPC server to serve up the source files of my website, all so I can write posts in MarsEdit.
As it happens, it works really well. I can write in Markdown, I can drag-and-drop images, I can save and edit posts as published or drafts, I can alter tags, edit HTML, and do just about everything I want to do with the content of my site without worrying at all about making sure I get files in the right folder and naming them correctly and manually resizing images…
I have created something beautiful and terrifying.
— Dave DeLong (@davedelong) June 14, 2020
Details forthcoming.
As is typically of my side projects, this one follows my side-project philosophy:
Anything worth doing is worth over-doing
I ended up building an entire XML-RPC Server, including custom XMLRPCEncoder
and XMLRPCDecoder
types so that I can write the actual request and response objects as normal Swift Codable
structs. I started off only focusing on the MetaWeblog API, but it turned out to not be quite descriptive enough for my purposes (it doesn’t have a way to describe post tags, for example).
So, because I had this massively over-engineered system in place, I was able to quickly add support for most of the Wordpress XML-RPC API with structs that look roughly like this:
enum Wordpress {
struct GetPost: XMLRPCMethod {
typealias XMLRPCMethodResult = Post
static let methodCalls: Set<String> = ["wp.getPost"]
let username: String
let password: String
let postID: String
func execute(with site: JekyllSite) throws -> XMLRPCMethodResult {
return Post(try site.getPost(postID))
}
}
struct Post: Codable {
let post_id: String?
let post_title: String
let post_date_gmt: Date?
let post_type: String
let post_status: String
let post_author: String
let post_content: String
let terms: Array<Term>
}
...
}
I’m very pleased with how this has turned out. It’s been a great weekend project, and it’s made it much simpler for me to blog again. So, hopefully, expect to see more posts from me in the future.
And sorry, this code will likely not be open-sourced. I’m offering it to Daniel, so maybe a future version of MarsEdit will have support for this sort of thing natively (but you’ll have to pester him about that).