Invidious/YouTube video template

Hello everyone!

I’ve been playing a bit with Silverbullet and I like it a lot. I’m streamlining some of the cases that I’d like to use on my notes and one of them are adding YouTube videos (not embed but a thumbnail + link). In my specific case I’d like videos that are retrieved and linked to an Indivious instance to avoid the cluttered and add-filled YouTube.

I created an small space-script that retrieves the video name, thumbnail and links it. This custom function input can be a YouTube URL, Indivious URL or just the video id. Add this snipplet of code to a page, reload (Control+Alt+r) and start using it as a template.

I used as the instance, but you can use your own self-hosted one or any of the public instances (Invidious Instances - Invidious Documentation).


async function invFetchVideoTitle(videoid) {
    const apiUrl = `${INVIDIOUS_INSTANCE}/api/v1/videos/${videoid}`;

    try {
        const response = await fetch(apiUrl);
        if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
        const data = await response.json();
        return data.title.replace(/[#\[\]{}*]/g, '');
    } catch (error) {
        console.error('Error fetching video title:', error);
        return null;

function invGetVideoThumbnail(videoid) {
    return `${INVIDIOUS_INSTANCE}/vi/${videoid}/0.jpg`

function invGetVideoLink(videoid) {
    return `${INVIDIOUS_INSTANCE}/watch?v=${videoid}`

function invExtractYouTubeVideoID(url_or_videoid) {
    const ytRegex = /(?:https?:\/\/)?(?:www\.)?(?:youtube\.com\/(?:[^\/\n\s]+\/\S+\/|(?:v|e(?:mbed)?)\/|\S*?[?&]v=)|youtu\.be\/)([a-zA-Z0-9_-]{11})/;
    const ytMatch = url_or_videoid.match(ytRegex);
    if (ytMatch) {
        return ytMatch[1];
    const invRegex = /(?:https?:\/\/)?[\w.-]+\/watch\?v=([a-zA-Z0-9_-]{11})/;
    const invMatch = url_or_videoid.match(invRegex);
    if (invMatch) {
        return invMatch[1];

    return url_or_videoid;

async function invGetVideoMarkdown(url_or_videoid) {
    videoid = invExtractYouTubeVideoID(url_or_videoid);
    title = await invFetchVideoTitle(videoid);
    thumb = invGetVideoThumbnail(videoid);
    link = invGetVideoLink(videoid);
    return `![${title}](${thumb})\n[${title}](${link})`

silverbullet.registerFunction({name: "youtube"}, async (videoid) => {
    return invGetVideoMarkdown(videoid);

Example usage:


This would look like this on a page:

I hope this is useful or at least that helps you to learn a bit on how to develop these custom functions (they’re quite powerful).



Nice! Link unfurling does something similar already for Youtube, e.g. putting a Youtube “naked” url in your page, and then running Link: Unfurl will offer to replace it with an embed. While it’s technically possible to extend this functionality from space script as well via event listening, I like this solution too :+1:

I’ll explore changing the unfurl behavior as well.

Templates can be good for queries to structured data , that might happen to have a video, but the unfurl is more appropriate to my intended usage.