Adding a Share On Mastodon button to a website

A high number of users are currently migrating onto Mastodon as a result of Musk's takeover of Twitter.

Many websites carry social media icons to allow easy sharing of content into social media networks (including Twitter), however very few have a button for sharing into Mastodon - in part because the mechanics of sharing into a decentralised network can be a little more complex than into a centralised one (because you need to know where to send the user).

In this post, I'll describe the process of creating a simple Mastodon toot button with a little bit of javascript and HTML, as well as how to add it to a Nikola theme.


The challenge

We need to send the user to /share on their Mastodon domain, but, we don't know which domain to send them to: it could be anything from mastodon.social to somesite.example.invalid.

There isn't a way to auto-detect this (that I know of), so the simplest solution is to ask the user.

We can use the following bit of javascript to handle a click event, prompt the user for their instance domain (via javascript's prompt()), and then open a window onto the share page, prepopulating the post title and URL

/* Generate a share link for the user's Mastodon domain */
function MastodonShare(e){

    // Get the source text
    src = e.target.getAttribute("data-src");

    // Get the Mastodon domain
    domain = prompt("Enter your Mastodon domain", "mastodon.social");

    if (domain == "" || domain == null){
        return;
    }

    // Build the URL
    url = "https://" + domain + "/share?text=" + src;

    // Open a window on the share page
    window.open(url, '_blank');
}

The function takes the share text from an attribute called data-src on the clicked element, so could be driven by something as simple as

<a
 onclick="MastodonShare(this);"
 data-src="My site&amp;url=https://www.bentasker.co.uk/"
>Share on Mastodon</a>

After clicking, the user receives a prompt asking them to provide their mastodon domain

Browser prompt for domain

Once they've submitted it, a new tab opens taking them to the toot page on their instance

Mastodon Share Page


A button

Although functional, links don't really stand out , so it's preferable to use an image as the anchor.

<img class="mastoimg" 
      style="display: none" 
      loading="lazy" 
      src="/images/social-icons/mastodon_share.jpg" 
      alt="Share this post on Mastodon" 
      title="Share this post on Mastodon" 
      data-src="Making%20A%20Shelf%20From%20A%20Tree%20Trunk&amp;url=https://www.bentasker.co.uk/posts/blog/house-stuff/making-a-tree-trunk-shelf.html"
      >

Because the share functionality is reliant on Javascript, it's best to hide the image by default (style="display: none") and use Javascript to make it visible so that users without Javascript aren't misled by a non-functioning button.

The images can be revealed with the following javascript function (which also adds the click event listener)

/* Call this on document.ready() */
function enableMastodonShare(){
    var eles = document.getElementsByClassName('mastoimg');
    for (var i=0; i<eles.length; i++){
        eles[i].addEventListener('click', MastodonShare);
        /* Make visible by removing the original display: none */
        eles[i].style = '';
    }
}

I don't use jQuery on my site, so I use a call to this function to trigger it

doDocumentReady(enableMastodonShare);

Dynamically embedding into Nikola pages

I use the Nikola Static Site Generator (SSG) on bentasker.co.uk.

Because there's no dynamic code running, it's not possible to insert information taken from the user's request into the page. However, Nikola does provide functions which can be used to insert the page URL at generation time.

I've published details on how to use this to add social media icons to Nikola in the past.

The section I've added to post.tmpl in my theme is

<img class="mastoimg"
    style="display: none"
    loading="lazy" src="/images/social-icons/mastodon_share.jpg" 
    alt="Share this post on Mastodon"
    title="Share this post on Mastodon"
    data-src="${post.title()|h}&amp;url=${abs_link(post.permalink())}"
        >

Which gives us this

Share this post on Mastodon

Conclusion

Adding Mastodon sharing buttons to a site so that users can easily "toot" content is reasonably straightforward.

If you're after a more polished workflow, there are redirect servers like Toot Proxy which can be used to ask the user which instance to use, but my preference is generally not to unnecessarily add a third party into workflows.