@sbax wow! Quindi se ho un sito statico hostato tramite GitHub posso usare comunque le api di mastodon in questa maniera, tanto lo Script viene eseguito lato browser?
Commenti con Mastodon
Era da un po' che volevo aggiungere i commenti al blog, ma non volevo delegarli a oscuri servizi di terze parti (col rischio che finisca per profilare tuttɜ e campare di pubblicità) né gestirmi un backend completo di database.
Spulciando il web ho trovato un post che proponeva un'alternativa interessante: usare Mastodon come sistema di commenti. Ho rubato spudoratamente l'idea e l'ho adattata al mio stack.
L'idea#
In buona sostanza quello che succede è più o meno questo:
- Scrivo un post per il blog.
- Pubblico su Mastodon un link all'articolo.
- Salvo l'id di quel post di Mastodon nell'articolo.
- Il mio sito interroga l'API di Mastodon e mostra i commenti direttamente in pagina.
Chi vuole commentare risponde dal proprio account mastodon e il mio blog si limita a mostrarli. Chi è già sul fediverso li vede anche nel loro habitat naturale.
Attaccarlo a Next.js#
Nel post originale l'API viene interrogata con JavaScript lato browser, cliccando un bottone vengono mostrati tutti i commenti. Ha il suo senso, essendo un sito statico, così si evita di martellare l'API a ogni reload.
Io però sono su Next.js, un server component mi permette di scaricare i commenti sul server e buttarli subito dentro l'HTML e applicando la cache di Next evito anche il problema delle eccessive richieste a Mastodon.
Al momento i commenti vengono rivalidati una volta ogni 24 ore, indipendentemente da quanti leggono il post. È un compromesso, ma per il traffico del mio blog, non mi serve avere i commenti che si aggiornano in tempo reale.
Uno snippettino#
const ONE_DAY_IN_SECONDS = 60 * 60 * 24;
const loadComments = async (instance: string, mastodonId: string) => {
const response = await fetch(
`https://${instance}/api/v1/statuses/${mastodonId}/context`,
{ next: { revalidate: ONE_DAY_IN_SECONDS } },
);
const data = await response.json();
return data.descendants;
};
export const Comments = async ({ mastodonId, instance }: CommentsProps) => {
const comments = await loadComments(instance, mastodonId);
return (
<section>
{comments?.map((comment) => (
<article key={comment.id}>
<header>
<a href={comment.account.url}>
<img
src={comment.account.avatar_static}
alt={comment.account.acct}
/>
</a>
<a href={comment.account.url}>
{comment.account.display_name || comment.account.acct}
</a>
</header>
<div
dangerouslySetInnerHTML={{ __html: sanitize(comment.content) }}
/>
</article>
))}
</section>
);
};
Comments
@gioele_silvestre circa, puoi farlo come nel post originale che ho linkato, non come l'ho fatto io lato server, leggi qua https://beej.us/blog/data/mastodon-comments/