Agent Skills by ALSEL
Anthropic ClaudeLLM・AI開発⭐ リポ 0品質スコア 50/100

tanstack-start

TanStack Startを使ってCloudflare Workers上にフルスタックアプリをゼロから構築します。SSR・ファイルベースルーティング・サーバー関数・D1+Drizzle・better-auth・Tailwind v4+shadcn/uiに対応しており、ユーザーがTanStack Startに言及した場合や、SSR付きCloudflareアプリのスキャフォールド、React 19+Cloudflare Workersのファイルベースルーティング構成を求めた際に自動で起動します。テンプレートリポジトリは使用せず、プロジェクトごとにすべてのファイルをClaudeが新規生成します。

description の原文を見る

Build a full-stack TanStack Start app on Cloudflare Workers from scratch — SSR, file-based routing, server functions, D1+Drizzle, better-auth, Tailwind v4+shadcn/ui. Use whenever the user mentions TanStack Start, asks to scaffold a full-stack Cloudflare app with SSR, wants an SSR dashboard, or asks for a React 19 + Cloudflare Workers app with file-based routing and server functions — even if they don't name TanStack Start specifically. No template repo — Claude generates every file fresh per project.

SKILL.md 本文

Cloudflare 上の TanStack Start

ゼロから完全なフルスタックアプリを構築します。Claude がすべてのファイルを生成します — テンプレートのクローンもスカフォルドコマンドも不要です。

スタック: Cloudflare Workers 上の TanStack Start v1(SSR、ファイルベースのルーティング、Nitro 経由のサーバー関数); React 19 + Tailwind v4 + shadcn/ui; D1 + Drizzle; better-auth(Google OAuth + メール/パスワード)。

プロジェクトファイルツリー

PROJECT_NAME/
├── src/
│   ├── routes/
│   │   ├── __root.tsx              # ルートレイアウト(HTML シェル、テーマ、CSS インポート)
│   │   ├── index.tsx               # ランディングページ / 認証リダイレクト
│   │   ├── login.tsx               # ログインページ
│   │   ├── register.tsx            # 登録ページ
│   │   ├── _authed.tsx             # 認証ガードレイアウトルート
│   │   ├── _authed/
│   │   │   ├── dashboard.tsx       # ダッシュボード(スタットカード付き)
│   │   │   ├── items.tsx           # アイテムリスト(テーブル)
│   │   │   ├── items.$id.tsx       # アイテム編集
│   │   │   └── items.new.tsx       # アイテム作成
│   │   └── api/
│   │       └── auth/
│   │           └── $.ts            # better-auth API キャッチオール
│   ├── components/
│   │   ├── ui/                     # shadcn/ui コンポーネント(自動インストール)
│   │   ├── app-sidebar.tsx         # ナビゲーションサイドバー
│   │   ├── theme-toggle.tsx        # ライト/ダーク/システム切り替え
│   │   ├── user-nav.tsx            # ユーザードロップダウンメニュー
│   │   └── stat-card.tsx           # ダッシュボードスタットカード
│   ├── db/
│   │   ├── schema.ts               # Drizzle スキーマ(全テーブル)
│   │   └── index.ts                # Drizzle クライアントファクトリ
│   ├── lib/
│   │   ├── auth.server.ts          # better-auth サーバー設定
│   │   ├── auth.client.ts          # better-auth React フック
│   │   └── utils.ts                # shadcn/ui 用 cn() ヘルパー
│   ├── server/
│   │   └── functions.ts            # サーバー関数(CRUD、認証チェック)
│   ├── styles/
│   │   └── app.css                 # Tailwind v4 + shadcn/ui CSS 変数
│   ├── router.tsx                  # TanStack Router 設定
│   ├── client.tsx                  # クライアントエントリー(hydrateRoot)
│   ├── ssr.tsx                     # SSR エントリー
│   └── routeTree.gen.ts            # 自動生成ルートツリー(編集禁止)
├── drizzle/                        # 生成されたマイグレーション
├── public/                         # 静的アセット(favicon など)
├── vite.config.ts
├── wrangler.jsonc
├── drizzle.config.ts
├── tsconfig.json
├── package.json
├── .dev.vars                       # ローカル環境変数(コミット対象外)
└── .gitignore

