next-safe-action
Next.jsでサーバーアクションの入力値を安全に検証したり、エラー処理をしたり、ミドルウェアを追加したり、型安全な変更処理を構築したりする際に、より安全で効率的な開発を実現するSkill。
📜 元の英語説明(参考)
Type-safe Server Actions in Next.js with next-safe-action. Use when a user asks to validate server action inputs, handle errors in server actions, add middleware to actions, or build type-safe mutations in Next.js.
🇯🇵 日本人クリエイター向け解説
Next.jsでサーバーアクションの入力値を安全に検証したり、エラー処理をしたり、ミドルウェアを追加したり、型安全な変更処理を構築したりする際に、より安全で効率的な開発を実現するSkill。
※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。
下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o next-safe-action.zip https://jpskill.com/download/15165.zip && unzip -o next-safe-action.zip && rm next-safe-action.zip
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/15165.zip -OutFile "$d\next-safe-action.zip"; Expand-Archive "$d\next-safe-action.zip" -DestinationPath $d -Force; ri "$d\next-safe-action.zip"
完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。
💾 手動でダウンロードしたい(コマンドが難しい人向け)
- 1. 下の青いボタンを押して
next-safe-action.zipをダウンロード - 2. ZIPファイルをダブルクリックで解凍 →
next-safe-actionフォルダができる - 3. そのフォルダを
C:\Users\あなたの名前\.claude\skills\(Win)または~/.claude/skills/(Mac)へ移動 - 4. Claude Code を再起動
⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。
🎯 このSkillでできること
下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。
📦 インストール方法 (3ステップ)
- 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
- 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
- 3. 展開してできたフォルダを、ホームフォルダの
.claude/skills/に置く- · macOS / Linux:
~/.claude/skills/ - · Windows:
%USERPROFILE%\.claude\skills\
- · macOS / Linux:
Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。
詳しい使い方ガイドを見る →- 最終更新
- 2026-05-18
- 取得日時
- 2026-05-18
- 同梱ファイル
- 1
📖 Skill本文(日本語訳)
※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。
next-safe-action
概要
next-safe-action は、Next.js Server Actions に型安全性、入力検証、およびミドルウェアを追加します。FormData の手動解析やエラー処理を行う代わりに、Zod スキーマを定義することで、検証済みの型付き入力を自動エラー処理とともに取得できます。
手順
ステップ 1: セットアップ
npm install next-safe-action zod
// lib/safe-action.ts — 認証ミドルウェアを備えたアクションクライアント
import { createSafeActionClient } from 'next-safe-action'
import { auth } from '@/auth'
// パブリックアクション (認証不要)
export const publicAction = createSafeActionClient()
// 認証済みアクション
export const authAction = createSafeActionClient({
async middleware() {
const session = await auth()
if (!session?.user) throw new Error('Not authenticated')
return { user: session.user }
},
})
ステップ 2: アクションの定義
// actions/projects.ts — 型安全なサーバーアクション
'use server'
import { authAction } from '@/lib/safe-action'
import { z } from 'zod'
import { prisma } from '@/lib/db'
import { revalidatePath } from 'next/cache'
const createProjectSchema = z.object({
name: z.string().min(1).max(100),
description: z.string().max(500).optional(),
})
export const createProject = authAction
.schema(createProjectSchema)
.action(async ({ parsedInput, ctx }) => {
const project = await prisma.project.create({
data: {
...parsedInput,
ownerId: ctx.user.id,
},
})
revalidatePath('/dashboard')
return { project }
})
const updateProjectSchema = z.object({
id: z.string().uuid(),
name: z.string().min(1).max(100).optional(),
description: z.string().max(500).optional(),
status: z.enum(['active', 'archived']).optional(),
})
export const updateProject = authAction
.schema(updateProjectSchema)
.action(async ({ parsedInput, ctx }) => {
const { id, ...data } = parsedInput
// 所有権の検証
const project = await prisma.project.findFirst({
where: { id, ownerId: ctx.user.id },
})
if (!project) throw new Error('Project not found')
const updated = await prisma.project.update({
where: { id },
data,
})
revalidatePath(`/projects/${id}`)
return { project: updated }
})
ステップ 3: コンポーネントでの使用
// components/CreateProjectForm.tsx — セーフアクションを備えたフォーム
'use client'
import { useAction } from 'next-safe-action/hooks'
import { createProject } from '@/actions/projects'
export function CreateProjectForm() {
const { execute, result, isExecuting } = useAction(createProject)
return (
<form action={execute}>
<input name="name" placeholder="Project name" required />
<textarea name="description" placeholder="Description (optional)" />
{result.validationErrors && (
<div className="errors">
{Object.entries(result.validationErrors).map(([field, errors]) => (
<p key={field}>{field}: {errors?.join(', ')}</p>
))}
</div>
)}
{result.serverError && (
<p className="error">{result.serverError}</p>
)}
<button disabled={isExecuting}>
{isExecuting ? 'Creating...' : 'Create Project'}
</button>
</form>
)
}
ガイドライン
- 入力検証には常に Zod スキーマを使用してください — クライアントから送信されたデータを決して信用しないでください。
- 認証にはミドルウェアを使用してください — チェーン内のすべてのアクションの前に実行されます。
useActionフックはisExecuting、result、および自動エラー処理を提供します。- 瞬時の UI フィードバックのために
useOptimisticActionと組み合わせてください。 - UI をデータベースと同期させるために、変更後にパス/タグを再検証してください。
📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開
next-safe-action
Overview
next-safe-action adds type safety, input validation, and middleware to Next.js Server Actions. Instead of manually parsing FormData and handling errors, define a Zod schema and get validated, typed inputs with automatic error handling.
Instructions
Step 1: Setup
npm install next-safe-action zod
// lib/safe-action.ts — Action client with auth middleware
import { createSafeActionClient } from 'next-safe-action'
import { auth } from '@/auth'
// Public actions (no auth required)
export const publicAction = createSafeActionClient()
// Authenticated actions
export const authAction = createSafeActionClient({
async middleware() {
const session = await auth()
if (!session?.user) throw new Error('Not authenticated')
return { user: session.user }
},
})
Step 2: Define Actions
// actions/projects.ts — Type-safe server actions
'use server'
import { authAction } from '@/lib/safe-action'
import { z } from 'zod'
import { prisma } from '@/lib/db'
import { revalidatePath } from 'next/cache'
const createProjectSchema = z.object({
name: z.string().min(1).max(100),
description: z.string().max(500).optional(),
})
export const createProject = authAction
.schema(createProjectSchema)
.action(async ({ parsedInput, ctx }) => {
const project = await prisma.project.create({
data: {
...parsedInput,
ownerId: ctx.user.id,
},
})
revalidatePath('/dashboard')
return { project }
})
const updateProjectSchema = z.object({
id: z.string().uuid(),
name: z.string().min(1).max(100).optional(),
description: z.string().max(500).optional(),
status: z.enum(['active', 'archived']).optional(),
})
export const updateProject = authAction
.schema(updateProjectSchema)
.action(async ({ parsedInput, ctx }) => {
const { id, ...data } = parsedInput
// Verify ownership
const project = await prisma.project.findFirst({
where: { id, ownerId: ctx.user.id },
})
if (!project) throw new Error('Project not found')
const updated = await prisma.project.update({
where: { id },
data,
})
revalidatePath(`/projects/${id}`)
return { project: updated }
})
Step 3: Use in Components
// components/CreateProjectForm.tsx — Form with safe action
'use client'
import { useAction } from 'next-safe-action/hooks'
import { createProject } from '@/actions/projects'
export function CreateProjectForm() {
const { execute, result, isExecuting } = useAction(createProject)
return (
<form action={execute}>
<input name="name" placeholder="Project name" required />
<textarea name="description" placeholder="Description (optional)" />
{result.validationErrors && (
<div className="errors">
{Object.entries(result.validationErrors).map(([field, errors]) => (
<p key={field}>{field}: {errors?.join(', ')}</p>
))}
</div>
)}
{result.serverError && (
<p className="error">{result.serverError}</p>
)}
<button disabled={isExecuting}>
{isExecuting ? 'Creating...' : 'Create Project'}
</button>
</form>
)
}
Guidelines
- Always use Zod schemas for input validation — never trust client-submitted data.
- Use middleware for authentication — runs before every action in the chain.
useActionhook providesisExecuting,result, and automatic error handling.- Combine with
useOptimisticActionfor instant UI feedback. - Revalidate paths/tags after mutations to keep the UI in sync with the database.