Next.jsでKijiというCMS風アプリケーションを作ってみました。
自主学習用に作ったためCMSと呼ぶには程遠いですが、ログイン機能や、記事の管理、ユーザー登録機能は実装しました。改良すれば掲示板サイトや、メディアサイト、SNSサイトなど応用できると思います。
GitHubで公開しています。
Kijiの特徴
- Next.jsのApp Routerを使用
- ログイン機能
- マイページ機能
- サーバーアクションを使ったデータの取得や追加
- Prismaを使用
- ダークモードあり
- shadcn/ui, tailwind CSSを使用
- Storybook
- Vitestを使ったユニットテスト
- Playwrightを使ったE2Eテスト
- フォームの検証にzodを使用

記事の詳細ページです。
タイトル、投稿日時、カテゴリー、タグ、投稿者のサムネと名前、記事本文を表示しています。
左下のアイコンはreact-queryの開発用ツールのアイコンです。

ユーザーの一覧ページです。
フィルターやソート、表示件数選択、ページはクエリパラメーターと連携します。関連する要素が多いため実装は難しいです。
クエリパラメーターはユーザーが操作できてしまうので、妥当性のチェックをしています。例えば、pageのパラメーターが自然数か否かをチェックしています。
開発に至った経緯
Next.jsのApp Routerや、ReactのServer Actionsの登場によりNext.jsを使ったWebアプリの開発スタイルが大きく変わりそうだと思い、作ってみました。
今まではReact(Next.js)がバックエンドのデータと連携するためにREST APIの実装が必要でしたが、Server Actionsを使うことでReactコード内にサーバー側の処理を書くことができるようになりました。
以下のようなイメージです。
(今まで)React -> REST API -> ORM -> DB
(新スタイル)React -> ORM -> DB
KijiではORMにPrismaを使用しています。
REST APIはマイクロサービスとの相性は良いですが、モノリス(1つのサービスしか作らない場合)ならは作るメリットが少ないと思います。
REST APIを使えばフロントエンドとバックエンドの役割を明確に分けられて開発効率が良いという意見もあるかもしれませんが、フロントエンド開発と、バックエンド開発の連携がスムーズに行かないと色々苦労します。例えば、
- フロントエンド開発者がユーザーぺージを作りたいがAPIがまだできていない。
- 仕様変更によりAPIのスキーマを変わると、フロントエンドのコードもバックエンドのコードも修正する必要がある。
- フロントエンドとバックエンドで使っているプログラミング言語が違う場合は人材の手配が困難になる
フロントエンドをリッチにするためだけにReactを使っているモノリスなWebアプリ場合は、REST APIを作る必要がなくなるメリットは非常に大きいです。
開発の流れ
開発期間は約3ヶ月です。最初はbulletproof-reactを基にして開発をしていました。
開発初期はExpressを使ってREST APIを作っていましたがサーバーアクションの存在を知って開発効率が上がると思ったため削除しました。
個人的には、ログイン機能、ログインユーザー専用ページ、データの追加・更新・削除、一覧データのフィルター・ソート・表示件数の実装方法を一番知りたくて開発しました。
Prismaのエラー処理をしていないなど荒削りな部分があります。
今回初めてPrismaを使いました。DjangoのORMよりも高性能で驚いた反面、ドキュメントが膨大で使い慣れるのに苦労しそうだなと思いました。
今後は画像投稿機能、コメント機能、管理者専用ページ、いいね機能、閲覧数、キャッシュの活用、SSOなどの機能追加やテストコードの実装などの機能を実装したいなと考えています。
最後に
実装経験を積むことは大切ではありますが、それでも、サンプルコードが有るのと無いのでは実装スピードが全然違います。
今回は自分のNext.jsの開発ノウハウの蓄積のためにを使ってCMS風アプリを開発しました。CMSに使われる機能は多くのwebアプリで使われる機能でも有るので今後の開発に活用できそうです。