Mastodon feed for your website

Unlike most social media platforms, displaying your latest mastodon posts is a doddle with vanilla JavaScript

Demo

screenshot of a ppt slide with all the design tools in the red header

Should you get tasked with designing a deck, install the super handy and free Toolbar – it places all the design tools right up in the toolbar.

It's by Slidor, a french company cursed to walk the earth designing in PowerPoint for sins unknown

slidor.agency/toolbar-powerpoi

Delighted to finally add our logo to the eduspots.org partner section.

We've just rebuilt their backend and server – it had picked up some digitial barnacles in the 8 or so years since we first designed and built the website.

A brilliant initiative we are proud to support.

we have spent the weekend vibe-coding for the first time to see what all the fuss was about. we built a flashcard for learning greek alphabet/numbers using @nuxt v4, and

we used cursor (also for the first time) and eleven labs to generate the audio.

safari/chrome/firefox all showing different renderings of the same codepen css

bad cross-browser things are happening to css again

1. Get your Mastodon ID

First you’ll need your Mastodon ID

https://example.social/api/v1/accounts/lookup?acct=your-username

In our case https://mastodon.cloud/api/v1/accounts/lookup?acct=blackspike returns the ID 109461933672061521

2. Fetch the posts

Then you’ll need to make a simple fetch call

const postsUrl = "https://mastodon.cloud/api/v1/accounts/109461933672061521/statuses"

const postsFetch = await fetch(postsUrl)

