tanstack-start
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.
DeepseekModel
キュレーション済みスキル
品質 優秀 · 90
v1.0.0
取得
https://deepseekmodel.com/api/download.php?id=jezweb-claude-skills-plugins-cloudflare-skills-tanstack-start-skill-md&format=skill
ダウンロード .skill
標準形式。system_prompt と model_config を収録し、任意の Agent で利用可能
.skill ファイルの system_prompt フィールドの実際の内容。
name tanstack-start 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. compatibility claude-code-only TanStack Start on Cloudflare Build a complete full-stack app from nothing. Claude generates every file — no template clone, no scaffold command. Stack: TanStack Start v1 (SSR, file-based routing, server functions via Nitro) on Cloudflare Workers; React 19 + Tailwind v4 + shadcn/ui; D1 + Drizzle; better-auth (Google OAuth + email/password). Project File Tree PROJECT_NAME/ ├── src/ │ ├── routes/ │ │ ├── __root.tsx # Root layout (HTML shell, theme, CSS import) │ │ ├── index.tsx # Landing / auth redirect │ │ ├── login.tsx # Login page │ │ ├── register.tsx # Register page │ │ ├── _authed.tsx # Auth guard layout route │ │ ├── _authed/ │ │ │ ├── dashboard.tsx # Dashboard with stat cards │ │ │ ├── items.tsx # Items list table │ │ │ ├── items.$id.tsx # Edit item │ │ │ └── items.new.tsx # Create item │ │ └── api/ │ │ └── auth/ │ │ └── $.ts # better-auth API catch-all │ ├── components/ │ │ ├── ui/ # shadcn/ui components (auto-installed) │ │ ├── app-sidebar.tsx # Navigation sidebar │ │ ├── theme-toggle.tsx # Light/dark/system toggle │ │ ├── user-nav.tsx # User dropdown menu │ │ └── stat-card.tsx # Dashboard stat card │ ├── db/ │ │ ├── schema.ts # Drizzle schema (all tables) │ │ └── index.ts # Drizzle client factory │ ├── lib/ │ │ ├── auth.server.ts # better-auth server config │ │ ├── auth.client.ts # better-auth React hooks │ │ └── utils.ts # cn() helper for shadcn/ui │ ├── server/ │ │ └── functions.ts # Server functions (CRUD, auth checks) │ ├── styles/ │ │ └── app.css # Tailwind v4 + shadcn/ui CSS variables │ ├── router.tsx # TanStack Router configuration │ ├── client.tsx # Client entry (hydrateRoot) │ ├── ssr.tsx # SSR entry │ └── routeTree.gen.ts # Auto-generated route tree (do not edit) ├── drizzle/ # Generated migrations ├── public/ # Static assets (favicon, etc.) ├── vite.config.ts ├── wrangler.jsonc ├── drizzle.config.ts ├── tsconfig.json ├── package.json ├── .dev.vars # Local env vars (NOT committed) └── .gitignore Dependencies Runtime: { "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" } Dev: { "@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" } Scripts: { "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" } Workflow Step 1: Gather Project Info Required Optional Project name (kebab-case) Google OAuth credentials One-line description Custom domain Cloudflare account R2 storage needed? Auth method: Google OAuth, email/password, or both Admin email Step 2: Initialise Project Create the project directory and all config files from scratch. vite.config.ts — Plugin order matters. Cloudflare MUST be first: 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" } ] } Key points: main MUST be "@tanstack/react-start/server-entry" (Nitro server entry). Use nodejs_compat (NOT node_compat ). Add account_id to avoid interactive prompts. 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.vars — generate BETTER_AUTH_SECRET with openssl rand -hex 32 : 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 Then install and create the D1 database: cd PROJECT_NAME && pnpm install npx wrangler d1 create PROJECT_NAME-db # Copy the database_id into wrangler.jsonc d1_databases binding Step 3: Database Schema src/db/schema.ts — All tables. better-auth requires: users , sessions , accounts , verifications . Add application tables (e.g. items ) for CRUD demo. D1-specific rules: Use integer for timestamps (Unix epoch), NOT Date objects Use text for primary keys (nanoid/cuid2), NOT autoincrement Keep bound parameters under 100 per query (batch large inserts) Foreign keys are always ON in D1 src/db/index.ts — Drizzle client factory: import { drizzle } from "drizzle-orm/d1" ; import { env } from "cloudflare:workers" ; import * as schema from "./schema" ; export function getDb ( ) { return drizzle (env. DB , { schema }); } CRITICAL : Use import { env } from "cloudflare:workers" — NOT process.env . Create the Drizzle client inside each server function (per-request), not at module level. drizzle.config.ts : import { defineConfig } from "drizzle-kit" ; export default defineConfig ({ schema : "./src/db/schema.ts" , out : "./drizzle" , dialect : "sqlite" , }); Generate and apply the initial migration: pnpm db:generate pnpm db:migrate: local Step 4: Configure Auth src/lib/auth.server.ts — Server-side 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 : { // Add Google OAuth if credentials provided }, }); } CRITICAL : getAuth() must be called per-request (inside handler/loader), NOT at module level. src/lib/auth.client.ts — Client-side auth hooks: import { createAuthClient } from "better-auth/react" ; export const { useSession, signIn, signOut, signUp } = createAuthClient (); src/routes/api/auth/$.ts — API catch-all for better-auth: 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), }); CRITICAL : Auth MUST use an API route ( createAPIFileRoute ), NOT a server function ( createServerFn ). better-auth needs direct request/response access. Step 5: Server Functions Core pattern — always create DB client inside the handler: 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 (); }); Input validation with 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 }; }); Protected server functions — check auth, throw redirect if unauthenticated: 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 (
このスキルを起動するキーワード。クリックでコピーできます。
このスキルにはトリガーワードがありません。
ダウンロードした .skill に含まれるフィールド。
| フィールド | 説明 |
|---|---|
| format | フォーマット識別子(skill/v1) |
| skill_id | スキル固有 ID |
| name | スキル名 |
| version | バージョン |
| description | 説明 |
| category | カテゴリ(配列) |
| trigger_words | トリガーワード |
| tags | タグ |
| source | ソース |
| source_url | ソース URL(本ページ) |
| exported_at | エクスポート日時(ダウンロード毎) |
| system_prompt | システムプロンプト本文 |
| model_config | モデル設定:provider / model / temperature / max_tokens / top_p |
| examples | サンプル |
| install_guide | 各プラットフォームの導入説明(Coze / Dify / Claude / カスタム) |