本文へ移動
cccskills
無料GitHub で公開

frontend-api-integration

Integrate with the FastAPI backend through the typed wrapper in frontend/lib/api.ts, attach Supabase JWTs for admin calls, and handle errors via ApiError. Use when adding/modifying API calls or wiring auth.

インストール方法を見る

含まれるファイル(1)

  • SKILL.md6.7 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

API Integration Skill

Version: 1.0 | Working Directory: frontend/

API integration patterns for $ARGUMENTS in the Next.js frontend.

Overview

Single API surface, single auth flow:

  • frontend/lib/api.ts — typed fetch wrapper, ApiError class, helpers per endpoint
  • process.env.NEXT_PUBLIC_API_URL — base URL (no other URLs hardcoded anywhere)
  • Supabase Auth — admin JWT obtained from the Supabase session and passed as token to admin* helpers
  • @supabase/ssr — createSupabaseServerClient() for RSC/route handlers, createSupabaseBrowserClient() for Client Components

Constitution (Non-Negotiable Rules)

#RuleWhy
1Every backend call is a typed helper in lib/api.ts — never fetch against NEXT_PUBLIC_API_URL from a component or pageOne typed surface, one place to add headers/cache
2Admin calls require token — get it from supabase.auth.getSession() and pass to the helperBackend's require_admin checks the JWT
3Never hardcode the API URL — always via NEXT_PUBLIC_API_URLEnvironment-portable
4Throw ApiError — non-2xx responses already throw; let it propagate or catch with instanceof ApiError for detailConsistent error surface
5Strict types for request and response — define them in lib/types.ts, import where usedNo any
6No service-role secret on the frontend — never reference SUPABASE_SERVICE_ROLE_KEY from frontend/; that key is backend-onlyService-role bypasses RLS
7Cache choice is deliberate — admin/checkout helpers use cache: "no-store" (already set); use next: { revalidate: N } for ISR-eligible readsAvoid stale dashboards and accidental caching of mutations
8Multipart goes through a dedicated helper — adminUploadImage builds FormData and skips Content-Type so the browser sets the boundaryMultipart needs no manual Content-Type

When to Use

  • Adding a new FastAPI endpoint to consume from the UI
  • Modifying error handling for a call
  • Wiring admin auth into a new admin page
  • Adding a multipart upload

Quick Start

1. Add a typed helper

// frontend/lib/api.ts
export function adminBulkUpdateProducts(token: string, ids: string[], patch: Partial<Product>) {
  return api<Product[]>(`/api/admin/products/bulk`, {
    method: "POST",
    token,
    body: JSON.stringify({ ids, patch }),
  });
}

(If new shapes are involved, define them in frontend/lib/types.ts first.)

2. Use it from a Server Component (admin)

import { createSupabaseServerClient } from "@/lib/supabase/server";
import { adminListOrders } from "@/lib/api";

export default async function OrdersPage() {
  const supabase = await createSupabaseServerClient();
  const { data: { session } } = await supabase.auth.getSession();
  if (!session) redirect("/admin/login");
  const { items } = await adminListOrders(session.access_token, { limit: 50 });
  return <OrdersTable items={items} />;
}

3. Use it from a Client Component (admin mutation)

"use client";
import { useRouter } from "next/navigation";
import { createSupabaseBrowserClient } from "@/lib/supabase/client";
import { adminSetOrderStatus, ApiError } from "@/lib/api";

export function StatusDropdown({ orderId, current }: { orderId: string; current: string }) {
  const router = useRouter();
  async function onChange(next: string) {
    const supabase = createSupabaseBrowserClient();
    const { data: { session } } = await supabase.auth.getSession();
    if (!session) return;
    try {
      await adminSetOrderStatus(session.access_token, orderId, next);
      router.refresh();
    } catch (err) {
      alert(err instanceof ApiError ? String(err.detail) : "Update failed");
    }
  }
  return <select defaultValue={current} onChange={(e) => onChange(e.target.value)}>{/* ... */}</select>;
}

4. Public/storefront call from a Server Component

import { listProducts } from "@/lib/api";
const { items } = await listProducts({ q, limit: 24 });

