Embed Mastodon Posts with mastodon-post Web Component

Category: Javascript , Social Media | September 25, 2026
Authordaviddarnes
Last UpdateSeptember 25, 2026
LicenseMIT
Views0 views
Embed Mastodon Posts with mastodon-post Web Component

<mastodon-post /> is a Web Component that turns a public Mastodon status URL into an inline post with its content and engagement counts.

You can replace the generated markup with your own HTML template for the page or for individual posts.

Features

  • Default quote markup with an author link, reposts, replies, and favorite counts.
  • Page-wide template replacement.
  • Per-instance templates.
  • Nested object and array bindings.
  • Multiple bindings on one template node.
  • Automatic custom-element registration after the module loads.

How To Use It

Installation

Self-hosted Module

Host mastodon-post.js in your project and load it as a module.

<script type="module" src="/path/to/mastodon-post.js"></script>

npm

Install the package when your project uses npm.

npm install @daviddarnes/mastodon-post

CDN

Load the library from a CDN.

<script
  type="module"
  src="https://www.unpkg.com/@daviddarnes/[email protected]/mastodon-post.js"
></script>
<script
  type="module"
  src="https://esm.sh/@daviddarnes/[email protected]"
></script>

Basic Usage

The original anchor stays inside <mastodon-post>. Hide it after the custom element registers when the generated post should replace the link. If JavaScript never loads, the anchor stays visible.

<style>
  mastodon-post:defined > a {
    display: none;
  }
</style>
<script type="module" src="/path/to/mastodon-post.js"></script>
<mastodon-post>
  <a href="https://mastodon.design/@DavidDarnes/109824258017750161">
    Discuss on Mastodon
  </a>
</mastodon-post>

Default Template

When the page does not define #mastodon-post-template, the module creates this template for the generated post.

<figure>
  <blockquote data-key="content"></blockquote>
  <figcaption>
    <cite>
      <a data-key="url">
        <span data-key="username"></span>
        @
        <span data-key="hostname"></span>
      </a>
    </cite>
    <dl>
      <dt>Reposts</dt>
      <dd data-key="reblogs_count"></dd>
      <dt>Replies</dt>
      <dd data-key="replies_count"></dd>
      <dt>Favourites</dt>
      <dd data-key="favourites_count"></dd>
    </dl>
  </figcaption>
</figure>

Replace the Default Template

Define a <template> with the ID mastodon-post-template to change the markup used by components that do not specify another template.

<template id="mastodon-post-template">
  <blockquote data-key="content"></blockquote>
  <dl>
    <dt>Reposts</dt>
    <dd data-key="reblogs_count"></dd>
    <dt>Replies</dt>
    <dd data-key="replies_count"></dd>
    <dt>Favourites</dt>
    <dd data-key="favourites_count"></dd>
  </dl>
</template>
<mastodon-post>
  <a href="https://mastodon.design/@DavidDarnes/109824258017750161">
    Discuss on Mastodon
  </a>
</mastodon-post>

Use a Different Template for One Post

Set the template attribute to the ID of another <template> when one embed needs different markup.

<template id="compact-post">
  <a data-key="content, url"></a>
</template>
<mastodon-post template="compact-post">
  <a href="https://mastodon.design/@DavidDarnes/109824258017750161">
    Discuss on Mastodon
  </a>
</mastodon-post>

Bind Mastodon Status Data

data-key reads fields from the Mastodon Status response. Dot notation reads nested objects. Bracket notation reads array entries. Only bind nested paths that exist in the returned status; the resolver does not guard a missing intermediate object or array item.

For a status with at least one media attachment:

<template id="mastodon-post-template">
  <article>
    <blockquote data-key="content"></blockquote>
    <p>
      <img alt="Mastodon account avatar" data-key="account.avatar" />
      <strong data-key="account.display_name"></strong>
    </p>
    <img
      alt="Mastodon post media"
      data-key="media_attachments[0]preview_url"
    />
    <p>
      Replies:
      <span data-key="replies_count"></span>
    </p>
    <a data-key="url">View original post</a>
  </article>
</template>

Bind Multiple Values to One Element

Separate keys with commas when one template node needs multiple values. Here, content fills the anchor body and url sets its destination.

<template id="linked-post">
  <a data-key="content, url"></a>
</template>
<mastodon-post template="linked-post">
  <a href="https://mastodon.design/@DavidDarnes/109824258017750161">
    Discuss on Mastodon
  </a>
</mastodon-post>

Template API Reference

  • template: Set on <mastodon-post> to select a <template> by ID for that instance.
  • id="mastodon-post-template": Defines the shared custom template when no per-instance template value is present.
  • data-key: Maps a Mastodon status field to a template node.
  • Comma-separated data-key values: Apply multiple fields to one node.
  • Nested keys: Read object properties such as account.display_name and array entries such as media_attachments[0]preview_url.
  • Link-derived fields: The default template uses url, username, and hostname from the source Mastodon link.

Value Binding Behavior

  • content is assigned to innerHTML.
  • A string beginning with http sets href when the receiving node is an <a>.
  • A string beginning with http sets src when the receiving node is an <img>.
  • Other values are assigned through textContent.

Styling

mastodon-post {
  display: block;
  max-inline-size: max-content;
  font-family: system-ui;
}
mastodon-post blockquote {
  margin: 0;
  border-inline-start: 2px solid currentColor;
  padding-inline-start: 1rem;
}
mastodon-post figure {
  margin: 0;
}
mastodon-post figcaption,
mastodon-post dl {
  display: flex;
  flex-wrap: wrap;
  align-items: end;
  gap: 1rem;
}
mastodon-post dl {
  margin: 0;
  margin-inline-start: auto;
  gap: 0.25rem;
}

Alternatives & Related Resources

You Might Be Interested In:


Leave a Reply