依存関係

ランタイム:

{
  "react": "^19.0.0",
  "react-dom": "^19.0.0",
  "@tanstack/react-router": "^1.120.0",
  "@tanstack/react-start": "^1.120.0",
  "drizzle-orm": "^0.38.0",
  "better-auth": "^1.2.0",
  "zod": "^3.24.0",
  "class-variance-authority": "^0.7.0",
  "clsx": "^2.1.0",
  "tailwind-merge": "^3.0.0",
  "lucide-react": "^0.480.0"
}

開発環境:

{
  "@cloudflare/vite-plugin": "^1.0.0",
  "@tailwindcss/vite": "^4.0.0",
  "@vitejs/plugin-react": "^4.4.0",
  "tailwindcss": "^4.0.0",
  "typescript": "^5.7.0",
  "drizzle-kit": "^0.30.0",
  "wrangler": "^4.0.0",
  "tw-animate-css": "^1.2.0"
}

スクリプト:

{
  "dev": "vite",
  "build": "vite build",
  "preview": "vite preview",
  "deploy": "wrangler deploy",
  "db:generate": "drizzle-kit generate",
  "db:migrate:local": "wrangler d1 migrations apply PROJECT_NAME-db --local",
  "db:migrate:remote": "wrangler d1 migrations apply PROJECT_NAME-db --remote"
}

ワークフロー

ステップ 1: プロジェクト情報を収集

必須オプション
プロジェクト名(ケバブケース)Google OAuth 認証情報
1 行の説明カスタムドメイン
Cloudflare アカウントR2 ストレージが必要?
認証方法: Google OAuth、メール/パスワード、または両方管理者メール

ステップ 2: プロジェクトを初期化

プロジェクトディレクトリとすべての設定ファイルをゼロから作成します。

vite.config.ts — プラグインの順序が重要です。Cloudflare は最初にする必要があります:

import { defineConfig } from "vite";
import { cloudflare } from "@cloudflare/vite-plugin";
import { tanstackStart } from "@tanstack/react-start/plugin/vite";
import tailwindcss from "@tailwindcss/vite";
import viteReact from "@vitejs/plugin-react";

export default defineConfig({
  plugins: [
    cloudflare({ viteEnvironment: { name: "ssr" } }),
    tailwindcss(),
    tanstackStart(),
    viteReact(),
  ],
});

wrangler.jsonc:

{
  "$schema": "node_modules/wrangler/config-schema.json",
  "name": "PROJECT_NAME",
  "compatibility_date": "2025-04-01",
  "compatibility_flags": ["nodejs_compat"],
  "main": "@tanstack/react-start/server-entry",
  "account_id": "ACCOUNT_ID",
  "d1_databases": [
    {
      "binding": "DB",
      "database_name": "PROJECT_NAME-db",
      "database_id": "DATABASE_ID",
      "migrations_dir": "drizzle"
    }
  ]
}

重要なポイント: main は必ず "@tanstack/react-start/server-entry" である必要があります(Nitro サーバーエントリー)。nodejs_compat を使用します(node_compat ではなく)。インタラクティブなプロンプトを避けるために account_id を追加します。

tsconfig.json:

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ESNext",
    "moduleResolution": "bundler",
    "jsx": "react-jsx",
    "strict": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true,
    "paths": { "@/*": ["./src/*"] },
    "types": ["@cloudflare/workers-types/2023-07-01"]
  },
  "include": ["src/**/*", "vite.config.ts"]
}

.dev.varsopenssl rand -hex 32BETTER_AUTH_SECRET を生成します:

BETTER_AUTH_SECRET=<generated-hex-32>
BETTER_AUTH_URL=http://localhost:3000
TRUSTED_ORIGINS=http://localhost:3000
# GOOGLE_CLIENT_ID=
# GOOGLE_CLIENT_SECRET=