const posts = await fetchPosts.json()
That will return a JSON array like this
[
  {
    "id": "110299745197176137",
    "created_at": "2023-05-02T15:15:45.611Z",
    "in_reply_to_id": null,
    "in_reply_to_account_id": null,
    "sensitive": false,
    "spoiler_text": "",
    "visibility": "public",
    "language": "en",
    "uri": "https://mastodon.cloud/users/blackspike/statuses/110299745197176137",
    "url": "https://mastodon.cloud/@blackspike/110299745197176137",
    "replies_count": 0,
    "reblogs_count": 0,
    "favourites_count": 0,
    "edited_at": null,
    "favourited": false,
    "reblogged": false,
    "muted": false,
    "bookmarked": false,
    "pinned": true,
    "content": "\u003cp\u003eWe are delighted to push our new website live – we welcome shares \u0026amp; feedback 🖤\u003c/p\u003e\u003cp\u003e\u003ca href=\"https://www.blackspike.com\" target=\"_blank\" rel=\"nofollow noopener noreferrer\"\u003e\u003cspan class=\"invisible\"\u003ehttps://www.\u003c/span\u003e\u003cspan class=\"\"\u003eblackspike.com\u003c/span\u003e\u003cspan class=\"invisible\"\u003e\u003c/span\u003e\u003c/a\u003e\u003c/p\u003e",
    "filtered": [],
    "reblog": null,
    "application": null,
    "account": {
      "id": "109461933672061521",
      "username": "blackspike",
      "acct": "blackspike",
      "display_name": "blackspike design",
      "locked": false,
      "bot": false,
      "discoverable": true,
      "group": false,
      "created_at": "2022-12-05T00:00:00.000Z",
      "note": "\u003cp\u003eA freelance full-stack creative development team working remotely from Brighton, UK\u003c/p\u003e",
      "url": "https://mastodon.cloud/@blackspike",
      "avatar": "https://media.mastodon.cloud/accounts/avatars/109/461/933/672/061/521/original/eb1f3ebaecf23fce.png",
      "avatar_static": "https://media.mastodon.cloud/accounts/avatars/109/461/933/672/061/521/original/eb1f3ebaecf23fce.png",
      "header": "https://media.mastodon.cloud/accounts/headers/109/461/933/672/061/521/original/53e72b9acfdbc9e7.jpg",
      "header_static": "https://media.mastodon.cloud/accounts/headers/109/461/933/672/061/521/original/53e72b9acfdbc9e7.jpg",
      "followers_count": 5,
      "following_count": 4,
      "statuses_count": 16,
      "last_status_at": "2023-05-02",
      "noindex": false,
      "emojis": [],
      "roles": [],
      "fields": [
        {
          "name": "www",
          "value": "\u003ca href=\"https://blackspike.com\" target=\"_blank\" rel=\"nofollow noopener noreferrer me\"\u003e\u003cspan class=\"invisible\"\u003ehttps://\u003c/span\u003e\u003cspan class=\"\"\u003eblackspike.com\u003c/span\u003e\u003cspan class=\"invisible\"\u003e\u003c/span\u003e\u003c/a\u003e",
          "verified_at": "2023-04-13T12:30:23.994+00:00"
        },
        {
          "name": "Twitter",
          "value": "\u003ca href=\"https://twitter.com/blackspikeltd\" target=\"_blank\" rel=\"nofollow noopener noreferrer me\"\u003e\u003cspan class=\"invisible\"\u003ehttps://\u003c/span\u003e\u003cspan class=\"\"\u003etwitter.com/blackspikeltd\u003c/span\u003e\u003cspan class=\"invisible\"\u003e\u003c/span\u003e\u003c/a\u003e",
          "verified_at": null
        },
        {
          "name": "new website coming soon!",
          "value": "\u003ca href=\"https://beta.blackspike.com\" target=\"_blank\" rel=\"nofollow noopener noreferrer me\"\u003e\u003cspan class=\"invisible\"\u003ehttps://\u003c/span\u003e\u003cspan class=\"\"\u003ebeta.blackspike.com\u003c/span\u003e\u003cspan class=\"invisible\"\u003e\u003c/span\u003e\u003c/a\u003e",
          "verified_at": "2023-04-13T12:30:51.474+00:00"
        }
      ]
    },
    "media_attachments": [
      {
        "id": "110299741526912479",
        "type": "gifv",
        "url": "https://media.mastodon.cloud/media_attachments/files/110/299/741/526/912/479/original/492f846154047751.mp4",
        "preview_url": "https://media.mastodon.cloud/media_attachments/files/110/299/741/526/912/479/small/492f846154047751.png",
        "remote_url": null,
        "preview_remote_url": null,
        "text_url": null,
        "meta": {
          "original": {
            "width": 960,
            "height": 960,
            "frame_rate": "60/1",
            "duration": 14.167,
            "bitrate": 6587363
          },
          "small": {
            "width": 400,
            "height": 400,
            "size": "400x400",
            "aspect": 1.0
          },
          "focus": { "x": 0.0, "y": 0.0 }
        },
        "description": "a screen recording of the homepage of blackspike.com being scrolled",
        "blurhash": "U58WaQpvI.$+{[EkNds+8zE0x]kDF-xct7Sc"
      }
    ],
    "mentions": [],
    "tags": [],
    "emojis": [],
    "card": {
      "url": "https://www.blackspike.com/",
      "title": "blackspike design - creative web development",
      "description": "blackspike design is a freelance full-stack creative development team working remotely from Brighton, UK",
      "type": "link",
      "author_name": "",
      "author_url": "",
      "provider_name": "",
      "provider_url": "",
      "html": "",
      "width": 400,
      "height": 210,
      "image": "https://media.mastodon.cloud/cache/preview_cards/images/026/387/228/original/f69a0a79d5a5f7ec.jpg",
      "embed_url": "",
      "blurhash": "UGBeH^}Z=eA?[Ca0nOK3-BS#$is.=Lf,,?w^"
    },
    "poll": null
  }
]

You can see in that example post there is a video and thumbnail image in the media_attachments that we use in our demo carousel.

3. Create HTML from the returned JSON

Use a template literal to create the HTML list items and format the date with toLocaleDateString

const postsList = document.querySelector('.posts')

const postsUrl = 'https://mastodon.cloud/api/v1/accounts/109461933672061521/statuses'

const getPosts = async () => {

  const fetchPosts = await fetch(postsUrl)

  const posts = await fetchPosts.json()

  const dateOptions = { year: 'numeric', month: 'long', day: 'numeric' }

  const markup = posts.map(toot => `
      <li class='toot'>
        <div class='content'>${toot.content}</div>
        <footer>
            ${new Date(toot.created_at).toLocaleDateString('en-GB', dateOptions)}
        </footer>
      </li>
      `
    )
    .join('')

  postsList.innerHTML = markup
}

getPosts()

Add a dash of CSS and you’re done

Of course you can add links, show images, play videos and hide replies etc, but it’s fantastic that you don’t have to worry about OAUTH or API keys or paying billionaires for the privilege of displaying your own content 🤌

See the Pen latest toots! by blackspike (@blackspike) on CodePen.


If you need help with adding a custom feed to your site, do get in touch!