社内Wiki（=Qiita Team）の利用状況を可視化するダッシュボードをNext.jsでつくっている話

## はじめに

本記事は[モチベーションクラウドシリーズ Advent Calendar 2022](https://qiita.com/advent-calendar/2022/mcs)の1日目になります。
完走目指して頑張ります💪

自分からは、趣味で開発しているダッシュボードの話を書こうと思います。

## 動機

弊社リンクアンドモチベーションの開発メンバーは日々Qiita Teamに知見を投稿しています。

せっかく導入した社内Wikiも利用されなければ意味がありません。

そのため利用状況を分かりやすく可視化したくなりました。

Qiita TeamはAPIが提供されています。せっかくなので使ったことのないNext.jsでつくってみます。

## つくったダッシュボード

デザインはTailwind.cssで自分が雰囲気でつくっています😅

### 投稿数累計ページ（トップページ）

累計の投稿数を（勝手に）一番のKPIとしています。

最近は全くやってませんが、グラフの傾きが小さくなった時は社内で盛り上げたりしてました。

![スクリーンショット 2022-12-01 11.55.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192435/cd7159f5-dad1-1167-5157-f2f03e5aef24.png)

### ユーザー別投稿数ページ

無印のQiitaは「Contributions」という形で個人の活動状況や獲得した反響が表現されています。

個人的にはこれがとても良いなと思っています。

別に「Contributions」が増えてもお金がもらえたりするわけでないですが、増えると嬉しいものです。人によっては地味にモチベーションになっていると思います。

社内に閉じたQiita Teamでも同様の体験を提供したいと思いました。

![スクリーンショット 2022-12-01 11.57.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192435/4baf6b03-3292-5785-8125-348ba890e067.png)

「1位とりたい！」と話してくれる人もいて割と好評だと思っています。

## Qiita Team API について

デイリーの累計記事数を取得したいのですが、[QiitaのAPI](https://qiita.com/api/v2/docs)はそのようなAPIが用意されていません。

サポートと話す機会があって質問したのですが、APIを使って利用状況を可視化しているケースはなかったそうです。退職者が出た時や組織編成が変わった時に自動で反映されるためにAPIを使うことが多いそう。

スマートさに欠けますが、全ての記事を取得して、必要な情報のみを加工しました。力技です。

```typescript
export default async function handler(req: NextApiRequest, res: NextApiResponse<Response>) {
  let hasNextPage = true
  let page = 1
  let allPosts: qiitaResponse = []
  const firstItemTitle = 'ステップ6 Qiita Team運用方法のヒント'

  while (hasNextPage) {
    const response = await fetch(`https://lmi.qiita.com/api/v2/items?page=${page}&per_page=100`, {
      headers: { Authorization: `Bearer ${process.env.QIITA_ACCESS_TOKEN}` },
    })
    const items: qiitaResponse = await response.json()

    allPosts = allPosts.concat(items)

    page++

    hasNextPage = !items.find((item) => item.title === firstItemTitle)
  }

  // 以下で画面毎に使いやすいように整形

  // 例えばデイリーの累計記事数は以下のように取得
  let dailyPostsCount = allPosts.reduce((result: Result, item) => {
    const createdAt = dayjs(item.created_at).format('YYYY-MM-DD')
    const element = result.find((e) => e.createdAt === createdAt)
    if (element) {
      element.count += 1
    } else {
      result.push({
        createdAt: createdAt,
        count: 1,
      })
    }
    return result
  }, [])

  
}
```

累計記事数が数万を超えたたらきつそうですが、当分訪れない　& 趣味の範疇なのでよしとしました。

`api/v2/items`では記事の内容や作成者、いいね数、コメント等ほぼ全部の情報が取れるので使いまわしはしやすかったです。

型定義を自前で書くのが面倒なので、GraphQLとか提供して欲しいなと思いました。笑

## Next.js の使い心地

今更ですがNext.jsを使ってみた感想です。

### API Route の仕組みが面白い

こんなのあるんですね！

https://nextjs-ja-translation-docs.vercel.app/docs/api-routes/introduction

以下のメリットがありそうです。

- 外部サービスのURLやクレデンシャルを隠蔽できる
- CORSを気にしなくて良い
- 複数のAPIを叩けるのでBFF的な使い方もできる

ん〜便利！

### webpackの設定しなくて良いのが楽

何度か`webpack.config.js`を書いてきましたが、毎回面倒に感じていました。

ゼロコンフィグ最高です。

### Vercelのデプロイが楽

デプロイが楽で驚きました。

「Twitterで皆んなが言っていたのこれか〜」と思いました。

大規模な商用サービスでインフラが基本AWSとかだと、AWSのサーベスでまとめたくなりますが、実験的なプロトタイプでNext.jsとかならVercelでやらない理由ないと思いました。

その他、ルーティングを勝手にやってくれたりSSRやSSGの仕組みがあって、総じて開発者体験が良かったです。

## 終わりに

たまに自由につくるのは楽しいですね。

Next.jsとかTailwind.cssとか流行っているエコシステムに乗ると楽だなと改めて実感しました。

自身が開発するプロダクトもモダンしていきたいと思います。

要望あれば少し抽象化してOSSにしようと思います。

それでは皆様、Happy Coding！