✨Discover storytelling in the AI age with Pixar's Matthew Luhn at Sanity Connect, May 8th—register now


By Arnstein Marjala

Utdanningsetaten i Oslo – #DinRetning

Desktop - front
Desktop - categories
Desktop - text content
Desktop - category list view
Desktop - single TikTok view
Mobile - front
Mobile - categories
Mobile - text content
Mobile - category list view
Mobile - single TikTok view
Edit category
Edit page content
Assign category
Preview TikTok
TikTok details

About the project

Oslo annually arranges an education fair for youth (around 15 y.o.) to help them decide which studies to choose later on. The fair usually gets visited by roughly 12 000 people. In 2020, due to Covid-19, it was impossible to do this the traditional way. They decided to go fully digital instead - and moved the whole shebang to TikTok.

While the campaign would live its own life on TikTok, somewhat kept together by a hashtag (#dinretning), there was also a need to gather produced content and publish it on a dedicated website. The idea was that this front end should mimic the behavior and feel of TikTok – a native app. How about that, right? 🤷‍♂️


1. Editorial

Editors would have an unknown amount of tiktoks to track down and publish. Also, there had to be some editorial control/filtering. I wouldn't want to be the person that had to manually go through TikTok chasing all those videos(*) by a hashtag.

They also needed to organize the tiktoks into categories. There would be 15 categories that match the 15 educational programs in Norway for high school / upper secondary education.

* Or maybe I would? To my surprise, TikTok turned out to be quite fun.

2. Content gathering

Getting the content sure was a challenge. TikTok has no official API, or more precisely, a minimal API. 1:1, you feed it an id, and it returns an embed code. We needed lists (tiktoks by a hashtag), details (user, caption, etc.), and preferably raw video files as we couldn't fill the front-end with an unknown load of embeds.

A combination of a couple of the APIs available at RapidAPI proved to make this possible; to get a list of tiktoks by a hashtag, get single item details, and get raw/clean video URLs.

3. Front-end

It "should feel like TikTok.", remember? That loosely translates to: "videos must load instantaneously, autoplay (preferably unmuted) when in view, stop when snap-scrolled out of view, etc."

We would also want to place custom icons and details (username, captions) over the videos. These requirements made it clear that we needed to set up a custom player and reliable source of video delivery.


The content workflow ended up being something like this behind the scenes:

  1. A cron job on Pipedream invokes a serverless function that gets a list of all the tiktoks with the hashtag #dinretning. Check if they already exist in Sanity; if not, create them.
  2. Find all tiktoks in Sanity that are missing the video field; use their id to get what we need (raw video) via another API at RapidAPI. Result returned from this was only valid for a short period, so send details to Cloudflare stream (copy video).
  3. Get streaming URLs (hls/m3u8) in return from Cloudflare when they're processed/ready, patch items in Sanity with this data.

This setup allowed the content editors to go through and preview (custom preview component) the harvested tiktoks right in the studio and then assign them to a category. If/when the tiktoks were categorized, they would be published on the site(s).


I built two separate front-ends, one for mobile and one for desktop —both with Gatsby. The sites featured a custom video player built on Video.js, and Cloudflare Stream delivered the video streaming. Thanks to this setup, I guess that "TikTok-feeling" wasn't too far off in the end.


Working with unofficial APIs is tricky.
Working with video streaming is tricky.
Working with Sanity is ... not that tricky.

#DinRetning was my first actual project with Sanity. Thanks to the extensive documentation and a vibrant community, getting into this territory was a pleasant and eye-opening experience.

Tools/services used: Sanity, Gatsby, Cloudflare Stream, Pipedream, Video.js, RapidAPI, Vercel.

At the last count, ~750 tiktoks were stored in Sanity. The target audience received the overall campaign quite well. It won one gold, one silver, and one diploma in the Norwegian "Gulltaggen" Awards 2021.