.gitignore — node_modules、.wrangler、dist、.output、.dev.vars、.vinxi、.DS_Store

その後、インストールして D1 データベースを作成します:

cd PROJECT_NAME && pnpm install
npx wrangler d1 create PROJECT_NAME-db
# database_id を wrangler.jsonc の d1_databases バインディングにコピーします

ステップ 3: データベーススキーマ

src/db/schema.ts — すべてのテーブル。better-auth には以下が必要です: userssessionsaccountsverifications。CRUD デモ用にアプリケーションテーブル(例: items)を追加します。

D1 固有のルール:

  • タイムスタンプに integer を使用します(Unix エポック)、Date オブジェクトではなく
  • 主キーに text を使用します(nanoid/cuid2)、オートインクリメントではなく
  • バインドされたパラメータを 1 クエリあたり 100 以下に保ちます(大量挿入はバッチ処理)
  • D1 では外部キーは常に ON です

src/db/index.ts — Drizzle クライアントファクトリ:

import { drizzle } from "drizzle-orm/d1";
import { env } from "cloudflare:workers";
import * as schema from "./schema";

export function getDb() {
  return drizzle(env.DB, { schema });
}

重大: import { env } from "cloudflare:workers" を使用します — process.env ではなく。Drizzle クライアントを各サーバー関数内(リクエストごと)で作成します。モジュールレベルでではなく。

drizzle.config.ts:

import { defineConfig } from "drizzle-kit";

export default defineConfig({
  schema: "./src/db/schema.ts",
  out: "./drizzle",
  dialect: "sqlite",
});

初期マイグレーションを生成して適用します:

pnpm db:generate
pnpm db:migrate:local

ステップ 4: 認証を設定

src/lib/auth.server.ts — サーバーサイド better-auth:

import { betterAuth } from "better-auth";
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { drizzle } from "drizzle-orm/d1";
import { env } from "cloudflare:workers";
import * as schema from "../db/schema";

export function getAuth() {
  const db = drizzle(env.DB, { schema });
  return betterAuth({
    database: drizzleAdapter(db, { provider: "sqlite" }),
    secret: env.BETTER_AUTH_SECRET,
    baseURL: env.BETTER_AUTH_URL,
    trustedOrigins: env.TRUSTED_ORIGINS?.split(",") ?? [],
    emailAndPassword: { enabled: true },
    socialProviders: {
      // 認証情報が提供されている場合は Google OAuth を追加
    },
  });
}

重大: getAuth() はリクエストごと(ハンドラー/ローダー内)に呼び出す必要があります。モジュールレベルではなく。

src/lib/auth.client.ts — クライアントサイド認証フック:

import { createAuthClient } from "better-auth/react";

export const { useSession, signIn, signOut, signUp } = createAuthClient();

src/routes/api/auth/$.ts — better-auth 用 API キャッチオール:

import { createAPIFileRoute } from "@tanstack/react-start/api";
import { getAuth } from "../../../lib/auth.server";

export const APIRoute = createAPIFileRoute("/api/auth/$")({
  GET: ({ request }) => getAuth().handler(request),
  POST: ({ request }) => getAuth().handler(request),
});

重大: 認証は API ルート(createAPIFileRoute)を使用する必要があります。サーバー関数(createServerFn)ではなく。better-auth は直接のリクエスト/レスポンスアクセスが必要です。

ステップ 5: サーバー関数

コアパターン — ハンドラー内に常に DB クライアントを作成します:

import { createServerFn } from "@tanstack/react-start";
import { getDb } from "../db";

export const getItems = createServerFn({ method: "GET" }).handler(async () => {
  const db = getDb();
  return db.select().from(items).all();
});

Zod での入力検証:

export const createItem = createServerFn({ method: "POST" })
  .inputValidator(
    z.object({
      name: z.string().min(1),
      description: z.string().optional(),
    })
  )
  .handler(async ({ data }) => {
    const db = getDb();
    const id = crypto.randomUUID();
    await db.insert(items).values({ id, ...data, createdAt: Date.now() });
    return { id };
  });

