こんにちは😊
株式会社プロドウガの@YushiYamamotoです!
らくらくサイトの開発・運営を担当しながら、React.js・Next.js専門のフリーランスエンジニアとしても活動しています❗️
この記事は Nextjs Advent Calendar 2025 の参加記事です🎄
Next.js App Router、最高ですよね。
でも、個人開発や小規模な社内ツールを作るとき、ふと思いませんか?
「バックエンド(API Route / DB接続 / メール送信処理)、書くの面倒くさいな……」
Prismaをセットアップして、Supabaseと繋いで、Resendでメールを送って……。
もちろん本番サービスなら必要ですが、もっとサクッと作りたい時もあります。
そこで今回は、Next.jsの「Server Actions」 と、ノーコードツール 「n8n」 を組み合わせて、バックエンドのコードを一行も書かずに高機能なアプリを作るアーキテクチャ を紹介します。
🏗️ アーキテクチャ:Server Actions を「BFF」にする
構成は非常にシンプルです。
Next.jsはUIとバリデーションに徹し、データの保存や加工はすべてn8n(Webhook)に投げます。
なぜ Server Actions なのか?
クライアント(useEffect や onClick)から直接n8nを叩かない理由は2つあります。
- セキュリティ: n8nのWebhook URLをブラウザに露出させないため。
- CORS回避: n8nのWebhookはCORS設定が面倒な場合があるため、Next.jsサーバーを経由させるのが確実。
🛠️ 実装:お問い合わせフォームを作ってみる
例として、「お問い合わせ内容を送信すると、Notionに保存されてSlackに通知が飛ぶ」機能を実装します。
1. n8n側の準備
n8nで Webhook ノードを作成し、Methodを POST に設定します。
(このURLを .env に N8N_WEBHOOK_URL として保存しておきます)
2. Next.js (Server Action) の実装
app/actions.ts に、n8nへデータを中継する関数を定義します。
ここでは Zod を使って、n8nに渡す前に型安全性を担保します。
'use server'
import { z } from 'zod'
// バリデーションスキーマ
const schema = z.object({
name: z.string().min(1, '名前は必須です'),
email: z.string().email('正しいメールアドレスを入力してください'),
message: z.string().min(10, 'メッセージは10文字以上でお願いします'),
})
export async function submitContact(prevState: any, formData: FormData) {
// 1. バリデーション
const validatedFields = schema.safeParse({
name: formData.get('name'),
email: formData.get('email'),
message: formData.get('message'),
})
if (!validatedFields.success) {
return {
success: false,
errors: validatedFields.error.flatten().fieldErrors,
}
}
try {
// 2. n8nのWebhookを叩く (BFFとしての役割)
const response = await fetch(process.env.N8N_WEBHOOK_URL!, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
// 必要ならここで認証ヘッダーを付与
// 'Authorization': `Bearer ${process.env.N8N_AUTH_TOKEN}`
},
body: JSON.stringify(validatedFields.data),
})
if (!response.ok) {
throw new Error('n8n error')
}
return { success: true, message: '送信しました!' }
} catch (error) {
return { success: false, message: '送信に失敗しました。' }
}
}
3. Next.js (Client Component) の実装
React 19 (Next.js 15) の useActionState を使ってフォームを作ります。
'use client'
import { useActionState } from 'react'
import { submitContact } from './actions'
const initialState = {
success: false,
message: '',
}
export default function ContactForm() {
const [state, formAction, isPending] = useActionState(submitContact, initialState)
if (state.success) {
return <div className="text-green-500">🎉 {state.message}</div>
}
return (
<form action={formAction} className="flex flex-col gap-4 max-w-md mx-auto">
<div>
<label>お名前</label>
<input name="name" type="text" className="border p-2 w-full" />
{state.errors?.name && <p className="text-red-500">{state.errors.name}</p>}
</div>
{/* ... email, message も同様 ... */}
<button
type="submit"
disabled={isPending}
className="bg-blue-500 text-white p-2 rounded disabled:opacity-50"
>
{isPending ? '送信中...' : '送信する'}
</button>
{state.message && !state.success && (
<p className="text-red-500">{state.message}</p>
)}
</form>
)
}
🚀 このアーキテクチャのメリット
-
バックエンド開発が「お絵かき」になる:
- 「やっぱりメールも送りたい」「Notionじゃなくてスプレッドシートにしたい」といった変更が、Next.jsのコードを触らずにn8nの画面だけで完結します。
-
Next.jsは「表示」に集中できる:
- 複雑なビジネスロジックや外部API連携をNext.jsから追い出すことで、フロントエンドのコードが驚くほどクリーンになります。
-
Server Actionsの恩恵:
- JavaScriptが無効な環境でも動作し、プログレッシブエンハンスメントに対応できます(n8n連携でも!)。
まとめ
「Next.jsを使うなら、バックエンドもTypeScriptで書かなきゃ」という固定観念を捨ててみましょう。
Server Actions を「n8nへの入り口」として使う ことで、爆速でプロトタイプを作り、検証サイクルを回すことができます。
2025年は、「書かない勇気」 を持ってNext.jsを使い倒していきましょう!💪
最後に:業務委託のご相談を承ります
私は業務委託エンジニアとしてWEB制作やシステム開発を請け負っています。最新技術を活用したレスポンシブなWebサイト制作、インタラクティブなアプリケーション開発、API連携など幅広いご要望に対応可能です。
「課題解決に向けた即戦力が欲しい」「高品質なWeb制作を依頼したい」という方は、お気軽にご相談ください。一緒にビジネスの成長を目指しましょう!
👉 ポートフォリオ
🌳 らくらくサイト