Ghost: Meeting Halfway

In A Past Platform...

It’s strange thinking that during high school I played around with setting up WordPress on a free host... then, several years later, only to end up building Squarespace websites for clients at work. But with that, I’m able to see and compare the merits of both.

For a start, “user friendliness” with both of them are top notch.

WordPress has been the standard for blogging; there’s a whole business out there centred just around developing plugins. Editing content is just like as you would for a forum, being able to switch freely between WYSIWYG and HTML source. It’s just that, for my site back then, I didn’t need something that robust, not to mention that the resulting HTML content had a lot of bloat (at least that was the case back in the day).

Squarespace is, uhh, good looking. Pick any theme, and you get designer vibes out of the box.

...Okay, no, hold up. So, you know how when someone says they’re “trying to phrase [something] in a considerate way”, they’ve actually just established that they’re not? So, I’mma say it straight.

It’s, in most situations, a professional solution for those who need the online presence and (emphasis) don’t have access to tech know-how to do so, be it themselves or outsourcing someone else. To achieve that landing page look without ever touching code, they use a drag and drop interface which comes with a handful of components.

That’s great – except for when (even Ghost throws shade[1] at this) you want to line up and lay out content right[2]. If you know, you know.

Keep in mind this isn’t “just Squarespace things”, it’s a side effect of drag and drop. It exudes similar vibes to, say, developing apps in Android Studio – it’s not rare to watch the XML file lay out your items via the visual editor in the most chaotic way possible. Just tell it exactly how you want it via the XML without beating around the bush. Simple.

Introducing Ghost

One of our rhythm game friends runs a game info site using Ghost, and I was impressed by how simple and clean (HTML-wise) it is, even when it’s running on the default theme with very little customisation, if any.

Ghost employs Markdown to author content. The appeal of a no-overhead plain text format, and not being shackled to one app[3], are perks I can really appreciate.

Like Squarespace, there’s a repertoire of useful components as well – the most practical ones being the Markdown block and HTML block. What this means is that if there’s anything that the editor can’t handle, don’t worry, fam – these two gotchu.

In between

You might be thinking why there’d be a Markdown block if the Markdown-based editor’s supposed to do that job.

That’s because, frustratingly, the editor falls short of anything advanced. For instance, hitting Tab inside a list... inserts an actual tab, instead of making it a sub-entry.

It’s during these times when the Markdown block will do the trick – however, that does mean you lose the WYSIWYG experience, in the sense that you’ll have to flick back and forth between Markdown and the rendered result. (Don’t forget you can also place HTML tags in Markdown, too.)

This makes the editor seem like it’s a hybrid of WordPress and Squarespace. It has WordPress’ WYSIWYG feel (though to be fair, Ghost and WP are both writing-focused platforms). Plus, it has Squarespace’s authoring methodology: if in doubt, welp: just chuck it in an HTML block.

Of course, I’ve had a real case of this: my previous workplace’s webpage is a Squarespace site, but me and our designer had strict visual guidelines so that spacers were the only Squarespace related parts we ended up using; all the actual content was built entirely out of HTML blocks.

Moving back to Ghost’s Markdown editor, here’s one feature that’s missing that you’d otherwise thought would’ve been standard for a blog: tables.

Oh man, tables

I’m aware they exist in Markdown. Reminiscent of ASCII art, you draw one up yourself using pipes, dashes and optional spaces so it looks kinda sane[4]. Yeah, it’s a slight hassle, but that’s not my main problem here.

Whilst creating my Games Backlog, I came across two problems:

  • You can make a header row, but you can’t seem to make a header column. The workaround is to manually mark the content in each header cell bold.
  • Unless you use HTML, not surprisingly, you can’t have newlines in cells. So in my case, to put a list in a cell, I’d need to peruse ul or ol.

Do you really expect me to manage an ASCII art table with HTML code where I’m not allowed to place newlines?

And so, my impression of Ghost being a WYSIWYG-lite HTML-in-doubt editor strengthened ever more as I...

Resort to JavaScript

At this point, I decided to revert my tables to HTML since I could use table headers (th) to properly create my header column.

First, I create the table itself (a canvas, if you will) with just the header row:

<h2 id="continuous-main" class="vis-hide">Continuous/Main</h2>
<table class="currently-playing vis-hide">
the vis-hide is there so the incomplete table is invisible until it’s been populated – if it ever does (e.g. js disabled)

The contents of these tables were stored in a JavaScript object – much easier for me to handle at this rate compared to Markdown.

