The online home of Brave Location Services Ltd.

TikTok redirects with Open Graph Metadata in Jekyll

I posted back in March 2025 about how I’m using social media now - basically switching to Mastodon and BlueSky for text, and TikTok and YouTube for video sharing.

8 months on I’ve pretty much stuck to that, and have surprisingly got much more (maybe too much!) into TikTok, and not posting much text any more

One problem I did find is that posting a link to TikTok on Mastodon or BlueSky didn’t look so good, as they don’t do a great job of implementing OpenGraph tags. So I thought I’d fix that myself

Redirect Pages with Custom Metadata

My solution was to make some intermediate redirect pages hosted on my own site here that contain the exact Open Graph metadata I want, then automatically redirect to the TikTok video.

First, I created a custom Jekyll layout called redirect.html that handles the redirection while including all the necessary metadata:


<!DOCTYPE html>
<html lang="en-gb">
    <head>
        {% include opengraph.html %}
        <meta http-equiv="refresh" content="0;url={{ page.redirect }}" />
        <link rel="canonical" href="{{ page.redirect }}" />
        <script>
            window.location.replace("{{ page.redirect }}");
        </script>
    </head>
    <body>
        This page has been moved to <a href="{{ page.redirect }}">{{ page.redirect }}</a>.
    </body>
</html>

This layout uses three different methods to ensure the redirect works reliably:

  • Meta refresh: A standard HTML meta tag that tells browsers to redirect immediately
  • Canonical link: Helps search engines understand the relationship between pages
  • JavaScript redirect: Provides a fallback for modern browsers

Each TikTok video gets its own post with custom front matter. Here’s an example:

---
layout: redirect
title: Steel Rigg (TikTok)
description: "Old bloke clambering up Steel Rigg (Hadrian's Wall) #hadrianswall #northumberland"
published: true
image: /assets/social_images/steelrigg.jpg
redirect: https://www.tiktok.com/@yeltzland/video/7479828444398865686
---

The key fields here are:

  • title and description: Used in the Open Graph metadata for the preview card
  • image: A custom thumbnail that appears in the preview
  • redirect: The actual TikTok URL to redirect to
  • published: Controls whether the post appears in the index

My existing OpenGraph include already handles most of the work. It checks for page-level metadata and uses it to populate the Open Graph tags:


{% if page.title %}
<meta name="og:title" content="{{ page.title }}" />
{% else %}
<meta name="og:title" content="{{ site.title }}" />
{% endif %}

{% if page.description %}
<meta property="og:description" content="{{ page.description }}"/>
{% else %}
<meta property="og:description" content="{{ content | markdownify | strip_html | xml_escape | truncate: 200 }}"/>
{% endif %}

{% if page.image %}
<meta property="og:image" content="{{ site.url }}{{ page.image }}"/>
{% else %}
<meta property="og:image" content="{{ site.url }}/images/logos/og-bravelocation.png">
{% endif %}

I can then post a link to my site, and it will look pretty good when the social site turns that link into a rich card - see https://mastodon.social/@yeltzland/115519188300810818 for example

Building a Social Posts Index

To make these posts discoverable, I created an index page at /social/ that displays all published posts as cards. The page uses Jekyll’s liquid templating to filter and sort the posts:


{% assign social_posts = site.pages | where_exp: "page", "page.path contains 'social/'" | where_exp: "page", "page.name != 'index.html'" | where: "published", true %}
{% assign sorted_posts = social_posts | sort: 'path' | reverse %}

{% for post in sorted_posts %}
    <a href="{{ post.redirect }}" class="social-card" target="_blank">
        {% if post.image %}
        <img src="{{ post.image }}" alt="{{ post.title }}" class="social-card-image">
        {% endif %}
        <div class="social-card-content">
            <h2 class="social-card-title">{{ post.title }}</h2>
            {% if post.description %}
            <p class="social-card-description">{{ post.description }}</p>
            {% endif %}
        </div>
    </a>
{% endfor %}

I used CoPilot to make some nice CSS cards that match the existing design - and you can see the results on this page

Conclusion

I’m pretty happy with this approach for sharing social videos - and in doing this I forgot how much I love Jekyll for running static sites!

If you want to follow me directly on TikTok, I’m @yeltzland on there of course!

Why I'm selling My Meta Raybans

Not a bad product, but really not for me

I bought my Meta Raybans a few months ago to try them out, despite my general reservations about buying anything from that company

They pretty much matched my expectations, but I’ve now realised they’re not for me - so I’m currently trying to sell them on eBay

Best Use Case - Hands Free Video

The glasses are really good at one thing - taking action videos while on the move

Having a hands-free camera that will take pretty decent quality footage is great when you need it. I was really happy with a couple of clips I posted on TikTok here and here

However, I heard a quote recently that wearing them is like having a GoPro attached to your face - which is a great description - but anyone who knows me definitely wouldn’t describe me as a GoPro kinda guy 😀

Decent Use Case - Headphones

