Tumblr as Headless CMS

Image source: Katerina Limpitsouni - undraw.com

Tumblr1 is a micro-blogging service which, unfortunately became irrelevant over the last years. As a tumblr user you can follow blogs, repost content with a comment (similar to Twitter) or create your own content.

The content creation is pretty easy, you can choose from pre-defined post types like photosets, video content, text post, quotes, web link and audio. And you can write your own templates for the public face of the blog, which made tumblr somehow attractive, after MySpace removed their customization feature (which was horrible and also shows how long tumblr is online).

Since Tumblr was bought and maintained by Verizon, the blogs are not really publicly accessible anymore, because with the GDPR they just slapped a consent page before you can enter a blog with an EU IP address. This page reveals (if you dig deeper) how tracker infested tumblr is2 and how the new owner tries to monetizes this platform as much as possible and completely failed anyway3.

Since I have a personal travel blog there and a migration from tumblr to my own wordpress instance (via a wordpress migration tool) completely failed, I thought it would be a nice exercise to utilize the Tumblr API and write my own template. The API delivers the content in JSON format, exactly what a "Headless CMS"4 is doing.

As I said, the posting interface is pretty good in the browser and on the phone, so why not use them as a backend and just cut out the tumblr cookies and tracker from the frontend. Sure, there is still the problem of content ownership. If Tumblr cease to exist I will be able to save my unformatted content, but that's it. But that's not the problem now.

Accessing the API to retrieve posts is easy and the developers did a pretty good job developing this interface.

For just read access you need a tumblr blog (or every public blog works) and an API key to send a request to the following endpoint:

api.tumblr.com/v2/blog/{blog-identifier}/posts[/type]?api_key={key}&[optional-params=]

See

Then just write a few templates for every post type and generate the pages in which way ever. Javascript, PHP or any language that can transform JSON with.

So far so easy.

The problem is, tumblr decided that HTML is not a very good way is to describe content (it is) and developed a new underlaying JSON based representation of content5 with the name Neue Post Format or NPF. I believe the rational was to follow the trend of block based content creation as seen in Wordpress or Editor.js6 and to be more flexible.

The developer is now free to write a parser to output content in which way ever, be it HTML or RTF.

For tumblr it looks like this:

{
    "content": [
        {
            "type": "text",
            "subtype": "heading1",
            "text": "Sward's Shopping List"
        },
        {
            "type": "text",
            "subtype": "ordered-list-item",
            "text": "Sword"
        },
        {
            "type": "text",
            "subtype": "ordered-list-item",
            "text": "Candy"
        },
        {
            "type": "text",
            "text": "But especially don't forget:"
        }
        {
            "type": "text",
            "subtype": "unordered-list-item",
            "text": "Death, which is uncountable on this list."
        }

        {
            "type": "image",
            "media": [
            {
                "type": "image/gif",
                "url": "http://69.media.tumblr.com/b06fe71cc4ab47e93749df060ff54a90/tumblr_nshp8oVOnV1rg0s9xo1_250.gif",
                "width": 250,
                "height": 200
            }
            ],
            "feedback_token": "abcdef123456"
        }
    ]
}

For Editor.js like this:

{
    "time" : 1555962128623,
    "blocks" : [
    {
        "type" : "header",
        "data" : {
            "text" : "Editor.js",
            "level" : 2
        }
    },
    {
        "type" : "paragraph",
        "data" : {
            "text" : "Hey. Meet the new Editor. On this page you can see it in action — try to edit this text."
        }
    },
    {
        "type" : "header",
        "data" : {
            "text" : "Key features",
            "level" : 3
        }
    },
    {
        "type" : "list",
        "data" : {
            "style" : "unordered",
            "items" : [
            "It is a block-styled editor",
            "It returns clean data output in JSON",
            "Designed to be extendable and pluggable with a simple API"
            ]
        }
    },
    {
        "type" : "header",
        "data" : {
            "text" : "What does it mean «block-styled editor»",
            "level" : 3
        }
    },
    {
        "type" : "paragraph",
        "data" : {
            "text" : "Workspace ..."
        }
    }
    {
        "type" : "image",
        "data" : {
            "file" : {
                "url" : "https://codex.so/upload/redactor_images/o_e48549d1855c7fc1807308dd14990126.jpg"
            },
            "caption" : "",
            "withBorder" : true,
            "stretched" : false,
            "withBackground" : false
        }
    }
    ],
    "version" : "2.12.4"
}

While the idea behind this is really nice, I gave up trying to render the weird construct to create nested HTML tags...

{
    "type": "text",
    "text": "some bold and italic text",
    "formatting": [
    {
        "start": 5,
        "end": 9,
        "type": "bold"
    },
    {
        "start": 14,
        "end": 20,
        "type": "italic"
    }
    ]
}

... and decided to render tumblrs "legacy" format, which is HTML, but as always, there is a caveat.

Tumblr focuses on their mobile app instead on the web experience and thus, creates all post on the app exclusively in the new Neue Post Format, and outputs only a lousy HTML representation of that post for legacy api calls.

Also, you can't edit some posts over their web interface, if they were made in the app, because of that very reason, that tumblr is not really interested in supporting the old HTML format anymore.

So I'm stuck between a rock and a hard place. The app is easy to use when I'm on the road, but I often prefer the website to edit things. Using both methods leads to a not very satisfying user experience and the code, to get around the quirks of the legacy HTML representation of the NPF content, becomes ugly.

In this case all posts are of the type text, with embedded image or video tags, which is hard to manage if you wanted to use the nice gallery feature of tumblr.

There are several reasons to not use a platform like tumblr as headless CMS, but to experiment with a JSON representation of content, without setting up your own CMS backend on a server, it's a pretty nice playground.