const currently = [
  [ "maimai [Casual]", "’22-03", "13.9k" ],
  [ "原神 (Genshin Impact)", "’20-09", "AR 58" ],
  [ "SDVX [Inactive]", "’20-01", "[VW] 14.74 / SL9" ],
  [ "ITG", "’09",
      "20 220 (Caprice / Oh Henry!), now considered a 19",
      "20 206 (JackOff Marathon / Cranked Pastry), debated 19+",
      "20 200 (Spacetime / Psychedelia 2)"
if the third item is an array, we’ll assume it’s a list

And then I target the correct table for this information to be added to.

currently.forEach(entry => {
    let row = $(document.createElement("tr"));
    // [0]: Game name
    // [1]: Starting date
    row.append(`<th class="centered">${entry[1]}</th>`);
    // [2]: Array (in JS, they're objects): Make a list
    if (typeof(entry[2]) === "object") {
        let data = $(document.createElement("td"));
        let list = $(document.createElement("ul"));
        entry[2].forEach(statusItem => {
    } else {
        // [2]: Text: It's just a regular text item
    $("table.currently-playing tbody").append(row);
ghost came with jquery, don’t shoot me

Of course, this means users who’ve disabled JavaScript won’t be able to see the contents. The easiest solution to address this would be to edit the object on my local environment, then copy-paste the processed HTML into the website.


If you thought one of Ghost’s tools in its kit included the footnote... sorry to break it to you, but nope – you’ll have to DIY.

Using the editor

  • Superscript the [n] using carets ^like this^
  • Link (Ctrl+K) the n to the end of the page, e.g. #some-id
  • At the end, within an HTML block, use an anchor <a name="some-id"> that the above will jump to (note: no #)

But this will only work one-way: you can click on a reference and it’ll jump to the end, but you won’t have a way back. This is because of the reliance on name specifying the jump point – something you can’t do with the editor.

Should’ve just stuck with HTML 🤦🏻‍♂️

So, in the end, you’ll have to HTML both ways. Whenever a paragraph requires a footnote – my apologies – but it’s gonna have to be an HTML block.

  • Superscript using <sup>
  • The referrer has an href to the footnote and a name for the footnote to jump back to this
  • The source has an href to the referrer and a name for the referrer to jump back to this

Conclusion: A Hands-On CMS

I like to think of Ghost as “the privileged Squarespace for web developers”.

According to their website, Ghost targets creators, publishers, and businesses. Indeed, I’ve seen more than enough support forum posts stating that the OP in question is “not a developer” and that, too bad, the solution to their customisation questions involves a non-trivial dive into the theme’s code base.

With Ghost, you’re practically on your own when it comes to customisation. WordPress has so many themes, you could pick a random free one that works for your content after doing some searching on the net, and be confident that you won’t come across another site that uses the same one. Unless it’s really good looking.

I can’t say the same with Ghost. This means you’ll need to step up and get your hands dirty tweaking the theme to your liking and needs – but the good news is that because you did it yourself, it’s tailored to you.

Customising routes, designing pages (e.g. my ‘category select’ home landing page), changing the styles, etc. are super easy and straightforward in Ghost. I didn’t remember it being that easy in WordPress... although that’s probably because I didn’t have as much web dev experience when I was in high school.

Ghost is one of those apps where there’s only the bare minimum provided, but if used in a smart (?) way, it’s plenty enough to allow you to achieve whatever you need.

FYI – I’m talking about the free, self-hosted version, not Ghost(Pro). There are some damn expensive features in the paid version that you’d otherwise pay nothing for. Remember, just like WordPress, Ghost is free and open-source.

...Never did I think I’d have to write JavaScript to compose an article that had nothing to do with code. But there you go.

[1] “No more suffering through clumsy toolbars or drag & oops”. Yeah, it’s on their front page.

[2] Is that a row of three objects, or is it actually two columns, but one has two and the other’s by itself? Are you sure you added stuff in the right order? Was that horizontal line when you dragged that object spanned over one column, not two, not the page?

[3] For me, that’s Sublime TextPC, iA WriteriPadOS, and formerly JotterPadAndroid – the app has switched to a subscription model for Cloud features, and the devs decided to not let supporters who bought it when it was a one-time payment keep the capability. Now I’m on the look out for another app that’s a bit more affordable than iA Writer – although I’m not in a desperate need, as I mostly write on my iPad.

[4] There are tools and plugins out there for text editors that can manage Markdown tables – not just the look, but also stuff like swap columns.