Backfeed based on Mastodon Comments

Examples

"Mastodon Comments" refers to the @oom/mastodon-components library.

<script type="module">
  import Comments from 'https://esm.run/@oom/mastodon-comments'
  customElements.define('oom-comments', Comments)
</script>
<link
  rel="stylesheet"
  href="https://cdn.jsdelivr.net/npm/@oom/mastodon-comments/src/styles.css"
/>
<oom-comments src="https://mastodon.gal/@misteroom/110810445656343599">
  No comments yet
</oom-comments>

The basic example should look something like the above, where https://mastodon.gal/@misteroom/110810445656343599 is the link to the post in Fediverse.

Hatsu uses predictable URLs, you just need to change the src:

// trim url
// input:
// https://example.com/foo/bar#baz
// https://example.com/foo/bar?baz=qux
// output:
// https://example.com/foo/bar
const { origin, pathname } = new URL(window.location.href)
const url = new URL(pathname, origin).href

// get id (base64url encode)
// aHR0cHM6Ly9leGFtcGxlLmNvbS9mb28vYmFy
const id = btoa(url).replaceAll('+', '-').replaceAll('/', '_')

// oom-comments src
// https://hatsu.local/notice/aHR0cHM6Ly9leGFtcGxlLmNvbS9mb28vYmFy
const src = new URL(`/notice/${id}`, 'https://hatsu.local').href

So eventually it will look like this:

<script type="module">
  import Comments from 'https://esm.run/@oom/mastodon-comments'
  customElements.define('oom-comments', Comments)
</script>
<link
  rel="stylesheet"
  href="https://cdn.jsdelivr.net/npm/@oom/mastodon-comments/src/styles.css"
/>
<oom-comments
  src="https://hatsu.local/notice/aHR0cHM6Ly9leGFtcGxlLmNvbS9mb28vYmFy"
>
  No comments yet
</oom-comments>

It's a real pain in the ass, but you can try to automate it.

Lume

If you're using Lume and Theme Simple Blog, it will read data.comments.src.

So you can do this:

// _config.ts
import lume from 'lume/mod.ts'
import blog from 'https://deno.land/x/lume_theme_simple_blog@v0.14.0/mod.ts'

const site = lume()

site.use(blog())

// add this:
site.preprocess(['.md'], (pages) =>
  pages
    .filter((page) => page.type === 'post')
    .forEach((page) => {
      page.data.comments = {
        src: new URL(
          `/notice/${btoa(site.url(page.data.url, true))
            .replaceAll('+', '-')
            .replaceAll('/', '_')}`,
          'https://hatsu.local' // your hatsu instance
        ).href,
      }
    })
)

export default site

How it works?

Hatsu mimics Pleroma's URL format.

@oom/mastodon-components will extract the ID from the URL and query the corresponding API for the data.

// oom-comments src
const src = 'https://hatsu.local/notice/aHR0cHM6Ly9leGFtcGxlLmNvbS9mb28vYmFy'
// origin: 'https://hatsu.local
// pathname: '/notice/aHR0cHM6Ly9leGFtcGxlLmNvbS9mb28vYmFy'
const { origin, pathname } = new URL(src)
// id: 'aHR0cHM6Ly9leGFtcGxlLmNvbS9mb28vYmFy'
const [, id] = pathname.match(/^\/notice\/([^\/?#]+)/)
// api url: https://hatsu.local/api/v1/statuses/aHR0cHM6Ly9leGFtcGxlLmNvbS9mb28vYmFy/context
const url = new URL(`/api/v1/statuses/${id}/context`, origin)

Upon receiving a request, Hatsu's corresponding API will attempt to decode the base64url ID and return the data.

If you're interested in the code, you can also take a look at routes/statuses/status_context.rs and entities/context.rs.