IndieWeb Link Sharing

A pain point of the IndieWeb is that it's sometimes not as convenient to share content as it is on the common social media platforms.

Posting a new short “note” on my site currently requires me to commit a new markdown file to the repository on Github. That’s doable (for a developer), but not really convenient, especially when you’re on the go and just want to share a quick link. Twitter and other social media platforms literally make this as easy as clicking a single button, which makes it tempting to just post stuff straight to them. That’s why I wanted to improve this process for my site.

A quick Google search revealed that smarter people have already solved that problem. I came across this blog post by Tim Kadlec who describes adapting someone else’s link sharing technique for his (Hugo-powered) blog. That just left me the task of adapting it for my setup (Eleventy, Netlify) and customizing a few details.

The new link sharing basically has three main parts:

  • a small Javascript bookmarklet to act as a “share button”
  • a form that collects and sends the shared link data, and
  • a serverless function to process it and create a new file.

Here’s how they work together:

The Bookmarklet

The button to kick things off is just a small bit of Javascript that takes the current page’s title, URL and optionally a piece of selected text you may want to quote along with the link.

It then sends these things as GET parameters to mxb.dev/share by opening a new window to it.

function(){
    // get link title
    var title = document.getElementsByTagName('title')[0].innerHTML;
    title = encodeURIComponent(title);

    // get optional text selection
    var selection = '';
    if (window.getSelection) {
        selection = window.getSelection().toString();
    } else if (document.selection && document.selection.type != 'Control') {
        selection = document.selection.createRange().text;
    }
    selection = encodeURIComponent(selection);

    // generate share URL
    var url = 'https://mxb.dev/share/?title='+title+'&body='+selection+'&url='+encodeURIComponent(document.location.href);

    // open popup window to sharing form
    var opts = 'resizable,scrollbars,status=0,toolbar=0,menubar=0,titlebar=0,width=680,height=700,location=0';
    window.open(url,'Sharer',opts);
})()

The bookmarklet looks like this:
Share on MXB

…and can then be dragged to the bookmarks bar for quick access.

The Sharing Form

At mxb.dev/share, I’ve created a small preact app. It will take the GET params passed in via the URL and generate a live preview of the resulting note, so I know what the end product will look like.

There’s also a form that will be pre-populated with the values, which lets me include additional information and edit everything before posting.

The form also has fields for the Github username and security token, necessary for authentification. My password manager will fill those in automatically.

The sharing form with a live preview of the note

The Handler Script

When I hit the submit button, the form will send the data along to another endpoint. I’ve built a serverless function to handle the processing, so I could theoretically send data from other sources there too and keep the posting logic in one place. Netlify Functions seemed to be a nice fit for this.

Here’s the full script if you’re interested. It reads the posted data and generates a new markdown file from it, called something like 2019-08-11-amphora-ethan-marcotte.md:

---
title: "Amphora - Ethan Marcotte"
date: "2019-08-11T16:57:13.104Z"
syndicate: false
tags: link
---