保護されたサーバー関数 — 認証をチェックし、未認証の場合はリダイレクトをスロー:

import { redirect } from "@tanstack/react-router";
import { getAuth } from "../lib/auth.server";

async function requireSession(request?: Request) {
  const auth = getAuth();
  const session = await auth.api.getSession({
    headers: request?.headers ?? new Headers(),
  });
  if (!session) {
    throw redirect({ to: "/login" });
  }
  return session;
}

export const getSessionFn = createServerFn({ method: "GET" }).handler(
  async ({ request }) => {
    const auth = getAuth();
    return auth.api.getSession({ headers: request.headers });
  }
);

export const getItems = createServerFn({ method: "GET" }).handler(
  async ({ request }) => {
    const session = await requireSession(request);
    const db = getDb();
    return db.select().from(items).where(eq(items.userId, session.user.id)).all();
  }
);

ルートローダーパターン — ルート loader のサーバー関数:

export const Route = createFileRoute("/_authed/items")({
  loader: () => getItems(),
  component: ItemsPage,
});

function ItemsPage() {
  const items = Route.useLoaderData();
  return <div>{items.map((item) => <div key={item.id}>{item.name}</div>)}</div>;
}

認証ガード_authed.tsx)— beforeLoad を使用:

export const Route = createFileRoute("/_authed")({
  beforeLoad: async () => {
    const session = await getSessionFn();
    if (!session) {
      throw redirect({ to: "/login" });
    }
    return { session };
  },
});

子ルートは Route.useRouteContext() でセッションにアクセスします。

ミューテーション + 無効化 — ミューテーション後、ローダーを再取得するためにルーターを無効化:

function CreateItemForm() {
  const router = useRouter();
  const handleSubmit = async (data: NewItem) => {
    await createItem({ data });
    router.invalidate();
    router.navigate({ to: "/items" });
  };
  return <form onSubmit={...}>...</form>;
}

型安全性 — サーバー関数の入出力型に Drizzle の InferSelectModel / InferInsertModel を使用します。認証失敗の場合は常に throw redirect() を使用します — エラーレスポンスではなく。

ステップ 6: アプリシェル + テーマ

src/routes/__root.tsx@tanstack/react-router<HeadContent /><Scripts /> を含む完全な HTML ドキュメント、<html>suppressHydrationWarning(SSR + テーマ用)、フラッシュを防ぐためのインラインテーマ初期化スクリプト、グローバル CSS インポート。

src/styles/app.css@import "tailwindcss"(v4 構文)+ :root.dark の shadcn/ui CSS 変数。セマンティックトークンのみ。

src/router.tsx:

import { createRouter as createTanStackRouter } from "@tanstack/react-router";
import { routeTree } from "./routeTree.gen";

export function createRouter() {
  return createTanStackRouter({ routeTree });
}

declare module "@tanstack/react-router" {
  interface Register {
    router: ReturnType<typeof createRouter>;
  }
}

src/client.tsx + src/ssr.tsx — 標準的な TanStack Start エントリーボイラープレート。

shadcn/ui をインストール:

pnpm dlx shadcn@latest init --defaults
pnpm dlx shadcn@latest add button card input label sidebar table dropdown-menu form separator sheet

テーマ切り替え — 3 段階(light → dark → system → light)、localStorage 保持、<html>.dark クラス。JS のみシステム環境設定検出。CSS @media (prefers-color-scheme) クエリはなし。

コンポーネント in src/components/: app-sidebar.tsxtheme-toggle.tsxuser-nav.tsxstat-card.tsx

ステップ 7: CRUD サーバー関数

関数メソッド目的
getItemsGET現在のユーザーのすべてのアイテムを一覧表示
getItemGETID で単一アイテムを取得
createItemPOST新しいアイテムを作成
updateItemPOST既存アイテムを更新
deleteItemPOSTID でアイテムを削除

