jpskill.com
🛠️ 開発・MCP コミュニティ

api-endpoint-creation

Next.js 15+ API endpoint creation patterns with Supabase and workspace validation

⚡ おすすめ: コマンド1行でインストール(60秒)

下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。

🍎 Mac / 🐧 Linux
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o api-endpoint-creation.zip https://jpskill.com/download/17893.zip && unzip -o api-endpoint-creation.zip && rm api-endpoint-creation.zip
🪟 Windows (PowerShell)
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/17893.zip -OutFile "$d\api-endpoint-creation.zip"; Expand-Archive "$d\api-endpoint-creation.zip" -DestinationPath $d -Force; ri "$d\api-endpoint-creation.zip"

完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。

💾 手動でダウンロードしたい(コマンドが難しい人向け)
  1. 1. 下の青いボタンを押して api-endpoint-creation.zip をダウンロード
  2. 2. ZIPファイルをダブルクリックで解凍 → api-endpoint-creation フォルダができる
  3. 3. そのフォルダを C:\Users\あなたの名前\.claude\skills\(Win)または ~/.claude/skills/(Mac)へ移動
  4. 4. Claude Code を再起動

⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。

🎯 このSkillでできること

下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。

📦 インストール方法 (3ステップ)

  1. 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
  2. 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
  3. 3. 展開してできたフォルダを、ホームフォルダの .claude/skills/ に置く
    • · macOS / Linux: ~/.claude/skills/
    • · Windows: %USERPROFILE%\.claude\skills\

Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。

詳しい使い方ガイドを見る →
最終更新
2026-05-18
取得日時
2026-05-18
同梱ファイル
1

📖 Skill本文(日本語訳)

※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。

API Endpoint Creation Skill

Next.js 15+ API Route のパターン

いつ使うか: src/app/api/ に新しい API エンドポイントを作成するとき。


標準的なパターン

import { NextRequest } from 'next/server';
import { getSupabaseServer } from '@/lib/supabase';
import { validateUserAndWorkspace } from '@/lib/api-helpers';
import { successResponse, errorResponse } from '@/lib/api-helpers';
import { withErrorBoundary } from '@/lib/error-boundary';

export const GET = withErrorBoundary(async (req: NextRequest) => {
  // 1. クエリパラメータから workspace_id を抽出
  const workspaceId = req.nextUrl.searchParams.get("workspaceId");
  if (!workspaceId) {
    return errorResponse("workspaceId required", 400);
  }

  // 2. ユーザーがワークスペースへのアクセス権を持っているか検証
  await validateUserAndWorkspace(req, workspaceId);

  // 3. Supabase クライアントを取得 (サーバーサイド)
  const supabase = getSupabaseServer();

  // 4. workspace_id フィルターでクエリ (必須)
  const { data, error } = await supabase
    .from("your_table")
    .select("*")
    .eq("workspace_id", workspaceId);

  if (error) {
    return errorResponse(error.message, 500);
  }

  // 5. 成功レスポンスを返す
  return successResponse(data);
});

POST エンドポイントのパターン

export const POST = withErrorBoundary(async (req: NextRequest) => {
  const workspaceId = req.nextUrl.searchParams.get("workspaceId");
  if (!workspaceId) {
    return errorResponse("workspaceId required", 400);
  }

  const user = await validateUserAndWorkspace(req, workspaceId);
  const supabase = getSupabaseServer();

  // リクエストボディを解析
  const body = await req.json();
  const { name, data } = body;

  // バリデーション
  if (!name) {
    return errorResponse("name required", 400);
  }

  // workspace_id を指定して挿入
  const { data: result, error } = await supabase
    .from("your_table")
    .insert({
      workspace_id: workspaceId,
      name,
      data,
      created_by: user.id
    })
    .select()
    .single();

  if (error) {
    return errorResponse(error.message, 500);
  }

  return successResponse(result, 201);
});

必要なインポート

import { NextRequest } from 'next/server';
import { getSupabaseServer } from '@/lib/supabase';
import { validateUserAndWorkspace } from '@/lib/api-helpers';
import { successResponse, errorResponse } from '@/lib/api-helpers';
import { withErrorBoundary } from '@/lib/error-boundary';

チェックリスト

  • [ ] withErrorBoundary ラッパーを使用する
  • [ ] クエリパラメータから workspace_id を検証する
  • [ ] validateUserAndWorkspace を呼び出す
  • [ ] DB アクセスに getSupabaseServer() を使用する
  • [ ] すべてのクエリを workspace_id でフィルタリングする
  • [ ] successResponse または errorResponse を返す
  • [ ] エラーを適切に処理する
  • [ ] TypeScript の型を追加する

標準: すべての API ルートは、ワークスペースを検証し、workspace_id でフィルタリングする必要があります。

📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開

API Endpoint Creation Skill

Next.js 15+ API Route Patterns

When to Use: Creating new API endpoints in src/app/api/


Standard Pattern

import { NextRequest } from 'next/server';
import { getSupabaseServer } from '@/lib/supabase';
import { validateUserAndWorkspace } from '@/lib/api-helpers';
import { successResponse, errorResponse } from '@/lib/api-helpers';
import { withErrorBoundary } from '@/lib/error-boundary';

export const GET = withErrorBoundary(async (req: NextRequest) => {
  // 1. Extract workspace_id from query params
  const workspaceId = req.nextUrl.searchParams.get("workspaceId");
  if (!workspaceId) {
    return errorResponse("workspaceId required", 400);
  }

  // 2. Validate user has access to workspace
  await validateUserAndWorkspace(req, workspaceId);

  // 3. Get Supabase client (server-side)
  const supabase = getSupabaseServer();

  // 4. Query with workspace_id filter (MANDATORY)
  const { data, error } = await supabase
    .from("your_table")
    .select("*")
    .eq("workspace_id", workspaceId);

  if (error) {
    return errorResponse(error.message, 500);
  }

  // 5. Return success response
  return successResponse(data);
});

POST Endpoint Pattern

export const POST = withErrorBoundary(async (req: NextRequest) => {
  const workspaceId = req.nextUrl.searchParams.get("workspaceId");
  if (!workspaceId) {
    return errorResponse("workspaceId required", 400);
  }

  const user = await validateUserAndWorkspace(req, workspaceId);
  const supabase = getSupabaseServer();

  // Parse request body
  const body = await req.json();
  const { name, data } = body;

  // Validation
  if (!name) {
    return errorResponse("name required", 400);
  }

  // Insert with workspace_id
  const { data: result, error } = await supabase
    .from("your_table")
    .insert({
      workspace_id: workspaceId,
      name,
      data,
      created_by: user.id
    })
    .select()
    .single();

  if (error) {
    return errorResponse(error.message, 500);
  }

  return successResponse(result, 201);
});

Required Imports

import { NextRequest } from 'next/server';
import { getSupabaseServer } from '@/lib/supabase';
import { validateUserAndWorkspace } from '@/lib/api-helpers';
import { successResponse, errorResponse } from '@/lib/api-helpers';
import { withErrorBoundary } from '@/lib/error-boundary';

Checklist

  • [ ] Use withErrorBoundary wrapper
  • [ ] Validate workspace_id from query params
  • [ ] Call validateUserAndWorkspace
  • [ ] Use getSupabaseServer() for DB access
  • [ ] Filter ALL queries by workspace_id
  • [ ] Return successResponse or errorResponse
  • [ ] Handle errors properly
  • [ ] Add TypeScript types

Standard: Every API route MUST validate workspace and filter by workspace_id