...we've reached a point where AMP may "solve" the web's 
performance issues by supercharging the web’s accessibility problem. 
(via [@beep](https://twitter.com/beep))

[ethanmarcotte.com/wrote/amphora](https://ethanmarcotte.com/wrote/amphora/)

It will then use the Github API to post that file as a base64-encoded string to a predetermined location in the site’s repository (in my case the folder where I keep all my notes).

Here’s the core function responsible for that:

const postFile = async data => {
    const { title, token } = data
    const fileName = getFileName(title)
    const fileContent = getFileContent(data)
    const url = API_FILE_TARGET + fileName

    const payload = {
        message: 'new shared link',
        content: Buffer.from(fileContent).toString('base64'),
        committer: {
            name: 'Max Böck',
            email: 'hello@mxb.dev'
        }
    }

    const options = {
        method: 'PUT',
        body: JSON.stringify(payload),
        headers: {
            'Content-Type': 'application/vnd.github.v3+json',
            Authorization: `token ${token}`
        }
    }

    return await fetch(url, options)
}

That’s pretty much it! After the file is committed, Netlify will kick in and re-build the static site with the new content. If I have marked the “syndicate to Twitter” flag, another script will then cross-post the link there. (More on that in Static Indieweb pt1: Syndicating Content).

Mobile Share Target

A caveat of this technique is the use on mobile. Javascript bookmarklets are not as easily available in mobile browsers, which complicates the process again.

Thankfully Aaron Gustafson recently pointed out that it’s possible to define a “Share Target” for Progressive Web Apps. That means if your site is a PWA (it probably should be), you can add an entry like this to its manifest file:

// site.webmanifest
{
    ...,
    "share_target": {
        "action": "/share/",
        "method": "GET",
        "enctype": "application/x-www-form-urlencoded",
        "params": {
            "title": "title",
            "text": "text",
            "url": "url"
        }
    }
}

That little bit of JSON registers your site as an application that can share things, just like Twitter, WhatsApp and the others. So after I “install” my PWA (read: create a shortcut link on my device home screen), it shows up as an option in the native Android “share” dialog:

PWA Share Sheet on Android
The "Max Böck" share option is available after installing the PWA.

Selecting the "MXB" option will grab the current page title and URL and send them as GET args to my sharing form, just like the bookmarklet would on desktop. There's still a small bug in there where the URL will be sent as the text parameter, but that can be corrected with a bit of Javascript in the form app.

I’m quite happy with how this turned out, as it feels really simple and straightforward. One step closer to IndieWeb bliss!

Webmentions

What’s this?
  1. Andy Bell
    Dope!!!
  2. f
    🤩
  3. Charlie Don't Surf
    I love this! 🎉
  4. Charlie Don't Surf
    What I absolutely adore about the #indieweb community is that it is free of the "one true way" mentality that infects the rest of the web industry. Do what works for you, on your website! Bespoke is good! https://t.co/NJXgm0K0ny
  5. This is brilliant!
Show All Webmentions (45)
  1. Ana Rodrigues
    I love this!!
  2. Paul Shryock
    Awesome!
  3. Grant Richmond
    Looks like you've come up with a nice solution that works for you 👍 You should check out micropub it's kind of a open specification for what you've already built, then you can use any micropub client to post to your own website!
  4. Niiiiice!
  5. Qasim
    How 😮
  6. Bryan Robinson
    This is awesome! You mentioned the mobile share stuff for android, for iOS users you could set up a Shortcut to share. I’ve got one that’s simpler that posts a link to a function to “bookmark” a site
  7. Netlify
    Read how @mxbck brilliantly implemented his own sharing functionality with this #IndieWeb approach using: - @Netlify Functions. - @GitHub API - #PreactJS mxb.dev/blog/indieweb-…
  8. Kahlil Lechelt
    Very nice!
  9. David Mateo
    This is awesome.
  10. Colin Johnston
    Extremely rad! 👏🏻
  11. ross
    This is great! I may have to try this out. I like that it's also tapped into your 'syndicate to twitter'
  12. ge ricci
    I love #IndieWeb :D
  13. Janne Wolterbeek
    Suh-weet!!
  14. Nathan Gathright
    Could I commission you to adapt this for me into a standalone thing?
  15. Zeyad Etman
    A great brilliant tool.
  16. This sounds like it could be a great thing to work with indieweb.org/Micropub - then it's independent of how the site works in the background. Really good stuff though!
  17. hckrnews
    IndieWeb Link Sharing 3 by mxbck | 0 comments on Hacker News. Advertisements Related
  18. Creativity4all
    IndieWeb Link Sharing 3 by mxbck | 0 comments on Hacker News. Share this: Twitter Facebook Like this: Like Loading...
  19. Angsuman Chakraborty
    IndieWeb Link Sharing mxb.dev/blog/indieweb-…
  20. Jan Boddez
    I used to use a bookmarklet to "quickly" share links on my blog, but it didn't quite work on mobile. My current sort of backwards setup involves posting notes to a private Mastodon account—thru a mobile app, mostly—then importing them with a cron job. Super convenient!
  21. Jan Boddez
    Despite the relative prevalence of bookmarklets, posting short status updates on one’s own website is often quite a bit more tedious than sharing on social media. Max Böck’s take on the issue sure makes for an interesting read. mxb.dev/blog/indieweb-…
  22. Tony Finch
    mxb.dev/blog/indieweb-… - IndieWeb link sharing.
  23. IndieWeb.Life
    IndieWeb Link Sharing | Max Böck - Frontend Web Developer #indieweb mxb.dev/blog/indieweb-…
  24. ross
    Yeah! This looks like it has a lot of possibilities. I've been thinking of using it for - Inspiration saving - Owning my own bookmarks (something like refind but self-hosted) - Small thoughts type posts like MXB is using
  25. Adactio Links
    IndieWeb Link Sharing | Max Böck - Frontend Web Developer mxb.dev/blog/indieweb-…
  26. Jacky
    呢個config比較複雜(preact+netifly+github actions)。 我自己只係wordpress整左個form可以share link,PWA+Share action可以參考 mxb.dev/blog/indieweb-…
  27. Jan Boddez
    In reply to https://janboddez.tech/notes/8f206ec788. A bookmarklet would help, too, on the desktop, and even on mobile. Heck, WordPress has had this for years! (And I should totally dig it up again.) Or a “Share to Micropub” browser extension or something. I mean, I’m not convinced sharing from within a reader app is necessarily the best solution.
  28. Chris Enns
    Oh I should’ve known to check his Github repos. 😆
  29. Jacky
    IndieWeb Link Sharing | Max Böck mxb.dev/blog/indieweb-…
  30. Phil Wolstenholme
    That's a cool little feature :) your work is always super interesting!
  31. Max Böck
    Thanks! 👍
  32. Jonathan Holden
    Ha ha... You say feature, I say bug!
  33. Jonathan Holden
    This is what i get now...
  34. Max Böck
    Hm ok - sorry thats a new one for me. Not familiar with chrome OS... Maybe there's an option somewhere in the browser settings to add twitter & co back?
  35. Daniel Schildt
    Found the example from 2019 mxb.dev/blog/indieweb-… that shows how to add link sharing functionality for a personal website. Could be adapted to a different use case.
  36. Robb Knight
    @mxbck @nhoizey Oh nice, will have a look at that later, looks excellent.