デザイナーでもバックエンドを気にせずデータの送受信ができるサービスを、手軽に作ってみたい!
というわけで、microCMSとNext.jsを使ってそれっぽいプロジェクトに挑戦しました。
今回はその制作プロセスをざっくり共有します!
どんなものを作る?
突然ですが、こんなシチュエーション、ありませんか?
「気の利いたメッセージや、日々の叫びやつぶやきをボトルに詰めて海に流したい!」
ありますよね。…あると、思います。
というわけで、以下のようなものを作ってみました。
メッセージを投稿すると、すでに投稿された中からランダムに1件が返ってくる。
誰かのメッセージを受け取れる体験を提供するインタラクティブなWebサービス。
使用した技術
- フロントエンド … Next.js(React + TypeScript)
- バックエンド … microCMS(ヘッドレスCMS)
- プラットフォーム … Vercel、GitHub
- サポートAI … ChatGPT、Copilot(AIコーディング支援)
開発プロセス
なぜヘッドレスCMS?
バックエンドやデータベース構築の知識があまりない私でも扱いやすく、
microCMSは「データの管理」と「API提供」を簡単に実現できる点が魅力でした。
サーバーレスな設計
サーバーの管理や構築を一切せず、データベース的な役割をmicroCMSに、
デプロイはVercelにお任せ。サーバーレスアーキテクチャの恩恵を活用。
APIの設計
今回作成したPOST APIの概要です。
スキーマ
フィールド | 表示名 | 種類 | 必須 | 詳細設定 |
---|---|---|---|---|
message | メッセージ | テキストエリア | true | 文字数を制限 |
ヘッドレスCMSにデータを送るには、microCMSの「APIキー管理」でPOSTリクエストを有効化します。
※ Hobby(無料)版だとPOST使えないので有料版のみ(今回はお試しなのでトライアルで)
フロントエンドの実装
環境セットアップ
Next.jsのプロジェクトを作成
…気づけば…15…!
npx create-next-app@latest
- 必要なコンポーネントやページを配置(ChatGPTに色々お願いしつつ)
- App RouterのRoute HandlersでmicroCMSにメッセージを投稿
メッセージ入力ページ
async function handleSubmit(event: React.FormEvent) {
event.preventDefault();
setIsSubmitting(true);
setError('');
try {
// 入力されたメッセージを取得
const message = textareaRef.current?.value || '';
// API Routeにデータを送信
const response = await fetch('/api/sendMessage', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ message }),
});
// レスポンスの確認
const result = await response.json();
if (!response.ok) {
throw new Error(result.error || '送信に失敗しました');
}
// 成功時に別のページにリダイレクト
router.push('/random');
} catch {
setError('エラーが発生しました');
} finally {
setIsSubmitting(false);
}
}
return (
<div className={`${css.contents_wrap}`}>
<p>メッセージをボトルにいれて海に流してみましょう</p>
<form onSubmit={handleSubmit}>
<div className={`${css.form_wrap}`}>
<div className={`${css.form_inner}`}>
<label htmlFor="message" className={`${css.label}`}>
Dear...
</label>
<textarea
ref={textareaRef}
className={`${css.textarea}`}
name="message"
placeholder="Write your message here"
required
defaultValue=""
onInput={handleInput}
></textarea>
{error && <p className={`${css.error}`}>{error}</p>}
<button type="submit" disabled={isSubmitting} className={`${css.button}`}>
{isSubmitting ? '送信中...' : 'メッセージを送る'}
</button>
</div>
</div>
</form>
</div>
);
Route
export async function POST(request: Request) {
try {
const { message } = await request.json();
if (!message) {
return NextResponse.json({ error: 'メッセージは必須です' }, { status: 400 });
}
const microCMSResponse = await fetch('YOUR_API_ENDPOINT', {
headers: {
'X-MICROCMS-API-KEY': process.env.MICROCMS_API_KEY || '',
'Content-Type': 'application/json',
},
method: 'POST',
body: JSON.stringify({ message }),
});
if (!microCMSResponse.ok) {
const error = await microCMSResponse.json();
return NextResponse.json(
{ error: error.message || '送信に失敗しました' },
{ status: microCMSResponse.status }
);
}
return NextResponse.json({ success: true });
} catch (error) {
return NextResponse.json({ error: 'サーバーエラーが発生しました' }, { status: 500 });
}
}
ランダムメッセージページ
送信後はすでに投稿されたメッセージからランダムに1件メッセージが表示されるページに遷移します。
export default async function Home() {
// 記事を取得
const contents = await getRandomPosts();
// ランダムなインデックスを生成
const getRandomIndices = (num: number, max: number): number[] => {
const indices: number[] = [];
while (indices.length < num) {
const index = Math.floor(Math.random() * max);
if (!indices.includes(index)) {
indices.push(index);
}
}
return indices;
};
//現在は1件だけど、複数設定できる
const randomIndices = getRandomIndices(1, contents.length);
const randomContents = randomIndices.map((index) => contents[index]);
return (
<>
<ul className={`${css.list}`}>
{randomContents.map((post) => (
<li key={post.id}>
<p>誰かのメッセージが流れ着きました</p>
<article className={`${css.message_wrap}`}>
<h2 className={`${css.head}`}>Dear...</h2>
<div className={`${css.message}`}>{post.message || 'メッセージはありません'}</div>
</article>
</li>
))}
</ul>
</>
);
}
デプロイ
- GitHubとVercelの連携
コードをGitHubにプッシュするたびにVercelが自動ビルドを実行。
完成
- メッセージを投稿すると、ランダムで誰かのメッセージが返ってくる
(デモページではRandomからアクセスして確認) - Collectionにこれまで投稿したメッセージ一覧を表示
デモはこちらです
※送信機能については、Hobby(無料)版のため使えなくなっています。
振り返り
良かった点
- バックエンドに触れずとも、インタラクティブなサービスを作れた!
- ヘッドレスCMSやサーバーレスの使い勝手の良さを実感
- microCMSとNext.js(App Route)を駆使して、フロントエンドとバックエンドをシンプルに統合
反省点
- フォーム送信時や、メッセージ表示に演出を加えたかった
- クライアントサイドとサーバーサイドの理解がまだイマイチ
- ISR設定だけだと、自分の投稿したメッセージがコレクションに反映されるまで時間がかかる→On-demand ISRを使えば解決する?
正直デザイナーでも簡単に…とまではいきませんでしたが、それっぽいサービスを作ることはできそうでした!
ローカルの環境とかも作りやすくて、昔に比べて格段にできることが増えるので、制作の幅が広がりそうです。