The sound quality of the headphones was much better than I expected. Pretty decent quality for listening to music or podcasts, and definitely usable

However I’m never without my Airpods Pro headphones, and their superior noise cancelling and general usability in the Apple eco-system meant I very rarely actually used them as headphones

Less Good Use Case - Camera

It’s definitely handy to have quick access to the camera while wearing the glasses, but the picture quality isn’t great compared to my iPhone

Also, it’s pretty hard to frame the pictures as the camera is off to one side - something that the new glasses with the in-screen display will probably help a lot with

For me, I always have my phone available for quick access, so I hardly used the glasses for taking photos other than for a few test shots

Poor Use Case - AI

Meta’s AI is not the best, and even if it was I’m really not sure I need to have an AI assistant on the move

Obviously I can always use my phone for this use case if I really feel the need, and access superior models without much friction

Worst Feature - Sunglasses/Weight

The real clincher for me is the weight. They aren’t very comfortable for any prolonged use , which means I’ve stopped wearing them as actual sunglasses

If I’m only going to use them for those rare occasions when I might take some action videos, and then revert to my cheap but light sunglasses whenever the sun comes out, then they are really not worth it

Conclusion

Clearly your mileage may vary, but for me they are too heavy for comfortable use as regular sunglasses, and the smart features aren’t compelling enough

Also wearing Meta hardware is a little too icky without it being super compelling

Maybe future Apple-made hardware might address some of my concerns, other than they’ll probably be over-engineered, overly expensive and with poor AI features 😀

Android Issues with Proguard and GSON

Fixing a tricky bug only found in production in my Android app

I don’t do much native Android development, but when I do I always learn something new.

I was working on my Yeltzland app, but then one of my users (thanks DJ!) told me the league table view hadn’t been working for a while on Android

I couldn’t repro this at all, until I installed the app from the Play Store and saw the same issue.

What I’d done a few weeks ago was get Proguard and other app size minification working, obviously to reduce the size of the app.

What I didn’t know is there are issues with the miniification of the generated classes used to parse the incoming JSON data feed when using GSON, which was causing the problem.

A bit of research found this template with the Proguard settings, and with a bit of experimentation I managed to fix it.

It’s pretty obscure that the GSON library can’t handle this itself, but I’m on the edge of my knowledge here so presumably there are good reasons??

I don’t use the Android app daily so hadn’t noticed the bug in the production app, but thought I’d post this just in case someone has the same issue.

Using The Socials

Thinking through how I should best use social media

I’ve been pretty quiet on social media recently, with the demise/descent into Fascism of Twitter/X meaning I’ve quit the place where I used to post the occasional bit of nonsense.

The trouble is I haven’t really found a natural home for my different interests:

  • I follow a lot of tech accounts on Mastodon
  • I follow those sports people and news sources who’ve migrated off X onto BlueSky
  • I now ignore everyone who’s left behind on X

My last usage of X was to keep up with the Halesowen Town social feeds, but with a bit of effort I’ve set up a scraper that mirrors their posts onto both Mastodon and BlueSky

I’ve not been on Facebook for many years, but did briefly go back to Instagram for a while. However their recent anti-DEI/LGBT+ pronouncements means I’m not really happy sharing photos there any more ☹️

It’s really hard keeping up with all this crap from the big tech companies 🤬

Going forward

Just writing the above down has made it a bit clearer what I’m going to do:

  • Any tech only posts will go onto my Mastodon account
  • Any non-tech posts will also go onto my BlueSky account
  • Not 100% sure how to share any photos, but probably will put them on both Mastodon and BlueSky - and considering posting videos to YouTube and/or TikTok

No idea if this will stick, but seems like a good plan for right now in March 2025

Brief Vision Pro Demo Review

Some quick notes on using Apple's fancy headset

I had an Apple Vision Pro demo yesterday in the Newcastle Apple Store, now it’s been released in the UK.

I’m not going to do a full review, as others have dome a far better job than I could.

However it was such a striking experience, I thought I’d jot down my thoughts while fresh in my mind …

  1. It was heavier on my face than I expected. There’s no way I could use it for extended periods as a monitor
  2. The spatial and immersive video quality were unbelievably good (the sports coverage in particular was superb)
  3. The videos shot on iPhones was also very good
  4. Slightly disappointed by the screen quality. I was my first time using a VR headset, so maybe it’s better than competing headsets but it’s “just” 4K and Idefinitely noticed foveation effects around the edges

I’m definitely NOT buying one, but that’s solely based on the cost. As a personal 3D cinema it’s truly fantastic, but that’s not something I really need in my life, and especially not at £3500.

I think if they could get the cost down to say £500, and there was a lot more content - especially live sports - I’d have walked out with one immediately. However I think that’s a long way off.

What I will do is start taking some spatial videos and panoramas on my phone, as in a few years time they would be fantastic to look back at through a future Vision Pro device.

Image credit: Steve Zhang from Wikimedia