各サーバー関数: (1) 認証セッションを取得、(2) getDb() 経由でリクエストごと Drizzle クライアントを作成、(3) DB 操作を実行、(4) 型付きデータを返す。ルートローダーは GET 関数を呼び出し。ミューテーションは POST 関数を呼び出してから router.invalidate() を実行。

ステップ 8: ローカルで検証

pnpm dev
  • アプリが http://localhost:3000 で読み込まれる
  • 新しいアカウントを登録(メール/パスワード)
  • ログインとログアウトが機能する
  • ダッシュボードがスタットカード付きで読み込まれる
  • アイテムの作成、一覧表示、編集、削除
  • テーマ切り替えが light -> dark -> system をサイクル
  • サイドバーがモバイルで折りたたまれる
  • コンソールエラーなし

ステップ 9: 本番環境にデプロイ

デプロイ前のチェックリスト — デプロイ実行前に検証します:

  • wrangler.jsonc に正しい account_id がある; main"@tanstack/react-start/server-entry" である; compatibility_flagsnodejs_compat がある
  • D1 データベースが作成済みで database_id が設定されている
  • .dev.vars がgitignored; ソース内にハードコードされたシークレットがない

本番環境シークレットを設定:

openssl rand -hex 32 | npx wrangler secret put BETTER_AUTH_SECRET
echo "https://PROJECT.SUBDOMAIN.workers.dev" | npx wrangler secret put BETTER_AUTH_URL
echo "http://localhost:3000,https://PROJECT.SUBDOMAIN.workers.dev" | npx wrangler secret put TRUSTED_ORIGINS

# Google OAuth(オプション)
echo "your-client-id" | npx wrangler secret put GOOGLE_CLIENT_ID
echo "your-client-secret" | npx wrangler secret put GOOGLE_CLIENT_SECRET

Google OAuth を使用する場合、Google Cloud Console で本番リダイレクト URI を追加します: https://PROJECT.SUBDOMAIN.workers.dev/api/auth/callback/google

マイグレーションしてデプロイ:

pnpm db:migrate:remote
pnpm build && npx wrangler deploy

最初のデプロイ後、BETTER_AUTH_URL を実際の Worker URL に更新してから再度デプロイします。

検証: 本番環境 URL でアプリが読み込まれ、認証が機能し、CRUD が機能し、テーマが保持される。

カスタムドメイン(オプション): Cloudflare ダッシュボード → Workers → トリガー → カスタムドメイン。BETTER_AUTH_URL + TRUSTED_ORIGINS シークレット + Google OAuth リダイレクト URI を新しいドメインに更新。再度デプロイします。

よくある問題

症状原因修正
env が undefinedモジュールレベルでアクセスリクエストハンドラー内でのみ import { env } from "cloudflare:workers" を使用
D1 データベースが見つからないバインディング不一致wrangler.jsonc の d1_databases バインディング名がコードと一致するか確認
認証リダイレクトループURL 不一致BETTER_AUTH_URL は実際の URL と完全に一致する必要があります(プロトコル + ドメイン、末尾のスラッシュなし)
認証が黙って失敗オリジンが足りないTRUSTED_ORIGINS シークレットをすべての有効な URL で設定します(カンマ区切り)
スタイルが読み込まれないプラグインが足りない@tailwindcss/vite プラグインが vite.config.ts にあるか確認
SSR ハイドレーション不一致テーマフラッシュ<html> 要素に suppressHydrationWarning を追加
Cloudflare でビルドが失敗設定不良wrangler.jsonc の nodejs_compat フラグと main フィールドを確認
シークレットが反映されない再度デプロイなしwrangler secret put は再度デプロイしません — その後 npx wrangler deploy を実行
認証エンドポイントが 404 を返すルート型が間違っているbetter-auth に createServerFn ではなく createAPIFileRoute(API ルート)を使用
"redirect_uri_mismatch"URI が足りないGoogle Cloud Console OAuth リダイレクト URI に本番環境 URL を追加
不可解な Vite エラープラグイン順序順序は必ず: cloudflare() -> tailwindcss() -> tanstackStart() -> viteReact()
"Table not found" 500sマイグレーション欠落デプロイ前に pnpm db:migrate:remote を実行

ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ

