とあるコミュニティのまとめサイトG+（ジープラス）の技術的解説


# 本文の前に

この記事は、ジーズアカデミー Advent Calendar 2022 7日目です。
6日目はイソノカツオさんによる「[今でも彼がメガやビットの海を泳いでいるのかを自分の目で確かめてみたくなって、その海に飛び込むことにした。](https://qiita.com/Katsuo-isono/items/086847c63aa422c9ad08)」でした。田川さんの記事内にもありましたが、プログラミングって大変で苦しいけど楽しいですよね。

# 今回のテーマ

今回個人開発しているG+（ジープラス）という実験的なメディアの技術的な部分について記事を書きたいと思います。サービスの紹介については以下Noteをご覧ください。

https://note.com/matakitanaka_jp/n/n9569bdae7d01

# G+とは何か

簡潔にいうと、ジーズアカデミーに関わる方が発信する記事をまとめた実験的なメディアサイトです。個人的にジーズアカデミーは素晴らしいコミュニティであると感じる一方で、十二分に活用できていないと感じていました。まずは縦と横が交わるような情報を集めるべく、実験的にメディア作りを始めました。

サービス名は、一般的に落第（Fで表される評価）の外にいる（Fの次）、一般的に評価されない人たち、すなわちギークの意味を込めて、G+と名づけました。

## つくり始める時に決めたこと

なるはやリリースで、使ったことがない技術で、運用費が安いことを目標にしました。

- なるべく早くリリースする
- Next.js x TypeScriptを使う
- Cloudflareを使ってみる

# 技術スタック・お世話になったOSS

<table>
  <thead>
    <tr>
      <th>項目名</th>
      <th>説明</th>
    </tr>
  </thead>
  <tr>
    <td> 言語 </td> <td>TypeScript</td>
  </tr>
  <tr>
    <td> フレームワーク </td> <td>Next.js</td>
  </tr>
  <tr>
    <td> デプロイサービス </td> <td>Cloudflare Pages</td>
  </tr>
  <tr>
    <td> DNS </td> <td>Cloudflare</td>
  </tr>
  <tr>
    <td> その他 </td> <td>RSS</td>
  </tr>
</table>

今回catnoseさんが公開されている「team-blog-hub」というテンプレートを使用しました。

https://github.com/catnose99/team-blog-hub

catnoseさんの解説記事はこちら

https://zenn.dev/catnose99/articles/cb72a73368a547756862

# デプロイまでの解説

## ビルド→デプロイの流れ

1. 各メンバーのRSSのURLから情報フェッチする
2. 1.で取得した情報をjsonファイルに書き出す
3. 2.を元に、Next.jsで静的ファイルに書き出す
4. 3.を、Cloudflare Pagesにデプロイ

## RSSを使用したフェッチ

以下のような情報を`members.ts`にベタ打ちします。さらに高級に実装したい場合は、データベースに保存することになります（MySQL, PostgreSQL, Firebase, etc...）。ソーシャルログインでユーザー情報を取得して、ユーザー自身が情報を保存してくれるような動線作りを考えると良いと思います。

```typescript:members.ts
import { Member } from "@src/types";

export const members: Member[] = [
  {
    id: "matakitanaka_jp",
    name: "田中又暉",
    role: "G's ACADEMYメンター",
    bio:
      "「子どもたちの未来をつくる」オンライン教育のプラットフォーム、キッズウィークエンドを開発しています。",
    avatarSrc: "/avatars/matakitanaka_jp.jpg",
    sources: [
      "https://note.com/matakitanaka_jp/rss",
    ],
    includeUrlRegex: "note.com|zenn.dev|qiita.com",
    twitterUsername: "matakitanaka_jp",
    githubUsername: "matakitanakajp09",
    websiteUrl: "https://www.kidsweekend.jp/portal",
    type: "admin|member|contributor"
  },
  {
    id: "hiro_yas",
    name: "児玉浩康",
    role: "G's ACADEMY ファウンダー",
    bio: "G's ACADEMY ファウンダー",
    avatarSrc: "/avatars/hiro_yas.jpg",
    sources: ["https://note.com/kodamay/rss"],
    twitterUsername: "hiro_yas",
  },
  {
    id: "daisu_yamazaki",
    name: "山崎大助",
    role: "G's ACADEMY 学校長",
    bio: "ジーズアカデミー学校長 / デジタルハリウッド大学院教授",
    avatarSrc: "/avatars/daisu_yamazaki.jpg",
    sources: ["https://note.com/daisu_yamazaki/rss"],
    twitterUsername: "daisu_yamazaki",
  },
]
```

## RSSの情報をフェッチして、ファイルに書き出す

今回RSSを使用していますが、APIなど使用する場合は、APIとして読み替えれば良いです。

```typescript:src/builder/posts.ts
import { members } from "../../members";

// 諸々割愛します。

(async function () {
  // 先ほど作成したMemberリストをfor文で回します
  for (const member of members) {
    // Memberひとりひとりの情報を使ってRSSの情報を取得していきます
    const items = await getMemberFeedItems(member);
    // RSSの情報があれば、allPostItemsに追加していきます
    if (items) allPostItems = [...allPostItems, ...items];
  }
  // allPostItemsを作成日時でソートします
  allPostItems.sort((a, b) => b.dateMiliSeconds - a.dateMiliSeconds);
  // .contentsディレクトリを作成します
  fs.ensureDirSync(".contents");
  // posts.jsonファイルに書き出します
  fs.writeJsonSync(".contents/posts.json", allPostItems);
})();
```

## ビルドコマンド

package.jsonを見ましょう。yarn buildを実行すると、

```bash
yarn build
```

最終的には、以下のコマンドが実行されます。先ほど見た`./src/builder/posts.ts`が実行されていますね。ビルドする際に毎回RSSの情報が更新されています。Github Actionsなどで定期的にビルドさせれば、オペレーションなしにサイトが更新されるようになります。

```bash
run-s ts-node --project tsconfig.builder.json ./src/builder/posts.ts next build
```

## Cloudflare Pagesにデプロイ

Cloudflareについて書くための余白が足りないので端折ってしまうのですが、Githubリポジトリを連携すると、特定のブランチにプッシュすると自動デプロイできます。一度リポジトリを連携してしまうと、リポジトリの付け替えができなくなってしまうので注意です。

# 上記を経て公開されたサイト

Cloudflareでドメインを取得して以下サイトを公開しました。

https://www.fetchgplus.site/

OSSのテンプレートを使用したため、開発着手〜リリースまでで6時間ほどで形が出来上がり、諸々リリース準備をして最終的に10時間程度でリリースすることができました。

# 今後の展開

クローズドOSSのような形で運営していきたいと考えてます。ジーズアカデミーコミュニティに属しているエンジニア・開発経験がない在校生など誰でも参加できるような開発体制にして、知識や経験のシェアが生まれると嬉しいと思ってます。

# 最後に
今後もゆるく運営していきます。皆さん思い出した時に覗きに来てください。毎回きっと違う情報があるはずです。
明日8日目は[ババソウイチロウ](https://twitter.com/bee21low)さんです。尖った記事を書いてやりますよ！って豪語していたのでとても楽しみです。