Auth & Token Lifecycle

  • Sign-in / sign-out — frontend/app/admin/login/page.tsx uses createSupabaseBrowserClient() to call signInWithPassword / signOut
  • Session refresh — frontend/middleware.ts runs updateSession() for /admin/:path*, which keeps cookies fresh on every request
  • Reading the session — server: createSupabaseServerClient().auth.getSession(); client: createSupabaseBrowserClient().auth.getSession()
  • Role check — user.app_metadata?.role === "admin"; non-admins get a redirect/403 server-side
  • Never copy the access token into localStorage or attach it to non-admin requests

Cache Strategy

CallCache
Admin list/detailcache: "no-store" (already set) — admins want fresh data
Mutations (POST/PATCH)cache: "no-store"
Public product list/detailcache: "no-store" for now; switch to next: { revalidate: 60 } if traffic warrants
After a mutationrouter.refresh() from the Client Component to re-render server data

Errors

api() throws ApiError(status, detail) for non-2xx. detail is the parsed JSON body when the server returned JSON (FastAPI usually returns { "detail": "..." }), otherwise the raw text.

try { await checkout(payload); }
catch (e) {
  if (e instanceof ApiError) {
    const msg = typeof e.detail === "object" && e.detail && "detail" in e.detail
      ? String((e.detail as { detail: unknown }).detail)
      : String(e.detail);
    setError(msg);
  } else {
    setError("Network error");
  }
}

In Server Components: let it bubble to the closest error.tsx, or catch and notFound() for 404s (see exemplar app/(store)/products/[slug]/page.tsx).

Multipart Uploads

adminUploadImage is the template:

  • Build FormData, append the file
  • Bypass the JSON api() wrapper (it sets Content-Type: application/json)
  • Set Authorization manually; let the browser set the multipart boundary
  • Throw ApiError on non-2xx for parity

Don't add a generic multipart helper unless a second upload endpoint shows up.

Exemplar Files

  • frontend/lib/api.ts — every helper, ApiError, the api<T>() core
  • frontend/lib/supabase/server.ts — RSC/route-handler client
  • frontend/lib/supabase/client.ts — browser client
  • frontend/lib/supabase/middleware.ts — session refresh used by frontend/middleware.ts
  • frontend/lib/types.ts — request/response types

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

Supabase Postgres + Storage + Auth operations from FastAPI — service-role client, RLS-aware queries, additive SQL migrations under backend/db/migrations, the create_order RPC, and the product-images bucket. Use when adding tables/columns, writing queries, calling RPCs, or working with Storage.

日本語の概要は準備中です。原文の説明を表示しています。

shanraisshan/learning-x-claude22026年5月7日 更新

Build FastAPI endpoints in the layered router → service → Supabase pattern, with Pydantic v2 schemas, JWT/admin gating, and consistent HTTPException-based domain errors. Use when adding/modifying any endpoint under backend/.

日本語の概要は準備中です。原文の説明を表示しています。

shanraisshan/learning-x-claude22026年5月7日 更新

pytest + httpx + TestClient patterns for the FastAPI backend. Dependency overrides for auth, FakeSupabase mocking, HTTPException assertions. Use when writing or reviewing backend/tests/test_*.py.

日本語の概要は準備中です。原文の説明を表示しています。

shanraisshan/learning-x-claude22026年5月7日 更新

Drive Chrome via the claude-in-chrome MCP to exercise plan.md::Verify steps for a shipped feature. Loads deferred MCP tool schemas, asserts console/network cleanliness, records a GIF for the PR. Used by the browser-verifier agent.

日本語の概要は準備中です。原文の説明を表示しています。

shanraisshan/learning-x-claude22026年5月7日 更新

Pre-PR code review checklist for this repo. Plan alignment, security gates, layering, dead code, API-surface completeness. Used by the code-reviewer agent.

日本語の概要は準備中です。原文の説明を表示しています。

shanraisshan/learning-x-claude22026年5月7日 更新

Build pages and components in the Next.js 15 App Router (RSC by default, "use client" only when needed), Tailwind for styling, typed props, and the existing CartProvider for cart state. Use when creating or modifying pages, layouts, components, or forms in frontend/.

日本語の概要は準備中です。原文の説明を表示しています。

shanraisshan/learning-x-claude22026年5月7日 更新

shanraisshan のスキルをすべて見る

このスキルの問題を報告する