詳細情報

作者
jezweb
リポジトリ
jezweb/claude-skills
ライセンス
MIT
最終更新
不明

Source: https://github.com/jezweb/claude-skills / ライセンス: MIT

関連スキル

OpenAILLM・AI開発⭐ リポ 6,054

agent-browser

AI エージェント向けのブラウザ自動化 CLI です。ウェブサイトとの対話が必要な場合に使用します。ページ遷移、フォーム入力、ボタンクリック、スクリーンショット取得、データ抽出、ウェブアプリのテスト、ブラウザ操作の自動化など、あらゆるブラウザタスクに対応できます。「ウェブサイトを開く」「フォームに記入する」「ボタンをクリックする」「スクリーンショットを取得する」「ページからデータを抽出する」「このウェブアプリをテストする」「サイトにログインする」「ブラウザ操作を自動化する」といった要求や、プログラマティックなウェブ操作が必要なタスクで起動します。

by JimmyLv
汎用LLM・AI開発⭐ リポ 1,982

anyskill

AnySkill — あなたのプライベート・スキルクラウド。GitHubを基盤としたリポジトリからエージェントスキルを管理、同期、動的にロードできます。自然言語でクラウドスキルを検索し、オンデマンドでプロンプトを自動ロード、カスタムスキルのアップロードと共有、スキルバンドルの一括インストールが可能です。OpenClaw、Antigravity、Claude Code、Cursorに対応しています。

by LeoYeAI
汎用LLM・AI開発⭐ リポ 1,982

engram

AIエージェント向けの永続的なメモリシステムです。バグ修正、意思決定、発見、設定変更の後はmem_saveを使用してください。ユーザーが「覚えている」「記憶している」と言及した場合、または以前のセッションと重複する作業を開始する際はmem_searchを使用します。セッション終了前にmem_session_summaryを使用して、コンテキストを保持してください。

by LeoYeAI
汎用LLM・AI開発⭐ リポ 21,584

skyvern

AI駆動のブラウザ自動化により、任意のウェブサイトを自動化できます。フォーム入力、データ抽出、ファイルダウンロード、ログイン、複数ステップのワークフロー実行など、ユーザーがウェブサイトと連携する必要があるときに使用します。Skyvernは、LLMとコンピュータビジョンを活用して、未知のサイトも自動操作可能です。Python SDK、TypeScript SDK、REST API、MCPサーバー、またはCLIを通じて統合できます。

by Skyvern-AI
汎用LLM・AI開発⭐ リポ 1,149

pinchbench

PinchBenchベンチマークを実行して、OpenClawエージェントの実世界タスクにおけるパフォーマンスを評価できます。モデルの機能テスト、モデル間の比較、ベンチマーク結果のリーダーボード提出、またはOpenClawのセットアップがカレンダー、メール、リサーチ、コーディング、複数ステップのワークフローにどの程度対応しているかを確認する際に使用します。

by pinchbench
汎用LLM・AI開発⭐ リポ 4,693

openui

OpenUIとOpenUI Langを使用してジェネレーティブUIアプリを構築できます。これらはLLM生成インターフェースのためのトークン効率的なオープン標準です。OpenUI、@openuidev、ジェネレーティブUI、LLMからのストリーミングUI、AI向けコンポーネントライブラリ、またはjson-render/A2UIの置き換えについて述べる際に使用します。スキャフォルディング、defineComponent、システムプロンプト、Renderer、およびOpenUI Lang出力のデバッグに対応しています。

by thesysdev
本サイトは GitHub 上で公開されているオープンソースの SKILL.md ファイルをクロール・インデックス化したものです。 各スキルの著作権は原作者に帰属します。掲載に問題がある場合は info@alsel.co.jp または /takedown フォームよりご連絡ください。
原作者: jezweb · jezweb/claude-skills · ライセンス: MIT