Article:

この記事はAnthrotech Advent Calendar 2025の2日目の記事です。

昨日は @adoringonion さんによるEarth, Wind & FireっぽいエフェクトをRenderGraphで実装するでした。素晴らしい記事をありがとうございます!

はじめに

Anthrotechは「ケモノ好き x 技術系好き」なコミュニティです。

Anthrotechでは「ユーザーディレクトリ」と称して、ユーザーごとのいわゆる「ホームページ」を持てるサービス(?)を提供しています。 サービスといっても、ただGitレポジトリをつくって、それをcloudflare pagesでホストしているだけなんですけどね。

Astroを使ってベースを作成し、メンバーが自由に自分のディレクトリにmarkdownファイルを放り込むことで、簡単に自分のページを持てるようにしています。

使い方は人それぞれなのですが、特に戌咬音かんぬきさんのページはswiftの解説なんかを提供されていて、とても見ごたえがあります。

本題

GitHubには通称「芝」と呼ばれるコンポーネントがありますね。

これです

Anthrotechでも、「Discordでの進捗報告」や、「イベントでの登壇」など様々な活動がありますので、これらをこのGitHubの芝のように一覧できると面白そうだなと思いました。

幸い、AstroはReactコンポーネントを埋め込むことができるので、Reactで簡単に作成してしまって、メンバーが自由に自分のプロフィールページに埋め込めると良さそうです。

クローラ

芝を表示するためには、まず活動情報を集める必要があります。 自動で「GitHubでの活動」と「Discordでの活動」をクロールしてくる仕組みを作成しました。

goで作成し、kubernetesのcronjobで定期実行しています。それ以上に特に凝ったことはしてないので特に書くことはないですね。 レポジトリはこちら github.com/anthrotech-dev/activity

芝コンポーネント

クロールしてきたデータを元に、芝風に描画するようにしましょう。

Reactの有効化

これもっと大変だと思ったのですが、びっくりするほど簡単でした。

@astrojs/reactをインストールして、astro.config.mjsに以下のように追加するだけです。

1
2
3
4
5
6
7
8
import { defineConfig } from 'astro/config';
import mdx from '@astrojs/mdx';
import react from '@astrojs/react';

// https://astro.build/config
export default defineConfig({
  integrations: [mdx(), react()],
});

これだけでReactが有効になります。すげー。

コンポーネントの作成と埋め込み

コンポーネントも、ふつうに".tsx"でファイルを作成すればOKです。

1
2
3
export default function ActivityHeatmap({ id }: ActivityHeatmapProps) {
  ...
}

埋め込みも、通常のmdxと同じように行えます。

1
2
3
4
5
6
import Activity from '../../components/Activity.tsx';

<Activity
    client:load
    id="totegamma"
/>

propsも渡せますね。

1点違うのは、client:指定子の存在ですね。 公式ドキュメント

Astroはデフォルトでビルド時にコンポーネントをレンダリングしますが、今回はクライアントからAPIを叩いてデータを取得する必要があるので、 client:loadを指定してクライアントサイドでレンダリングするようにしています。

とはいえ頻繁に更新されるものでもないので、サーバーサイドでレンダリングするようにして、サイトを毎日ビルドするようにしても良いかもしれません。

完成

これでユーザーページに芝を埋め込むことができました!やったね。

各日付をクリックして詳細を確認することもできます。

おわりに

astroを使うのはAnthrotechでの利用が初めてだったのですが、とても簡単にReactコンポーネントを埋め込むことができて驚きました。 これからもAstroを活用していきたいですね。 このブログ(Gammalab)もHugoからそろそろ移行したいな…。

明日はDABUさんによる記事が予定されています。お楽しみに!