Initial commit
This commit is contained in:
295
commands/es-auth-setup.md
Normal file
295
commands/es-auth-setup.md
Normal file
@@ -0,0 +1,295 @@
|
||||
---
|
||||
description: Interactive authentication setup wizard. Configures better-auth, OAuth providers, and generates handlers for Cloudflare Workers.
|
||||
---
|
||||
|
||||
# Authentication Setup Command
|
||||
|
||||
<command_purpose> Guide developers through authentication stack configuration with automated code generation, database migrations, and MCP-driven provider setup. </command_purpose>
|
||||
|
||||
## Introduction
|
||||
|
||||
<role>Senior Security Engineer with expertise in authentication, better-auth, and Cloudflare Workers security</role>
|
||||
|
||||
**This command will**:
|
||||
- Detect framework (Tanstack Start vs standalone Worker)
|
||||
- Configure better-auth for all authentication needs
|
||||
- Query better-auth MCP for OAuth provider requirements
|
||||
- Generate login/register/logout handlers with React Server Functions
|
||||
- Create D1 database schema for users/sessions
|
||||
- Configure session security (HTTPS cookies, CSRF)
|
||||
- Generate environment variables template
|
||||
|
||||
## Prerequisites
|
||||
|
||||
<requirements>
|
||||
- Cloudflare Workers project (Tanstack Start or Hono)
|
||||
- D1 database configured (or will create)
|
||||
- For OAuth: Provider credentials (Google, GitHub, etc.)
|
||||
</requirements>
|
||||
|
||||
## Main Tasks
|
||||
|
||||
### 1. Detect Framework & Auth Requirements
|
||||
|
||||
**Ask User**:
|
||||
```markdown
|
||||
🔐 Authentication Setup Wizard
|
||||
|
||||
1. What framework are you using?
|
||||
a) Tanstack Start
|
||||
b) Standalone Worker (Hono/plain TS)
|
||||
|
||||
2. What authentication methods do you need?
|
||||
a) Email/Password only
|
||||
b) OAuth providers (Google, GitHub, etc.)
|
||||
c) Passkeys
|
||||
d) Magic Links
|
||||
e) Multiple (OAuth + Email/Password)
|
||||
```
|
||||
|
||||
**Decision Logic**:
|
||||
```
|
||||
If Tanstack Start:
|
||||
→ better-auth with React Server Functions
|
||||
|
||||
If Standalone Worker (Hono):
|
||||
→ better-auth with Hono middleware
|
||||
```
|
||||
|
||||
### 2. Install Dependencies
|
||||
|
||||
**For Tanstack Start**:
|
||||
```bash
|
||||
pnpm add better-auth @node-rs/argon2
|
||||
```
|
||||
|
||||
**For Standalone Worker (Hono)**:
|
||||
```bash
|
||||
pnpm add better-auth hono @node-rs/argon2
|
||||
```
|
||||
|
||||
### 3. Generate Configuration Files
|
||||
|
||||
#### Tanstack Start + better-auth
|
||||
|
||||
**Generate**: `app/auth.server.ts`
|
||||
```typescript
|
||||
import { betterAuth } from 'better-auth';
|
||||
|
||||
export const auth = betterAuth({
|
||||
database: {
|
||||
type: 'd1',
|
||||
database: process.env.DB,
|
||||
},
|
||||
|
||||
emailAndPassword: {
|
||||
enabled: true,
|
||||
requireEmailVerification: true,
|
||||
},
|
||||
|
||||
session: {
|
||||
cookieName: 'session',
|
||||
maxAge: 60 * 60 * 24 * 7, // 7 days
|
||||
cookieCache: {
|
||||
enabled: true,
|
||||
maxAge: 5 * 60 * 1000, // 5 minutes
|
||||
},
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
**Generate**: `server/api/auth/login.post.ts`
|
||||
```typescript
|
||||
import { hash, verify } from '@node-rs/argon2';
|
||||
|
||||
export default defineEventHandler(async (event) => {
|
||||
const { email, password } = await readBody(event);
|
||||
|
||||
const user = await event.context.cloudflare.env.DB.prepare(
|
||||
'SELECT id, email, password_hash FROM users WHERE email = ?'
|
||||
).bind(email).first();
|
||||
|
||||
if (!user || !await verify(user.password_hash, password)) {
|
||||
throw createError({ statusCode: 401, message: 'Invalid credentials' });
|
||||
}
|
||||
|
||||
await setUserSession(event, {
|
||||
user: { id: user.id, email: user.email },
|
||||
loggedInAt: new Date().toISOString(),
|
||||
});
|
||||
|
||||
return { success: true };
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
**Query MCP for OAuth Setup**:
|
||||
```typescript
|
||||
const googleSetup = await mcp.betterAuth.getProviderSetup('google');
|
||||
const githubSetup = await mcp.betterAuth.getProviderSetup('github');
|
||||
```
|
||||
|
||||
**Generate**: `server/utils/auth.ts`
|
||||
```typescript
|
||||
import { betterAuth } from 'better-auth';
|
||||
|
||||
export const auth = betterAuth({
|
||||
database: {
|
||||
type: 'd1',
|
||||
database: process.env.DB,
|
||||
},
|
||||
|
||||
socialProviders: {
|
||||
google: {
|
||||
clientId: process.env.GOOGLE_CLIENT_ID!,
|
||||
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
|
||||
},
|
||||
github: {
|
||||
clientId: process.env.GITHUB_CLIENT_ID!,
|
||||
clientSecret: process.env.GITHUB_CLIENT_SECRET!,
|
||||
},
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
**Generate**: `server/api/auth/[...].ts` (OAuth handler)
|
||||
```typescript
|
||||
export default defineEventHandler(async (event) => {
|
||||
const response = await auth.handler(event.node.req, event.node.res);
|
||||
|
||||
//
|
||||
if (event.node.req.url?.includes('/callback')) {
|
||||
const session = await auth.api.getSession({ headers: event.node.req.headers });
|
||||
if (session) {
|
||||
await setUserSession(event, {
|
||||
user: {
|
||||
id: session.user.id,
|
||||
email: session.user.email,
|
||||
name: session.user.name,
|
||||
provider: session.user.provider,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return response;
|
||||
});
|
||||
```
|
||||
|
||||
### 4. Generate Database Migration
|
||||
|
||||
**Generate**: `migrations/0001_auth.sql`
|
||||
```sql
|
||||
-- Users table
|
||||
CREATE TABLE users (
|
||||
id TEXT PRIMARY KEY,
|
||||
email TEXT UNIQUE NOT NULL,
|
||||
email_verified INTEGER DEFAULT 0,
|
||||
password_hash TEXT, -- NULL for OAuth-only
|
||||
name TEXT,
|
||||
image TEXT,
|
||||
created_at TEXT NOT NULL,
|
||||
updated_at TEXT NOT NULL
|
||||
);
|
||||
|
||||
-- OAuth accounts (if using better-auth)
|
||||
CREATE TABLE accounts (
|
||||
id TEXT PRIMARY KEY,
|
||||
user_id TEXT NOT NULL,
|
||||
provider TEXT NOT NULL,
|
||||
provider_account_id TEXT NOT NULL,
|
||||
access_token TEXT,
|
||||
refresh_token TEXT,
|
||||
expires_at INTEGER,
|
||||
created_at TEXT NOT NULL,
|
||||
|
||||
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
|
||||
UNIQUE(provider, provider_account_id)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_users_email ON users(email);
|
||||
CREATE INDEX idx_accounts_user ON accounts(user_id);
|
||||
```
|
||||
|
||||
### 5. Configure Environment Variables
|
||||
|
||||
**Generate**: `.dev.vars`
|
||||
```bash
|
||||
# better-auth secret (generate with: openssl rand -base64 32)
|
||||
BETTER_AUTH_SECRET=your-32-char-secret-here
|
||||
|
||||
# OAuth credentials (if using OAuth providers)
|
||||
GOOGLE_CLIENT_ID=your-google-client-id
|
||||
GOOGLE_CLIENT_SECRET=your-google-client-secret
|
||||
GITHUB_CLIENT_ID=your-github-client-id
|
||||
GITHUB_CLIENT_SECRET=your-github-client-secret
|
||||
```
|
||||
|
||||
**Production Setup**:
|
||||
```bash
|
||||
wrangler secret put BETTER_AUTH_SECRET
|
||||
wrangler secret put GOOGLE_CLIENT_SECRET
|
||||
wrangler secret put GITHUB_CLIENT_SECRET
|
||||
```
|
||||
|
||||
### 6. Generate Protected Route Example
|
||||
|
||||
**Generate**: `server/api/protected.get.ts`
|
||||
```typescript
|
||||
export default defineEventHandler(async (event) => {
|
||||
const session = await requireUserSession(event);
|
||||
|
||||
return {
|
||||
message: 'Protected data',
|
||||
user: session.user,
|
||||
};
|
||||
});
|
||||
```
|
||||
|
||||
### 7. Validate Setup
|
||||
|
||||
**Security Checklist**:
|
||||
- ✅ HTTPS-only cookies configured
|
||||
- ✅ httpOnly flag set
|
||||
- ✅ SameSite configured (lax or strict)
|
||||
- ✅ Password hashing uses Argon2id
|
||||
- ✅ Session password is 32+ characters
|
||||
- ✅ OAuth redirect URIs configured (if applicable)
|
||||
- ✅ CSRF protection enabled (automatic)
|
||||
|
||||
## Success Criteria
|
||||
|
||||
✅ Auth setup complete when:
|
||||
- Framework detected and appropriate stack chosen
|
||||
- Dependencies installed
|
||||
- Configuration files generated
|
||||
- Database migration created
|
||||
- Environment variables template created
|
||||
- Security settings validated
|
||||
- Example handlers provided
|
||||
|
||||
## Output Summary
|
||||
|
||||
**Files Created**:
|
||||
- Configuration (app.config.ts or auth.ts)
|
||||
- Auth handlers (login, register, logout, OAuth callback)
|
||||
- Database migration (users, accounts)
|
||||
- Protected route example
|
||||
- Environment variables template
|
||||
|
||||
**Next Actions**:
|
||||
1. Run database migration
|
||||
2. Generate session password (32+ chars)
|
||||
3. Configure OAuth providers (if applicable)
|
||||
4. Test authentication flow
|
||||
5. Add rate limiting to auth endpoints
|
||||
6. Deploy with `/es-deploy`
|
||||
|
||||
## Notes
|
||||
|
||||
- Always use better-auth for authentication (Workers-optimized)
|
||||
- Add OAuth/passkeys/magic links as needed
|
||||
- Query better-auth MCP for latest provider requirements
|
||||
- Use Argon2id for password hashing (never bcrypt)
|
||||
- Store secrets in Cloudflare Workers secrets (not wrangler.toml)
|
||||
- See `agents/integrations/better-auth-specialist` for detailed guidance
|
||||
542
commands/es-billing-setup.md
Normal file
542
commands/es-billing-setup.md
Normal file
@@ -0,0 +1,542 @@
|
||||
---
|
||||
description: Interactive Polar.sh billing integration wizard. Sets up products, webhooks, database schema, and subscription middleware for Cloudflare Workers.
|
||||
---
|
||||
|
||||
# Billing Setup Command
|
||||
|
||||
<command_purpose> Guide developers through complete Polar.sh billing integration with automated code generation, database migrations, and MCP-driven product configuration. </command_purpose>
|
||||
|
||||
## Introduction
|
||||
|
||||
<role>Senior Payments Integration Engineer with expertise in Polar.sh, Cloudflare Workers, and subscription management</role>
|
||||
|
||||
**This command will**:
|
||||
- Query Polar MCP for existing products/subscriptions
|
||||
- Generate webhook handler with signature verification
|
||||
- Create D1 database schema for customers/subscriptions
|
||||
- Generate subscription middleware for protected routes
|
||||
- Configure environment variables
|
||||
- Validate setup via Polar MCP
|
||||
|
||||
## Prerequisites
|
||||
|
||||
<requirements>
|
||||
- Cloudflare Workers project (Tanstack Start or Hono)
|
||||
- Polar.sh account: https://polar.sh
|
||||
- D1 database configured in wrangler.toml (or will create)
|
||||
- Polar Access Token (will guide through obtaining)
|
||||
</requirements>
|
||||
|
||||
## Main Tasks
|
||||
|
||||
### 1. Check Polar Account Setup
|
||||
|
||||
<thinking>
|
||||
First, verify user has Polar account and products created.
|
||||
Use Polar MCP to check for existing products.
|
||||
</thinking>
|
||||
|
||||
#### Immediate Actions:
|
||||
|
||||
<task_list>
|
||||
|
||||
- [ ] Check if Polar MCP is available
|
||||
- [ ] Prompt user for Polar Access Token (if not in env)
|
||||
- [ ] Query Polar MCP for existing products
|
||||
- [ ] If no products found, guide to Polar dashboard
|
||||
- [ ] Display available products and let user select which to integrate
|
||||
|
||||
</task_list>
|
||||
|
||||
**Check Polar Products**:
|
||||
```typescript
|
||||
// Query MCP for products
|
||||
const products = await mcp.polar.listProducts();
|
||||
|
||||
if (products.length === 0) {
|
||||
console.log("⚠️ No products found in your Polar account");
|
||||
console.log("📋 Next steps:");
|
||||
console.log("1. Go to https://polar.sh/dashboard");
|
||||
console.log("2. Create your products (Pro, Enterprise, etc.)");
|
||||
console.log("3. Run this command again");
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// Display products
|
||||
console.log("✅ Found Polar products:");
|
||||
products.forEach((p, i) => {
|
||||
console.log(`${i + 1}. ${p.name} - $${p.prices[0].amount / 100}/${p.prices[0].interval}`);
|
||||
console.log(` ID: ${p.id}`);
|
||||
});
|
||||
```
|
||||
|
||||
### 2. Generate Webhook Handler
|
||||
|
||||
<thinking>
|
||||
Create comprehensive webhook handler with signature verification
|
||||
and all critical event handlers.
|
||||
</thinking>
|
||||
|
||||
**Generate File**: `app/routes/api/webhooks/polar.ts` (Tanstack Start) or `src/webhooks/polar.ts` (Hono)
|
||||
|
||||
```typescript
|
||||
// Generated webhook handler
|
||||
import { Polar } from '@polar-sh/sdk';
|
||||
|
||||
export interface Env {
|
||||
POLAR_ACCESS_TOKEN: string;
|
||||
POLAR_WEBHOOK_SECRET: string;
|
||||
DB: D1Database;
|
||||
}
|
||||
|
||||
export async function handlePolarWebhook(
|
||||
request: Request,
|
||||
env: Env
|
||||
): Promise<Response> {
|
||||
// 1. Verify webhook signature
|
||||
const signature = request.headers.get('polar-signature');
|
||||
if (!signature) {
|
||||
return new Response('Missing signature', { status: 401 });
|
||||
}
|
||||
|
||||
const body = await request.text();
|
||||
const polar = new Polar({ accessToken: env.POLAR_ACCESS_TOKEN });
|
||||
|
||||
let event;
|
||||
try {
|
||||
event = polar.webhooks.verify(body, signature, env.POLAR_WEBHOOK_SECRET);
|
||||
} catch (err) {
|
||||
console.error('Webhook verification failed:', err);
|
||||
return new Response('Invalid signature', { status: 401 });
|
||||
}
|
||||
|
||||
// 2. Log event for debugging
|
||||
await env.DB.prepare(
|
||||
\`INSERT INTO webhook_events (id, type, data, created_at)
|
||||
VALUES (?, ?, ?, ?)\`
|
||||
).bind(
|
||||
crypto.randomUUID(),
|
||||
event.type,
|
||||
JSON.stringify(event.data),
|
||||
new Date().toISOString()
|
||||
).run();
|
||||
|
||||
// 3. Handle event types
|
||||
try {
|
||||
switch (event.type) {
|
||||
case 'checkout.completed':
|
||||
await handleCheckoutCompleted(event.data, env);
|
||||
break;
|
||||
|
||||
case 'subscription.created':
|
||||
await handleSubscriptionCreated(event.data, env);
|
||||
break;
|
||||
|
||||
case 'subscription.updated':
|
||||
await handleSubscriptionUpdated(event.data, env);
|
||||
break;
|
||||
|
||||
case 'subscription.canceled':
|
||||
await handleSubscriptionCanceled(event.data, env);
|
||||
break;
|
||||
|
||||
case 'subscription.past_due':
|
||||
await handleSubscriptionPastDue(event.data, env);
|
||||
break;
|
||||
|
||||
default:
|
||||
console.log('Unhandled event type:', event.type);
|
||||
}
|
||||
|
||||
return new Response('OK', { status: 200 });
|
||||
} catch (err) {
|
||||
console.error('Webhook processing error:', err);
|
||||
return new Response('Processing failed', { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
// Event handlers
|
||||
async function handleCheckoutCompleted(data: any, env: Env) {
|
||||
const { customer_id, product_id, metadata } = data;
|
||||
|
||||
await env.DB.prepare(
|
||||
\`UPDATE users
|
||||
SET polar_customer_id = ?,
|
||||
product_id = ?,
|
||||
subscription_status = 'active',
|
||||
updated_at = ?
|
||||
WHERE id = ?\`
|
||||
).bind(customer_id, product_id, new Date().toISOString(), metadata.user_id).run();
|
||||
}
|
||||
|
||||
async function handleSubscriptionCreated(data: any, env: Env) {
|
||||
const { id, customer_id, product_id, status, current_period_end } = data;
|
||||
|
||||
await env.DB.prepare(
|
||||
\`INSERT INTO subscriptions (id, polar_customer_id, product_id, status, current_period_end, created_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?)\`
|
||||
).bind(id, customer_id, product_id, status, current_period_end, new Date().toISOString()).run();
|
||||
}
|
||||
|
||||
async function handleSubscriptionUpdated(data: any, env: Env) {
|
||||
const { id, status, product_id, current_period_end } = data;
|
||||
|
||||
await env.DB.prepare(
|
||||
\`UPDATE subscriptions
|
||||
SET status = ?, product_id = ?, current_period_end = ?, updated_at = ?
|
||||
WHERE id = ?\`
|
||||
).bind(status, product_id, current_period_end, new Date().toISOString(), id).run();
|
||||
}
|
||||
|
||||
async function handleSubscriptionCanceled(data: any, env: Env) {
|
||||
const { id } = data;
|
||||
|
||||
await env.DB.prepare(
|
||||
\`UPDATE subscriptions
|
||||
SET status = 'canceled', canceled_at = ?, updated_at = ?
|
||||
WHERE id = ?\`
|
||||
).bind(new Date().toISOString(), new Date().toISOString(), id).run();
|
||||
}
|
||||
|
||||
async function handleSubscriptionPastDue(data: any, env: Env) {
|
||||
const { id } = data;
|
||||
|
||||
await env.DB.prepare(
|
||||
\`UPDATE subscriptions
|
||||
SET status = 'past_due', updated_at = ?
|
||||
WHERE id = ?\`
|
||||
).bind(new Date().toISOString(), id).run();
|
||||
|
||||
// TODO: Send payment failure notification
|
||||
console.log('Subscription past due:', id);
|
||||
}
|
||||
|
||||
// App-specific export
|
||||
export default defineEventHandler(async (event) => {
|
||||
return await handlePolarWebhook(
|
||||
event.node.req,
|
||||
event.context.cloudflare.env
|
||||
);
|
||||
});
|
||||
```
|
||||
|
||||
### 3. Generate Database Migration
|
||||
|
||||
<thinking>
|
||||
Create D1 schema for users, subscriptions, and webhook event logging.
|
||||
</thinking>
|
||||
|
||||
**Generate File**: `migrations/0001_polar_billing.sql`
|
||||
|
||||
```sql
|
||||
-- Users table (add Polar fields)
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id TEXT PRIMARY KEY,
|
||||
email TEXT UNIQUE NOT NULL,
|
||||
polar_customer_id TEXT UNIQUE,
|
||||
product_id TEXT,
|
||||
subscription_status TEXT, -- 'active', 'canceled', 'past_due', NULL
|
||||
current_period_end TEXT,
|
||||
created_at TEXT NOT NULL,
|
||||
updated_at TEXT NOT NULL
|
||||
);
|
||||
|
||||
-- Subscriptions table (detailed tracking)
|
||||
CREATE TABLE subscriptions (
|
||||
id TEXT PRIMARY KEY, -- Polar subscription ID
|
||||
polar_customer_id TEXT NOT NULL,
|
||||
product_id TEXT NOT NULL,
|
||||
price_id TEXT NOT NULL,
|
||||
status TEXT NOT NULL, -- 'active', 'canceled', 'past_due', 'trialing'
|
||||
current_period_start TEXT,
|
||||
current_period_end TEXT,
|
||||
canceled_at TEXT,
|
||||
created_at TEXT NOT NULL,
|
||||
updated_at TEXT NOT NULL,
|
||||
|
||||
FOREIGN KEY (polar_customer_id) REFERENCES users(polar_customer_id)
|
||||
);
|
||||
|
||||
-- Webhook events log (debugging/auditing)
|
||||
CREATE TABLE webhook_events (
|
||||
id TEXT PRIMARY KEY,
|
||||
type TEXT NOT NULL,
|
||||
data TEXT NOT NULL, -- JSON blob
|
||||
created_at TEXT NOT NULL
|
||||
);
|
||||
|
||||
-- Indexes for performance
|
||||
CREATE INDEX idx_users_polar_customer ON users(polar_customer_id);
|
||||
CREATE INDEX idx_users_subscription_status ON users(subscription_status);
|
||||
CREATE INDEX idx_subscriptions_customer ON subscriptions(polar_customer_id);
|
||||
CREATE INDEX idx_subscriptions_status ON subscriptions(status);
|
||||
CREATE INDEX idx_webhook_events_type ON webhook_events(type);
|
||||
CREATE INDEX idx_webhook_events_created ON webhook_events(created_at);
|
||||
```
|
||||
|
||||
**Run Migration**:
|
||||
```bash
|
||||
wrangler d1 migrations apply DB --local
|
||||
wrangler d1 migrations apply DB --remote
|
||||
```
|
||||
|
||||
### 4. Generate Subscription Middleware
|
||||
|
||||
<thinking>
|
||||
Create middleware to check subscription status on protected routes.
|
||||
</thinking>
|
||||
|
||||
**Generate File**: `app/middleware/subscription.ts` (Tanstack Start) or `src/middleware/subscription.ts` (Hono)
|
||||
|
||||
```typescript
|
||||
// Subscription check middleware
|
||||
export async function requireActiveSubscription(
|
||||
request: Request,
|
||||
env: Env,
|
||||
ctx?: ExecutionContext
|
||||
) {
|
||||
// Get user ID from session (assumes auth is already set up)
|
||||
const userId = await getUserIdFromSession(request, env);
|
||||
|
||||
if (!userId) {
|
||||
return new Response('Unauthorized', { status: 401 });
|
||||
}
|
||||
|
||||
// Check subscription status
|
||||
const user = await env.DB.prepare(
|
||||
\`SELECT subscription_status, current_period_end, product_id
|
||||
FROM users
|
||||
WHERE id = ?\`
|
||||
).bind(userId).first();
|
||||
|
||||
if (!user) {
|
||||
return new Response('User not found', { status: 404 });
|
||||
}
|
||||
|
||||
// Check if subscription is active
|
||||
if (user.subscription_status !== 'active') {
|
||||
return new Response(JSON.stringify({
|
||||
error: 'subscription_required',
|
||||
message: 'Active subscription required to access this feature',
|
||||
upgrade_url: '/pricing'
|
||||
}), {
|
||||
status: 403,
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
}
|
||||
|
||||
// Check if subscription hasn't expired
|
||||
if (user.current_period_end) {
|
||||
const periodEnd = new Date(user.current_period_end);
|
||||
if (periodEnd < new Date()) {
|
||||
return new Response(JSON.stringify({
|
||||
error: 'subscription_expired',
|
||||
message: 'Your subscription has expired',
|
||||
renew_url: '/pricing'
|
||||
}), {
|
||||
status: 403,
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Subscription is valid, continue
|
||||
return null;
|
||||
}
|
||||
|
||||
// Helper to get user ID from session
|
||||
async function getUserIdFromSession(request: Request, env: Env): Promise<string | null> {
|
||||
// TODO: Implement based on your auth setup
|
||||
// const session = await getUserSession(event);
|
||||
// return session?.user?.id || null;
|
||||
|
||||
// For better-auth:
|
||||
// const session = await auth.api.getSession({ headers: request.headers });
|
||||
// return session?.user?.id || null;
|
||||
|
||||
return null; // Placeholder
|
||||
}
|
||||
```
|
||||
|
||||
**Usage Example**:
|
||||
```typescript
|
||||
// Protected API route
|
||||
export default defineEventHandler(async (event) => {
|
||||
// Check subscription
|
||||
const subscriptionCheck = await requireActiveSubscription(
|
||||
event.node.req,
|
||||
event.context.cloudflare.env
|
||||
);
|
||||
|
||||
if (subscriptionCheck) {
|
||||
return subscriptionCheck; // Return 403 if no subscription
|
||||
}
|
||||
|
||||
// User has active subscription, proceed
|
||||
return {
|
||||
message: 'Premium feature accessed',
|
||||
data: '...'
|
||||
};
|
||||
});
|
||||
```
|
||||
|
||||
### 5. Configure Environment Variables
|
||||
|
||||
<thinking>
|
||||
Update wrangler.toml and create .dev.vars template.
|
||||
</thinking>
|
||||
|
||||
**Update**: `wrangler.toml`
|
||||
|
||||
```toml
|
||||
# Add Polar webhook secret (public, not sensitive)
|
||||
[vars]
|
||||
POLAR_WEBHOOK_SECRET = "whsec_..." # Get from Polar dashboard
|
||||
|
||||
# D1 database (if not already configured)
|
||||
[[d1_databases]]
|
||||
binding = "DB"
|
||||
database_name = "my-app-db"
|
||||
database_id = "..." # Get from: wrangler d1 create my-app-db
|
||||
```
|
||||
|
||||
**Create**: `.dev.vars` (local development)
|
||||
|
||||
```bash
|
||||
# Polar Access Token (sensitive - DO NOT COMMIT)
|
||||
POLAR_ACCESS_TOKEN=polar_at_xxxxxxxxxxxxx
|
||||
|
||||
# Get this from: https://polar.sh/dashboard/settings/api
|
||||
```
|
||||
|
||||
**Production Setup**:
|
||||
```bash
|
||||
# Set secret in Cloudflare Workers
|
||||
wrangler secret put POLAR_ACCESS_TOKEN
|
||||
# Paste: polar_at_xxxxxxxxxxxxx
|
||||
```
|
||||
|
||||
### 6. Configure Polar Webhook Endpoint
|
||||
|
||||
<thinking>
|
||||
User needs to configure webhook endpoint in Polar dashboard.
|
||||
</thinking>
|
||||
|
||||
**Instructions for User**:
|
||||
|
||||
```markdown
|
||||
## Configure Polar Webhook
|
||||
|
||||
1. Go to https://polar.sh/dashboard/settings/webhooks
|
||||
2. Click "Add Webhook Endpoint"
|
||||
3. Enter your webhook URL:
|
||||
- Development: http://localhost:3000/api/webhooks/polar
|
||||
- Production: https://yourdomain.com/api/webhooks/polar
|
||||
4. Select events to send:
|
||||
✅ checkout.completed
|
||||
✅ subscription.created
|
||||
✅ subscription.updated
|
||||
✅ subscription.canceled
|
||||
✅ subscription.past_due
|
||||
5. Copy the "Webhook Secret" (whsec_...)
|
||||
6. Add to wrangler.toml: POLAR_WEBHOOK_SECRET = "whsec_..."
|
||||
7. Click "Create Endpoint"
|
||||
8. Test with "Send Test Event" button
|
||||
```
|
||||
|
||||
### 7. Validate Setup
|
||||
|
||||
<thinking>
|
||||
Use Polar MCP to verify configuration is correct.
|
||||
</thinking>
|
||||
|
||||
**Validation Checklist**:
|
||||
|
||||
```typescript
|
||||
// Run validation checks
|
||||
const validation = {
|
||||
polarAccount: await mcp.polar.verifySetup(),
|
||||
products: await mcp.polar.listProducts(),
|
||||
webhookEvents: await mcp.polar.getWebhookEvents(),
|
||||
database: await checkDatabaseSchema(env),
|
||||
environment: await checkEnvironmentVars(env),
|
||||
webhookEndpoint: await checkWebhookHandler()
|
||||
};
|
||||
|
||||
console.log("🔍 Polar.sh Integration Validation\n");
|
||||
|
||||
// 1. Polar Account
|
||||
console.log("✅ Polar Account:", validation.polarAccount.status);
|
||||
console.log(` Found ${validation.products.length} products`);
|
||||
|
||||
// 2. Database Schema
|
||||
if (validation.database.users && validation.database.subscriptions) {
|
||||
console.log("✅ Database Schema: Complete");
|
||||
} else {
|
||||
console.log("❌ Database Schema: Missing tables");
|
||||
console.log(" Run: wrangler d1 migrations apply DB");
|
||||
}
|
||||
|
||||
// 3. Environment Variables
|
||||
if (validation.environment.POLAR_ACCESS_TOKEN && validation.environment.POLAR_WEBHOOK_SECRET) {
|
||||
console.log("✅ Environment Variables: Configured");
|
||||
} else {
|
||||
console.log("❌ Environment Variables: Missing");
|
||||
if (!validation.environment.POLAR_ACCESS_TOKEN) {
|
||||
console.log(" Missing: POLAR_ACCESS_TOKEN");
|
||||
}
|
||||
if (!validation.environment.POLAR_WEBHOOK_SECRET) {
|
||||
console.log(" Missing: POLAR_WEBHOOK_SECRET");
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Webhook Handler
|
||||
if (validation.webhookEndpoint.exists) {
|
||||
console.log("✅ Webhook Handler: Exists");
|
||||
} else {
|
||||
console.log("❌ Webhook Handler: Not found");
|
||||
}
|
||||
|
||||
console.log("\n📋 Next Steps:");
|
||||
console.log("1. Configure webhook in Polar dashboard");
|
||||
console.log("2. Test webhook with Polar's 'Send Test Event'");
|
||||
console.log("3. Implement subscription checks on protected routes");
|
||||
console.log("4. Deploy to production with: /es-deploy");
|
||||
```
|
||||
|
||||
## Success Criteria
|
||||
|
||||
✅ Billing setup complete when:
|
||||
- Polar products queried successfully via MCP
|
||||
- Webhook handler generated with signature verification
|
||||
- Database schema created (users, subscriptions, webhook_events)
|
||||
- Subscription middleware generated
|
||||
- Environment variables configured
|
||||
- Validation passes all checks
|
||||
- User guided through Polar dashboard configuration
|
||||
|
||||
## Output Summary
|
||||
|
||||
**Files Created**:
|
||||
- `server/api/webhooks/polar.ts` (or `src/webhooks/polar.ts`)
|
||||
- `server/middleware/subscription.ts` (or `src/middleware/subscription.ts`)
|
||||
- `migrations/0001_polar_billing.sql`
|
||||
- `.dev.vars` (template)
|
||||
|
||||
**Files Updated**:
|
||||
- `wrangler.toml` (added Polar vars and D1 binding)
|
||||
|
||||
**Next Actions**:
|
||||
1. Run database migration
|
||||
2. Configure webhook in Polar dashboard
|
||||
3. Test webhook with Polar simulator
|
||||
4. Add subscription checks to protected routes
|
||||
5. Deploy with `/es-deploy`
|
||||
|
||||
## Notes
|
||||
|
||||
- Always use Polar MCP for real-time product data
|
||||
- Test webhooks locally with Polar's test event feature
|
||||
- Store POLAR_ACCESS_TOKEN as Cloudflare secret (not in wrangler.toml)
|
||||
- Webhook endpoint must be publicly accessible (use ngrok for local testing)
|
||||
- See `agents/integrations/polar-billing-specialist` for detailed implementation guidance
|
||||
365
commands/es-commit.md
Normal file
365
commands/es-commit.md
Normal file
@@ -0,0 +1,365 @@
|
||||
---
|
||||
description: Commit all changes with AI-generated message and push to current branch
|
||||
---
|
||||
|
||||
# Commit and Push Changes
|
||||
|
||||
<command_purpose> Automatically stage all changes, generate a comprehensive commit message based on the diff, commit with proper formatting, and push to the current branch. </command_purpose>
|
||||
|
||||
## Introduction
|
||||
|
||||
<role>Git Workflow Automation Specialist</role>
|
||||
|
||||
This command analyzes your changes, generates a meaningful commit message following conventional commit standards, and pushes to your current working branch.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
<requirements>
|
||||
- Git repository initialized
|
||||
- Changes to commit (tracked or untracked files)
|
||||
- Remote repository configured
|
||||
- Authentication set up for push operations
|
||||
</requirements>
|
||||
|
||||
## Commit Message Override
|
||||
|
||||
<commit_message_override> #$ARGUMENTS </commit_message_override>
|
||||
|
||||
**Usage**:
|
||||
- `/es-commit` - Auto-generate commit message from changes
|
||||
- `/es-commit "Custom message"` - Use provided message
|
||||
|
||||
## Main Tasks
|
||||
|
||||
### 1. Pre-Commit Validation
|
||||
|
||||
<thinking>
|
||||
Before committing, verify the repository state and ensure we're ready to commit.
|
||||
</thinking>
|
||||
|
||||
**Check repository status**:
|
||||
|
||||
```bash
|
||||
# Verify we're in a git repository
|
||||
if ! git rev-parse --git-dir > /dev/null 2>&1; then
|
||||
echo "❌ Error: Not a git repository"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get current branch
|
||||
CURRENT_BRANCH=$(git branch --show-current)
|
||||
echo "📍 Current branch: $CURRENT_BRANCH"
|
||||
|
||||
# Check if there are changes to commit
|
||||
if git diff --quiet && git diff --cached --quiet && [ -z "$(git ls-files --others --exclude-standard)" ]; then
|
||||
echo "✅ No changes to commit"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Show status
|
||||
git status --short
|
||||
```
|
||||
|
||||
### 2. Analyze Changes
|
||||
|
||||
<thinking>
|
||||
Analyze what changed to generate an appropriate commit message.
|
||||
</thinking>
|
||||
|
||||
**Gather change information**:
|
||||
|
||||
```bash
|
||||
# Count changes
|
||||
ADDED=$(git ls-files --others --exclude-standard | wc -l)
|
||||
MODIFIED=$(git diff --name-only | wc -l)
|
||||
STAGED=$(git diff --cached --name-only | wc -l)
|
||||
DELETED=$(git ls-files --deleted | wc -l)
|
||||
|
||||
echo ""
|
||||
echo "📊 Change Summary:"
|
||||
echo " Added: $ADDED files"
|
||||
echo " Modified: $MODIFIED files"
|
||||
echo " Staged: $STAGED files"
|
||||
echo " Deleted: $DELETED files"
|
||||
|
||||
# Get detailed diff for commit message generation
|
||||
git diff --cached --stat
|
||||
git diff --stat
|
||||
```
|
||||
|
||||
### 3. Generate Commit Message
|
||||
|
||||
<thinking>
|
||||
If user didn't provide a message, generate one based on the changes.
|
||||
Use conventional commit format with proper categorization.
|
||||
</thinking>
|
||||
|
||||
**If no custom message provided**:
|
||||
|
||||
Analyze the diff and generate a commit message following this format:
|
||||
|
||||
```
|
||||
<type>: <short description>
|
||||
|
||||
<detailed description>
|
||||
|
||||
<body with specifics>
|
||||
|
||||
🤖 Generated with [Claude Code](https://claude.com/claude-code)
|
||||
|
||||
Co-Authored-By: Claude <noreply@anthropic.com>
|
||||
```
|
||||
|
||||
**Commit type selection**:
|
||||
- `feat:` - New features or capabilities
|
||||
- `fix:` - Bug fixes
|
||||
- `refactor:` - Code restructuring without behavior change
|
||||
- `docs:` - Documentation only
|
||||
- `style:` - Formatting, whitespace, etc.
|
||||
- `perf:` - Performance improvements
|
||||
- `test:` - Adding or updating tests
|
||||
- `chore:` - Maintenance tasks, dependencies
|
||||
- `ci:` - CI/CD changes
|
||||
|
||||
**Message generation guidelines**:
|
||||
|
||||
1. **Analyze file changes**:
|
||||
```bash
|
||||
# Check which directories/files changed
|
||||
git diff --name-only HEAD
|
||||
git diff --cached --name-only
|
||||
git ls-files --others --exclude-standard
|
||||
```
|
||||
|
||||
2. **Categorize the changes**:
|
||||
- New files → likely `feat:`
|
||||
- Modified existing files → check diff content
|
||||
- Deleted files → `refactor:` or `chore:`
|
||||
- Documentation files → `docs:`
|
||||
- Config files → `chore:` or `ci:`
|
||||
|
||||
3. **Generate specific description**:
|
||||
- List key files changed
|
||||
- Explain WHY the change was made (not just WHAT)
|
||||
- Include impact/benefits
|
||||
- Reference related commands, agents, or SKILLs if relevant
|
||||
|
||||
4. **Example generated message**:
|
||||
```
|
||||
feat: Add automated commit workflow command
|
||||
|
||||
Created /es-commit command to streamline git workflow by automatically
|
||||
staging changes, generating contextual commit messages, and pushing to
|
||||
the current working branch.
|
||||
|
||||
Key features:
|
||||
- Auto-detects current branch (PR branches, feature branches, main)
|
||||
- Generates conventional commit messages from diff analysis
|
||||
- Supports custom commit messages via arguments
|
||||
- Validates repository state before committing
|
||||
- Automatically pushes to remote after successful commit
|
||||
|
||||
Files added:
|
||||
- commands/es-commit.md (workflow automation command)
|
||||
|
||||
🤖 Generated with [Claude Code](https://claude.com/claude-code)
|
||||
|
||||
Co-Authored-By: Claude <noreply@anthropic.com>
|
||||
```
|
||||
|
||||
### 4. Stage All Changes
|
||||
|
||||
<thinking>
|
||||
Stage all changes including untracked files.
|
||||
</thinking>
|
||||
|
||||
```bash
|
||||
# Stage everything
|
||||
git add -A
|
||||
|
||||
echo "✅ Staged all changes"
|
||||
```
|
||||
|
||||
### 5. Create Commit
|
||||
|
||||
<thinking>
|
||||
Commit with the generated or provided message.
|
||||
Use heredoc for proper formatting.
|
||||
</thinking>
|
||||
|
||||
**If custom message provided**:
|
||||
|
||||
```bash
|
||||
git commit -m "$(cat <<'EOF'
|
||||
$CUSTOM_MESSAGE
|
||||
|
||||
🤖 Generated with [Claude Code](https://claude.com/claude-code)
|
||||
|
||||
Co-Authored-By: Claude <noreply@anthropic.com>
|
||||
EOF
|
||||
)"
|
||||
```
|
||||
|
||||
**If auto-generated message**:
|
||||
|
||||
```bash
|
||||
git commit -m "$(cat <<'EOF'
|
||||
$GENERATED_MESSAGE
|
||||
EOF
|
||||
)"
|
||||
```
|
||||
|
||||
**Verify commit succeeded**:
|
||||
|
||||
```bash
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "✅ Commit created successfully"
|
||||
git log -1 --oneline
|
||||
else
|
||||
echo "❌ Commit failed"
|
||||
exit 1
|
||||
fi
|
||||
```
|
||||
|
||||
### 6. Push to Current Branch
|
||||
|
||||
<thinking>
|
||||
Push to the current branch (whether it's main, a feature branch, or a PR branch).
|
||||
Use -u flag to set upstream if not already set.
|
||||
</thinking>
|
||||
|
||||
```bash
|
||||
# Get current branch again
|
||||
CURRENT_BRANCH=$(git branch --show-current)
|
||||
|
||||
# Check if branch has upstream
|
||||
if git rev-parse --abbrev-ref @{upstream} > /dev/null 2>&1; then
|
||||
# Upstream exists, just push
|
||||
echo "📤 Pushing to origin/$CURRENT_BRANCH..."
|
||||
git push origin "$CURRENT_BRANCH"
|
||||
else
|
||||
# No upstream, set it with -u
|
||||
echo "📤 Pushing to origin/$CURRENT_BRANCH (setting upstream)..."
|
||||
git push -u origin "$CURRENT_BRANCH"
|
||||
fi
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "✅ Pushed successfully to origin/$CURRENT_BRANCH"
|
||||
else
|
||||
echo "❌ Push failed"
|
||||
exit 1
|
||||
fi
|
||||
```
|
||||
|
||||
### 7. Summary Report
|
||||
|
||||
<deliverable>
|
||||
Final report showing what was committed and pushed
|
||||
</deliverable>
|
||||
|
||||
```markdown
|
||||
## ✅ Commit Complete
|
||||
|
||||
**Branch**: $CURRENT_BRANCH
|
||||
**Commit**: $(git log -1 --oneline)
|
||||
**Remote**: origin/$CURRENT_BRANCH
|
||||
|
||||
### Changes Committed:
|
||||
- Added: $ADDED files
|
||||
- Modified: $MODIFIED files
|
||||
- Deleted: $DELETED files
|
||||
|
||||
### Commit Message:
|
||||
```
|
||||
$COMMIT_MESSAGE
|
||||
```
|
||||
|
||||
### Next Steps:
|
||||
- View commit: `git log -1 -p`
|
||||
- View on GitHub: `gh browse`
|
||||
- Create PR: `gh pr create` (if on feature branch)
|
||||
```
|
||||
|
||||
## Usage Examples
|
||||
|
||||
### Auto-generate commit message
|
||||
```bash
|
||||
/es-commit
|
||||
```
|
||||
|
||||
### Custom commit message
|
||||
```bash
|
||||
/es-commit "fix: Resolve authentication timeout issue"
|
||||
```
|
||||
|
||||
### With detailed custom message
|
||||
```bash
|
||||
/es-commit "feat: Add Polar.sh billing integration
|
||||
|
||||
Complete implementation of Polar.sh billing with webhooks,
|
||||
subscription middleware, and D1 database schema."
|
||||
```
|
||||
|
||||
## Safety Features
|
||||
|
||||
**Pre-commit checks**:
|
||||
- ✅ Verifies git repository exists
|
||||
- ✅ Shows status before committing
|
||||
- ✅ Validates changes exist
|
||||
- ✅ Confirms commit succeeded before pushing
|
||||
|
||||
**Branch awareness**:
|
||||
- ✅ Always pushes to current branch (respects PR branches)
|
||||
- ✅ Sets upstream automatically if needed
|
||||
- ✅ Shows clear feedback on branch and remote
|
||||
|
||||
**Message quality**:
|
||||
- ✅ Follows conventional commit standards
|
||||
- ✅ Includes Claude Code attribution
|
||||
- ✅ Provides detailed context from diff analysis
|
||||
|
||||
## Integration with Other Commands
|
||||
|
||||
**Typical workflow**:
|
||||
1. `/es-work` - Work on feature
|
||||
2. `/es-validate` - Validate changes
|
||||
3. `/es-commit` - Commit and push ← THIS COMMAND
|
||||
4. `gh pr create` - Create PR (if on feature branch)
|
||||
|
||||
**Or for quick iterations**:
|
||||
1. Make changes
|
||||
2. `/es-commit` - Auto-commit with generated message
|
||||
3. Continue working
|
||||
|
||||
## Best Practices
|
||||
|
||||
**Do's** ✅:
|
||||
- Run `/es-validate` before committing
|
||||
- Review the generated commit message
|
||||
- Use custom messages for complex changes
|
||||
- Let it auto-detect your current branch
|
||||
- Use on feature branches and main branch
|
||||
|
||||
**Don'ts** ❌:
|
||||
- Don't commit secrets or credentials (command doesn't check)
|
||||
- Don't use for force pushes (not supported)
|
||||
- Don't amend commits (creates new commit)
|
||||
- Don't bypass hooks (respects all git hooks)
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**Issue**: "Not a git repository"
|
||||
**Solution**: Run `git init` or navigate to repository root
|
||||
|
||||
**Issue**: "No changes to commit"
|
||||
**Solution**: Make changes first or check if already committed
|
||||
|
||||
**Issue**: "Push failed"
|
||||
**Solution**: Check authentication (`gh auth status`), verify remote exists
|
||||
|
||||
**Issue**: "Commit message too generic"
|
||||
**Solution**: Provide custom message with `/es-commit "your message"`
|
||||
|
||||
---
|
||||
|
||||
**Remember**: This command commits ALL changes (tracked and untracked). Review `git status` if you want to commit selectively.
|
||||
943
commands/es-component.md
Normal file
943
commands/es-component.md
Normal file
@@ -0,0 +1,943 @@
|
||||
---
|
||||
description: Scaffold shadcn/ui components with distinctive design, accessibility, and animation best practices built-in. Prevents generic aesthetics from the start.
|
||||
---
|
||||
|
||||
# Component Generator Command
|
||||
|
||||
<command_purpose> Generate shadcn/ui components with distinctive design patterns, deep customization, accessibility features, and engaging animations built-in. Prevents generic "AI aesthetic" by providing branded templates from the start. </command_purpose>
|
||||
|
||||
## Introduction
|
||||
|
||||
<role>Senior Component Architect with expertise in shadcn/ui, React 19 with hooks, Tailwind CSS, accessibility, and distinctive design patterns</role>
|
||||
|
||||
**Design Philosophy**: Start with distinctive, accessible, engaging components rather than fixing generic patterns later.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
<requirements>
|
||||
- Tanstack Start project with Vue 3
|
||||
- shadcn/ui component library installed
|
||||
- Tailwind 4 CSS configured with custom theme (or will be created)
|
||||
- (Optional) shadcn/ui MCP server for component API validation
|
||||
- (Optional) Existing `composables/useDesignSystem.ts` for consistent patterns
|
||||
</requirements>
|
||||
|
||||
## Command Usage
|
||||
|
||||
```bash
|
||||
/es-component <type> <name> [options]
|
||||
```
|
||||
|
||||
### Arguments:
|
||||
|
||||
- `<type>`: Component type (button, card, form, modal, hero, navigation, etc.)
|
||||
- `<name>`: Component name in PascalCase (e.g., `PrimaryButton`, `FeatureCard`)
|
||||
- `[options]`: Optional flags:
|
||||
- `--theme <dark|light|custom>`: Theme variant
|
||||
- `--animations <minimal|standard|rich>`: Animation complexity
|
||||
- `--accessible`: Include enhanced accessibility features (default: true)
|
||||
- `--output <path>`: Custom output path (default: `components/`)
|
||||
|
||||
### Examples:
|
||||
|
||||
```bash
|
||||
# Generate primary button component
|
||||
/es-component button PrimaryButton
|
||||
|
||||
# Generate feature card with rich animations
|
||||
/es-component card FeatureCard --animations rich
|
||||
|
||||
# Generate hero section with custom theme
|
||||
/es-component hero LandingHero --theme custom
|
||||
|
||||
# Generate modal with custom output path
|
||||
/es-component modal ConfirmDialog --output components/dialogs/
|
||||
```
|
||||
|
||||
## Main Tasks
|
||||
|
||||
### 1. Project Context Analysis
|
||||
|
||||
<thinking>
|
||||
First, I need to understand existing design system, theme configuration, and component patterns.
|
||||
This ensures generated components match existing project aesthetics.
|
||||
</thinking>
|
||||
|
||||
#### Immediate Actions:
|
||||
|
||||
<task_list>
|
||||
|
||||
- [ ] Check for `tailwind.config.ts` and extract custom theme (fonts, colors, animations)
|
||||
- [ ] Check for `composables/useDesignSystem.ts` and extract existing variants
|
||||
- [ ] Check for `app.config.ts` and extract shadcn/ui global customization
|
||||
- [ ] Scan existing components for naming conventions and structure patterns
|
||||
- [ ] Determine if design system is established or needs creation
|
||||
|
||||
</task_list>
|
||||
|
||||
#### Output Summary:
|
||||
|
||||
<summary_format>
|
||||
📦 **Project Context**:
|
||||
- Custom fonts: Found/Not Found (Inter ❌ or Custom ✅)
|
||||
- Brand colors: Found/Not Found (Purple ❌ or Custom ✅)
|
||||
- Design system composable: Exists/Missing
|
||||
- Component count: X components found
|
||||
- Naming convention: Detected pattern
|
||||
</summary_format>
|
||||
|
||||
### 2. Validate Component Type with MCP (if available)
|
||||
|
||||
<thinking>
|
||||
If shadcn/ui MCP is available, validate that the requested component type exists
|
||||
and get accurate props/slots before generating.
|
||||
</thinking>
|
||||
|
||||
#### MCP Validation:
|
||||
|
||||
<mcp_workflow>
|
||||
|
||||
If shadcn/ui MCP available:
|
||||
1. Query `shadcn-ui.list_components()` to get available components
|
||||
2. Map component type to shadcn/ui component:
|
||||
- `button` → `Button`
|
||||
- `card` → `Card`
|
||||
- `modal` → `Dialog`
|
||||
- `form` → `UForm` + `Input`/`UTextarea`/etc.
|
||||
- `hero` → Custom layout with `Button`, `Card`
|
||||
- `navigation` → `UTabs` or custom
|
||||
3. Query `shadcn-ui.get_component("Button")` for accurate props
|
||||
4. Use real props in generated component (prevent hallucination)
|
||||
|
||||
If MCP not available:
|
||||
- Use documented shadcn/ui API
|
||||
- Include comment: "// TODO: Verify props with shadcn/ui docs"
|
||||
|
||||
</mcp_workflow>
|
||||
|
||||
### 3. Generate Component with Design Best Practices
|
||||
|
||||
<thinking>
|
||||
Generate React component with:
|
||||
1. Distinctive typography (custom fonts, not Inter)
|
||||
2. Brand colors (custom palette, not purple)
|
||||
3. Rich animations (transitions, micro-interactions)
|
||||
4. Deep shadcn/ui customization (ui prop + utilities)
|
||||
5. Accessibility features (ARIA, keyboard, focus states)
|
||||
6. Responsive design
|
||||
</thinking>
|
||||
|
||||
#### Component Templates by Type:
|
||||
|
||||
#### Button Component
|
||||
|
||||
<button_template>
|
||||
|
||||
```tsx
|
||||
<!-- app/components/PrimaryButton.tsx -->
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'react';
|
||||
|
||||
interface Props {
|
||||
/** Button label */
|
||||
label?: string;
|
||||
/** Icon name (Iconify format) */
|
||||
icon?: string;
|
||||
/** Loading state */
|
||||
loading?: boolean;
|
||||
/** Disabled state */
|
||||
disabled?: boolean;
|
||||
/** Button size */
|
||||
size?: 'sm' | 'md' | 'lg' | 'xl';
|
||||
/** Full width */
|
||||
fullWidth?: boolean;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
label: '',
|
||||
icon: '',
|
||||
loading: false,
|
||||
disabled: false,
|
||||
size: 'lg',
|
||||
fullWidth: false
|
||||
});
|
||||
|
||||
const emit = defineEmits<{
|
||||
click: [event: MouseEvent];
|
||||
}>();
|
||||
|
||||
const buttonClasses = computed(() => ({
|
||||
'w-full': props.fullWidth
|
||||
}));
|
||||
|
||||
<Button
|
||||
:color="primary"
|
||||
:size="size"
|
||||
loading={loading"
|
||||
disabled={disabled || loading"
|
||||
:icon="icon"
|
||||
:ui="{
|
||||
font: 'font-heading tracking-wide',
|
||||
rounded: 'rounded-full',
|
||||
padding: {
|
||||
sm: 'px-4 py-2',
|
||||
md: 'px-6 py-3',
|
||||
lg: 'px-8 py-4',
|
||||
xl: 'px-10 py-5'
|
||||
},
|
||||
shadow: 'shadow-lg hover:shadow-xl'
|
||||
}"
|
||||
:class="[
|
||||
'transition-all duration-300 ease-out',
|
||||
'hover:scale-105 hover:-rotate-1',
|
||||
'active:scale-95 active:rotate-0',
|
||||
'focus:outline-none',
|
||||
'focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2',
|
||||
'motion-safe:hover:scale-105',
|
||||
'motion-reduce:hover:bg-primary-700',
|
||||
buttonClasses
|
||||
]"
|
||||
onClick={emit('click', $event)"
|
||||
>
|
||||
<span class="inline-flex items-center gap-2">
|
||||
<slot>{ label}</slot>
|
||||
|
||||
<!-- Animated icon on hover -->
|
||||
<Icon
|
||||
{&& "icon && !loading"
|
||||
:name="icon"
|
||||
class="
|
||||
transition-transform duration-300
|
||||
group-hover:translate-x-1 group-hover:-translate-y-0.5
|
||||
"
|
||||
/>
|
||||
</span>
|
||||
</Button>
|
||||
```
|
||||
|
||||
**Usage Example**:
|
||||
```tsx
|
||||
const handleClick = () => {
|
||||
console.log('Clicked!');
|
||||
};
|
||||
|
||||
<PrimaryButton
|
||||
label="Get Started"
|
||||
icon="i-heroicons-arrow-right"
|
||||
size="lg"
|
||||
onClick={handleClick"
|
||||
/>
|
||||
```
|
||||
|
||||
</button_template>
|
||||
|
||||
#### Card Component
|
||||
|
||||
<card_template>
|
||||
|
||||
```tsx
|
||||
<!-- app/components/FeatureCard.tsx -->
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'react';
|
||||
|
||||
interface Props {
|
||||
/** Card title */
|
||||
title: string;
|
||||
/** Card description */
|
||||
description?: string;
|
||||
/** Icon name */
|
||||
icon?: string;
|
||||
/** Enable hover effects */
|
||||
hoverable?: boolean;
|
||||
/** Card variant */
|
||||
variant?: 'default' | 'elevated' | 'outlined';
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
description: '',
|
||||
icon: '',
|
||||
hoverable: true,
|
||||
variant: 'elevated'
|
||||
});
|
||||
|
||||
const isHovered = ref(false);
|
||||
|
||||
const cardUi = computed(() => ({
|
||||
background: 'bg-white dark:bg-brand-midnight',
|
||||
ring: props.variant === 'outlined' ? 'ring-1 ring-brand-coral/20' : '',
|
||||
rounded: 'rounded-2xl',
|
||||
shadow: props.variant === 'elevated' ? 'shadow-xl hover:shadow-2xl' : 'shadow-md',
|
||||
body: {
|
||||
padding: 'p-8',
|
||||
background: 'bg-gradient-to-br from-white to-gray-50 dark:from-brand-midnight dark:to-gray-900'
|
||||
}
|
||||
}));
|
||||
|
||||
<Card
|
||||
:ui="cardUi"
|
||||
:class="[
|
||||
'transition-all duration-300',
|
||||
hoverable && 'hover:-translate-y-2 hover:rotate-1 cursor-pointer',
|
||||
'motion-safe:hover:-translate-y-2',
|
||||
'motion-reduce:hover:shadow-xl'
|
||||
]"
|
||||
onMouseEnter="isHovered = true"
|
||||
onMouseLeave="isHovered = false"
|
||||
>
|
||||
<div class="space-y-4">
|
||||
<!-- Icon -->
|
||||
<div
|
||||
{&& "icon"
|
||||
:class="[
|
||||
'inline-flex items-center justify-center',
|
||||
'w-16 h-16 rounded-2xl',
|
||||
'bg-gradient-to-br from-brand-coral to-brand-ocean',
|
||||
'transition-transform duration-300',
|
||||
isHovered && 'scale-110 rotate-3'
|
||||
]"
|
||||
>
|
||||
<Icon
|
||||
:name="icon"
|
||||
class="w-8 h-8 text-white"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Title -->
|
||||
<h3
|
||||
:class="[
|
||||
'font-heading text-2xl',
|
||||
'text-brand-midnight dark:text-white',
|
||||
'transition-colors duration-300',
|
||||
isHovered && 'text-brand-coral'
|
||||
]"
|
||||
>
|
||||
{ title}
|
||||
</h3>
|
||||
|
||||
<!-- Description -->
|
||||
<p
|
||||
{&& "description"
|
||||
class="text-gray-700 dark:text-gray-300 leading-relaxed"
|
||||
>
|
||||
{ description}
|
||||
</p>
|
||||
|
||||
<!-- Default slot for custom content -->
|
||||
<div {&& "$slots.default">
|
||||
<slot />
|
||||
</div>
|
||||
|
||||
<!-- Footer slot -->
|
||||
<div {&& "$slots.footer" class="pt-4 border-t border-gray-200 dark:border-gray-700">
|
||||
<slot name="footer" />
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
```
|
||||
|
||||
**Usage Example**:
|
||||
```tsx
|
||||
<FeatureCard
|
||||
title="Fast Deployment"
|
||||
description="Deploy to the edge in seconds with Cloudflare Workers"
|
||||
icon="i-heroicons-rocket-launch"
|
||||
hoverable
|
||||
>
|
||||
<template #footer>
|
||||
<PrimaryButton label="Learn More" size="sm" />
|
||||
</FeatureCard>
|
||||
```
|
||||
|
||||
</card_template>
|
||||
|
||||
#### Form Component
|
||||
|
||||
<form_template>
|
||||
|
||||
```tsx
|
||||
<!-- app/components/ContactForm.tsx -->
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive } from 'react';
|
||||
import { z } from 'zod';
|
||||
import type { FormSubmitEvent } from '#ui/types';
|
||||
|
||||
// Validation schema
|
||||
const schema = z.object({
|
||||
name: z.string().min(2, 'Name must be at least 2 characters'),
|
||||
email: z.string().email('Invalid email address'),
|
||||
message: z.string().min(10, 'Message must be at least 10 characters')
|
||||
});
|
||||
|
||||
type Schema = z.output<typeof schema>;
|
||||
|
||||
const formData = reactive<Schema>({
|
||||
name: '',
|
||||
email: '',
|
||||
message: ''
|
||||
});
|
||||
|
||||
const isSubmitting = ref(false);
|
||||
const showSuccess = ref(false);
|
||||
const showError = ref(false);
|
||||
const errorMessage = ref('');
|
||||
|
||||
const onSubmit = async (event: FormSubmitEvent<Schema>) => {
|
||||
isSubmitting.value = true;
|
||||
showSuccess.value = false;
|
||||
showError.value = false;
|
||||
|
||||
try {
|
||||
// Simulate API call
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
|
||||
console.log('Form submitted:', event.data);
|
||||
|
||||
showSuccess.value = true;
|
||||
|
||||
// Reset form
|
||||
formData.name = '';
|
||||
formData.email = '';
|
||||
formData.message = '';
|
||||
|
||||
// Hide success message after 5 seconds
|
||||
setTimeout(() => {
|
||||
showSuccess.value = false;
|
||||
}, 5000);
|
||||
} catch (error) {
|
||||
showError.value = true;
|
||||
errorMessage.value = 'Failed to submit form. Please try again.';
|
||||
} finally {
|
||||
isSubmitting.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
<div class="space-y-6">
|
||||
<!-- Success Alert -->
|
||||
<Transition
|
||||
enter-active-class="transition-all duration-300 ease-out"
|
||||
enter-from-class="opacity-0 translate-y-2 scale-95"
|
||||
enter-to-class="opacity-100 translate-y-0 scale-100"
|
||||
leave-active-class="transition-all duration-200 ease-in"
|
||||
leave-from-class="opacity-100"
|
||||
leave-to-class="opacity-0"
|
||||
>
|
||||
<Alert
|
||||
{&& "showSuccess"
|
||||
color="green"
|
||||
icon="i-heroicons-check-circle"
|
||||
title="Success!"
|
||||
description="Your message has been sent successfully."
|
||||
:closable="true"
|
||||
:ui="{ rounded: 'rounded-xl', padding: 'p-4' }"
|
||||
onClose="showSuccess = false"
|
||||
/>
|
||||
</Transition>
|
||||
|
||||
<!-- Error Alert -->
|
||||
<Transition
|
||||
enter-active-class="transition-all duration-300 ease-out"
|
||||
enter-from-class="opacity-0 translate-y-2"
|
||||
enter-to-class="opacity-100 translate-y-0"
|
||||
>
|
||||
<Alert
|
||||
{&& "showError"
|
||||
color="red"
|
||||
icon="i-heroicons-x-circle"
|
||||
title="Error"
|
||||
:description="errorMessage"
|
||||
:closable="true"
|
||||
onClose="showError = false"
|
||||
/>
|
||||
</Transition>
|
||||
|
||||
<!-- Form -->
|
||||
<UForm
|
||||
:schema="schema"
|
||||
:state="formData"
|
||||
class="space-y-6"
|
||||
onSubmit="onSubmit"
|
||||
>
|
||||
<!-- Name Field -->
|
||||
<UFormGroup
|
||||
label="Name"
|
||||
name="name"
|
||||
required
|
||||
:ui="{ label: { base: 'font-medium text-sm' } }"
|
||||
>
|
||||
<Input
|
||||
value="formData.name"
|
||||
placeholder="Your name"
|
||||
icon="i-heroicons-user"
|
||||
:ui="{
|
||||
rounded: 'rounded-lg',
|
||||
padding: { sm: 'px-4 py-3' },
|
||||
icon: { leading: { padding: { sm: 'ps-11' } } }
|
||||
}"
|
||||
class="transition-all duration-200 focus-within:ring-2 focus-within:ring-brand-coral"
|
||||
/>
|
||||
</UFormGroup>
|
||||
|
||||
<!-- Email Field -->
|
||||
<UFormGroup
|
||||
label="Email"
|
||||
name="email"
|
||||
required
|
||||
>
|
||||
<Input
|
||||
value="formData.email"
|
||||
type="email"
|
||||
placeholder="your@email.com"
|
||||
icon="i-heroicons-envelope"
|
||||
:ui="{
|
||||
rounded: 'rounded-lg',
|
||||
padding: { sm: 'px-4 py-3' }
|
||||
}"
|
||||
class="transition-all duration-200 focus-within:ring-2 focus-within:ring-brand-coral"
|
||||
/>
|
||||
</UFormGroup>
|
||||
|
||||
<!-- Message Field -->
|
||||
<UFormGroup
|
||||
label="Message"
|
||||
name="message"
|
||||
required
|
||||
>
|
||||
<UTextarea
|
||||
value="formData.message"
|
||||
placeholder="Your message..."
|
||||
:rows="5"
|
||||
:ui="{
|
||||
rounded: 'rounded-lg',
|
||||
padding: { sm: 'px-4 py-3' }
|
||||
}"
|
||||
class="transition-all duration-200 focus-within:ring-2 focus-within:ring-brand-coral"
|
||||
/>
|
||||
</UFormGroup>
|
||||
|
||||
<!-- Submit Button -->
|
||||
<Button
|
||||
type="submit"
|
||||
loading={isSubmitting"
|
||||
disabled={isSubmitting"
|
||||
color="primary"
|
||||
size="lg"
|
||||
:ui="{
|
||||
font: 'font-heading',
|
||||
rounded: 'rounded-full',
|
||||
padding: { lg: 'px-8 py-4' }
|
||||
}"
|
||||
class="
|
||||
w-full
|
||||
transition-all duration-300
|
||||
hover:scale-105 hover:shadow-xl
|
||||
active:scale-95
|
||||
motion-safe:hover:scale-105
|
||||
motion-reduce:hover:bg-primary-700
|
||||
"
|
||||
>
|
||||
<span class="inline-flex items-center gap-2">
|
||||
<Icon
|
||||
{&& "!isSubmitting"
|
||||
name="i-heroicons-paper-airplane"
|
||||
class="transition-transform duration-300 group-hover:translate-x-1 group-hover:-translate-y-0.5"
|
||||
/>
|
||||
{ isSubmitting ? 'Sending...' : 'Send Message'}
|
||||
</span>
|
||||
</Button>
|
||||
</UForm>
|
||||
</div>
|
||||
```
|
||||
|
||||
</form_template>
|
||||
|
||||
#### Hero Component
|
||||
|
||||
<hero_template>
|
||||
|
||||
```tsx
|
||||
<!-- app/components/LandingHero.tsx -->
|
||||
<script setup lang="ts">
|
||||
interface Props {
|
||||
/** Hero title */
|
||||
title: string;
|
||||
/** Hero subtitle */
|
||||
subtitle?: string;
|
||||
/** Primary CTA label */
|
||||
primaryCta?: string;
|
||||
/** Secondary CTA label */
|
||||
secondaryCta?: string;
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
subtitle: '',
|
||||
primaryCta: 'Get Started',
|
||||
secondaryCta: 'Learn More'
|
||||
});
|
||||
|
||||
const emit = defineEmits<{
|
||||
primaryClick: [];
|
||||
secondaryClick: [];
|
||||
}>();
|
||||
|
||||
<div class="relative min-h-screen flex items-center justify-center overflow-hidden">
|
||||
<!-- Atmospheric Background -->
|
||||
<div class="absolute inset-0 bg-gradient-to-br from-brand-cream via-white to-brand-ocean/10" />
|
||||
|
||||
<!-- Animated Gradient Orbs -->
|
||||
<div
|
||||
class="absolute top-20 left-20 w-96 h-96 bg-brand-coral/20 rounded-full blur-3xl animate-pulse"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<div
|
||||
class="absolute bottom-20 right-20 w-96 h-96 bg-brand-ocean/20 rounded-full blur-3xl animate-pulse"
|
||||
style="animation-delay: 1s;"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
|
||||
<!-- Subtle Pattern Overlay -->
|
||||
<div
|
||||
class="absolute inset-0 opacity-5"
|
||||
style="background-image: radial-gradient(circle, #000 1px, transparent 1px); background-size: 20px 20px;"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
|
||||
<!-- Content -->
|
||||
<div class="relative z-10 max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-24">
|
||||
<div class="text-center space-y-8">
|
||||
<!-- Animated Badge -->
|
||||
<div
|
||||
class="
|
||||
inline-flex items-center gap-2
|
||||
px-4 py-2 rounded-full
|
||||
bg-brand-coral/10 border border-brand-coral/20
|
||||
text-brand-coral font-medium
|
||||
animate-in slide-in-from-top duration-500
|
||||
"
|
||||
>
|
||||
<Icon name="i-heroicons-sparkles" class="w-4 h-4 animate-pulse" />
|
||||
<span class="text-sm">New: Now on Cloudflare Workers</span>
|
||||
</div>
|
||||
|
||||
<!-- Title -->
|
||||
<h1
|
||||
class="
|
||||
font-heading text-6xl sm:text-7xl lg:text-8xl
|
||||
tracking-tighter leading-none
|
||||
text-brand-midnight dark:text-white
|
||||
animate-in slide-in-from-top duration-700
|
||||
"
|
||||
style="animation-delay: 100ms;"
|
||||
>
|
||||
{ title}
|
||||
</h1>
|
||||
|
||||
<!-- Subtitle -->
|
||||
<p
|
||||
{&& "subtitle"
|
||||
class="
|
||||
max-w-2xl mx-auto
|
||||
text-xl sm:text-2xl leading-relaxed
|
||||
text-gray-700 dark:text-gray-300
|
||||
animate-in slide-in-from-top duration-700
|
||||
"
|
||||
style="animation-delay: 200ms;"
|
||||
>
|
||||
{ subtitle}
|
||||
</p>
|
||||
|
||||
<!-- CTAs -->
|
||||
<div
|
||||
class="
|
||||
flex flex-col sm:flex-row items-center justify-center gap-4
|
||||
animate-in slide-in-from-top duration-700
|
||||
"
|
||||
style="animation-delay: 300ms;"
|
||||
>
|
||||
<Button
|
||||
color="primary"
|
||||
size="xl"
|
||||
:ui="{
|
||||
font: 'font-heading tracking-wide',
|
||||
rounded: 'rounded-full',
|
||||
padding: { xl: 'px-10 py-5' }
|
||||
}"
|
||||
class="
|
||||
transition-all duration-300
|
||||
hover:scale-110 hover:-rotate-2 hover:shadow-2xl
|
||||
active:scale-95 active:rotate-0
|
||||
motion-safe:hover:scale-110
|
||||
"
|
||||
onClick={emit('primaryClick')"
|
||||
>
|
||||
<span class="inline-flex items-center gap-2">
|
||||
{ primaryCta}
|
||||
<Icon
|
||||
name="i-heroicons-arrow-right"
|
||||
class="transition-transform duration-300 group-hover:translate-x-2"
|
||||
/>
|
||||
</span>
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
color="gray"
|
||||
variant="outline"
|
||||
size="xl"
|
||||
:ui="{
|
||||
font: 'font-sans',
|
||||
rounded: 'rounded-full'
|
||||
}"
|
||||
class="
|
||||
transition-all duration-300
|
||||
hover:scale-105 hover:shadow-lg
|
||||
active:scale-95
|
||||
"
|
||||
onClick={emit('secondaryClick')"
|
||||
>
|
||||
{ secondaryCta}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<!-- Slot for additional content -->
|
||||
<div {&& "$slots.default" class="mt-12">
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
</hero_template>
|
||||
|
||||
### 4. Create Design System Composable (if missing)
|
||||
|
||||
<thinking>
|
||||
If design system composable doesn't exist, generate it to ensure consistency
|
||||
across all components.
|
||||
</thinking>
|
||||
|
||||
<design_system_composable>
|
||||
|
||||
```typescript
|
||||
// composables/useDesignSystem.ts
|
||||
import type { ButtonProps } from '#ui/types';
|
||||
|
||||
export const useDesignSystem = () => {
|
||||
/**
|
||||
* Button Variants
|
||||
*/
|
||||
const button = {
|
||||
primary: {
|
||||
color: 'primary',
|
||||
size: 'lg',
|
||||
ui: {
|
||||
font: 'font-heading tracking-wide',
|
||||
rounded: 'rounded-full',
|
||||
padding: { lg: 'px-8 py-4' },
|
||||
shadow: 'shadow-lg hover:shadow-xl'
|
||||
},
|
||||
class: 'transition-all duration-300 hover:scale-105 hover:-rotate-1 active:scale-95 active:rotate-0'
|
||||
} as ButtonProps,
|
||||
|
||||
secondary: {
|
||||
color: 'gray',
|
||||
variant: 'outline',
|
||||
size: 'md',
|
||||
ui: {
|
||||
font: 'font-sans',
|
||||
rounded: 'rounded-lg'
|
||||
},
|
||||
class: 'transition-colors duration-200 hover:bg-gray-100 dark:hover:bg-gray-800'
|
||||
} as ButtonProps,
|
||||
|
||||
ghost: {
|
||||
variant: 'ghost',
|
||||
size: 'md',
|
||||
ui: {
|
||||
font: 'font-sans'
|
||||
},
|
||||
class: 'transition-colors duration-200'
|
||||
} as ButtonProps
|
||||
};
|
||||
|
||||
/**
|
||||
* Card Variants
|
||||
*/
|
||||
const card = {
|
||||
elevated: {
|
||||
ui: {
|
||||
background: 'bg-white dark:bg-brand-midnight',
|
||||
rounded: 'rounded-2xl',
|
||||
shadow: 'shadow-xl hover:shadow-2xl',
|
||||
body: { padding: 'p-8' }
|
||||
},
|
||||
class: 'transition-all duration-300 hover:-translate-y-1'
|
||||
},
|
||||
|
||||
outlined: {
|
||||
ui: {
|
||||
background: 'bg-white dark:bg-brand-midnight',
|
||||
ring: 'ring-1 ring-brand-coral/20',
|
||||
rounded: 'rounded-2xl',
|
||||
body: { padding: 'p-8' }
|
||||
},
|
||||
class: 'transition-all duration-300 hover:ring-brand-coral/40'
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Animation Presets
|
||||
*/
|
||||
const animations = {
|
||||
fadeIn: 'animate-in fade-in duration-500',
|
||||
slideUp: 'animate-in slide-in-from-bottom duration-500',
|
||||
slideDown: 'animate-in slide-in-from-top duration-500',
|
||||
scaleIn: 'animate-in zoom-in duration-300',
|
||||
hover: {
|
||||
scale: 'transition-transform duration-300 hover:scale-105',
|
||||
lift: 'transition-all duration-300 hover:-translate-y-1',
|
||||
shadow: 'transition-shadow duration-300 hover:shadow-xl'
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
button,
|
||||
card,
|
||||
animations
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
</design_system_composable>
|
||||
|
||||
### 5. Generate Component Files
|
||||
|
||||
<thinking>
|
||||
Create the actual files in the filesystem with proper naming and structure.
|
||||
</thinking>
|
||||
|
||||
#### File Creation:
|
||||
|
||||
<file_creation_steps>
|
||||
|
||||
1. **Determine output path**:
|
||||
- Default: `components/<ComponentName>.react`
|
||||
- Custom: User-specified `--output` path
|
||||
|
||||
2. **Generate component file**:
|
||||
- Use template for component type
|
||||
- Replace placeholders with actual names
|
||||
- Include TypeScript types
|
||||
- Include JSDoc comments
|
||||
- Include usage examples in comments
|
||||
|
||||
3. **Update or create design system composable** (if needed):
|
||||
- Path: `composables/useDesignSystem.ts`
|
||||
- Add new variants if applicable
|
||||
|
||||
4. **Generate Storybook story** (optional, if Storybook detected):
|
||||
- Path: `components/<ComponentName>.stories.ts`
|
||||
|
||||
5. **Generate test file** (optional):
|
||||
- Path: `components/<ComponentName>.spec.ts`
|
||||
|
||||
</file_creation_steps>
|
||||
|
||||
### 6. Validate Generated Component
|
||||
|
||||
<thinking>
|
||||
Run validation to ensure generated component follows best practices.
|
||||
</thinking>
|
||||
|
||||
#### Validation Checks:
|
||||
|
||||
<validation_checklist>
|
||||
|
||||
- [ ] Uses custom fonts (not Inter/Roboto)
|
||||
- [ ] Uses brand colors (not default purple)
|
||||
- [ ] Includes animations/transitions
|
||||
- [ ] Has hover states on interactive elements
|
||||
- [ ] Has focus states (focus-visible rings)
|
||||
- [ ] Respects reduced motion (motion-safe/motion-reduce)
|
||||
- [ ] Includes ARIA labels where needed
|
||||
- [ ] Uses shadcn/ui components (not reinventing)
|
||||
- [ ] Deep customization with `ui` prop
|
||||
- [ ] TypeScript props interface
|
||||
- [ ] JSDoc comments
|
||||
- [ ] Accessible (keyboard navigation, screen readers)
|
||||
- [ ] Responsive design
|
||||
- [ ] Dark mode support
|
||||
|
||||
</validation_checklist>
|
||||
|
||||
## Output Format
|
||||
|
||||
<output_format>
|
||||
|
||||
```
|
||||
✅ Component Generated: <ComponentName>
|
||||
|
||||
📁 Files Created:
|
||||
- app/components/<ComponentName>.tsx (primary component)
|
||||
- composables/useDesignSystem.ts (updated/created)
|
||||
|
||||
🎨 Design Features:
|
||||
✅ Custom typography (font-heading)
|
||||
✅ Brand colors (brand-coral, brand-ocean)
|
||||
✅ Rich animations (hover:scale-105, transitions)
|
||||
✅ Deep shadcn/ui customization (ui prop)
|
||||
✅ Accessibility features (ARIA, focus states)
|
||||
✅ Reduced motion support (motion-safe)
|
||||
✅ Responsive design
|
||||
✅ Dark mode support
|
||||
|
||||
📖 Usage Example:
|
||||
|
||||
```tsx
|
||||
import { <ComponentName> } from '#components';
|
||||
|
||||
// Your component logic
|
||||
|
||||
<<ComponentName>
|
||||
prop1="value1"
|
||||
prop2="value2"
|
||||
onEvent="handleEvent"
|
||||
/>
|
||||
```
|
||||
|
||||
🔍 Next Steps:
|
||||
1. Review generated component in `components/<ComponentName>.react`
|
||||
2. Customize props/styles as needed
|
||||
3. Test accessibility with keyboard navigation
|
||||
4. Test animations with reduced motion preference
|
||||
5. Run `/es-design-review` to validate design patterns
|
||||
```
|
||||
|
||||
</output_format>
|
||||
|
||||
## Success Criteria
|
||||
|
||||
✅ Component generated successfully when:
|
||||
- File created at correct path
|
||||
- Uses distinctive design patterns (not generic)
|
||||
- Includes all accessibility features
|
||||
- Includes rich animations
|
||||
- TypeScript types included
|
||||
- Usage examples in comments
|
||||
- Follows project conventions
|
||||
|
||||
## Post-Generation Actions
|
||||
|
||||
After generating component:
|
||||
1. **Review code**: Open generated file and review
|
||||
2. **Test component**: Add to a page and test interactions
|
||||
3. **Validate design**: Run `/es-design-review` if needed
|
||||
4. **Document**: Add to component library docs/Storybook
|
||||
|
||||
## Notes
|
||||
|
||||
- This command generates **starting templates** with best practices built-in
|
||||
- Components are **fully customizable** after generation
|
||||
- **Design system composable** ensures consistency across all generated components
|
||||
- Use **shadcn/ui MCP** (if available) to prevent prop hallucination
|
||||
- All generated components follow **WCAG 2.1 AA** accessibility standards
|
||||
- Generated components respect **user's reduced motion preference**
|
||||
459
commands/es-deploy.md
Normal file
459
commands/es-deploy.md
Normal file
@@ -0,0 +1,459 @@
|
||||
---
|
||||
description: Perform comprehensive pre-flight checks and deploy Cloudflare Workers safely using wrangler
|
||||
---
|
||||
|
||||
# Cloudflare Workers Deployment Command
|
||||
|
||||
<command_purpose> Perform comprehensive pre-flight checks and deploy Cloudflare Workers safely using wrangler with multi-agent validation. </command_purpose>
|
||||
|
||||
## Introduction
|
||||
|
||||
<role>Cloudflare Deployment Specialist with expertise in Workers deployment, wrangler CLI, and production readiness validation</role>
|
||||
|
||||
This command performs thorough pre-deployment validation, runs all necessary checks, and safely deploys your Worker to Cloudflare's edge network.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
<requirements>
|
||||
- Cloudflare account with Workers enabled
|
||||
- wrangler CLI installed (`npm install -g wrangler`)
|
||||
- Authenticated with Cloudflare (`wrangler login`)
|
||||
- Valid `wrangler.toml` configuration
|
||||
- Clean git working directory (recommended)
|
||||
</requirements>
|
||||
|
||||
## Deployment Target
|
||||
|
||||
<deployment_target> #$ARGUMENTS </deployment_target>
|
||||
|
||||
**Supported targets**:
|
||||
- Empty (default) - Deploy to production
|
||||
- `--env staging` - Deploy to staging environment
|
||||
- `--env preview` - Deploy to preview environment
|
||||
- `--dry-run` - Perform all checks without deploying
|
||||
|
||||
## Main Tasks
|
||||
|
||||
### 1. Pre-Flight Checks (Critical - Must Pass)
|
||||
|
||||
<critical_requirement> ALL pre-flight checks must pass before deployment. No exceptions. </critical_requirement>
|
||||
|
||||
#### Phase 1: Configuration Validation
|
||||
|
||||
<thinking>
|
||||
First, validate the wrangler.toml configuration and ensure all required settings are present.
|
||||
</thinking>
|
||||
|
||||
**Checks to perform**:
|
||||
|
||||
1. **Verify wrangler.toml exists**
|
||||
```bash
|
||||
if [ ! -f wrangler.toml ]; then
|
||||
echo "❌ CRITICAL: wrangler.toml not found"
|
||||
exit 1
|
||||
fi
|
||||
```
|
||||
|
||||
2. **Validate required fields**
|
||||
- Task binding-context-analyzer(deployment target)
|
||||
- Parse wrangler.toml
|
||||
- Verify all bindings have valid IDs
|
||||
- Check compatibility_date is 2025-09-15 or later (required for remote bindings GA)
|
||||
- Verify all bindings have `remote = true` configured for development
|
||||
- Validate name, main, and account_id fields
|
||||
|
||||
3. **Check authentication**
|
||||
```bash
|
||||
wrangler whoami
|
||||
# Verify logged in to correct account
|
||||
```
|
||||
|
||||
#### Phase 2: Code Quality Checks
|
||||
|
||||
**SKILL-based Continuous Validation** (Already Active During Development):
|
||||
- **workers-runtime-validator SKILL**: Runtime compatibility validation
|
||||
- **cloudflare-security-checker SKILL**: Security pattern validation
|
||||
- **workers-binding-validator SKILL**: Binding configuration validation
|
||||
- **edge-performance-optimizer SKILL**: Performance optimization guidance
|
||||
- **kv-optimization-advisor SKILL**: KV storage optimization
|
||||
- **durable-objects-pattern-checker SKILL**: DO best practices validation
|
||||
- **cors-configuration-validator SKILL**: CORS setup validation
|
||||
|
||||
**Agent-based Comprehensive Analysis** (Run for deployment validation):
|
||||
|
||||
**Critical Checks (Must Pass)**:
|
||||
|
||||
1. Task workers-runtime-guardian(current code)
|
||||
- Deep runtime compatibility analysis
|
||||
- Complex Node.js API migration patterns
|
||||
- Package dependency analysis
|
||||
- **Status**: Must be CRITICAL-free (P1 issues block deployment)
|
||||
- **Note**: Complements workers-runtime-validator SKILL
|
||||
|
||||
2. Task cloudflare-security-sentinel(current code)
|
||||
- Comprehensive security audit
|
||||
- Advanced threat analysis
|
||||
- Security architecture review
|
||||
- **Status**: Must be CRITICAL-free (P1 security issues block deployment)
|
||||
- **Note**: Complements cloudflare-security-checker SKILL
|
||||
|
||||
3. Task binding-context-analyzer(current code)
|
||||
- Complex binding configuration analysis
|
||||
- Cross-service binding validation
|
||||
- Advanced binding patterns
|
||||
- **Status**: Must have no mismatches
|
||||
- **Note**: Complements workers-binding-validator SKILL
|
||||
|
||||
**Important Checks (Warnings)**:
|
||||
|
||||
4. Task edge-performance-oracle(current code)
|
||||
- Comprehensive performance analysis
|
||||
- Global latency optimization
|
||||
- Advanced bundle optimization
|
||||
- **Status**: P2 issues generate warnings
|
||||
- **Note**: Complements edge-performance-optimizer SKILL
|
||||
|
||||
5. Task cloudflare-pattern-specialist(current code)
|
||||
- Advanced Cloudflare architecture patterns
|
||||
- Complex anti-pattern detection
|
||||
- Multi-service optimization
|
||||
- **Status**: P2 issues generate warnings
|
||||
- **Note**: Complements all storage SKILLs
|
||||
|
||||
#### Phase 3: Build & Test
|
||||
|
||||
<thinking>
|
||||
Build the Worker and run tests to ensure everything works before deployment.
|
||||
</thinking>
|
||||
|
||||
1. **Clean previous builds**
|
||||
```bash
|
||||
rm -rf dist/ .wrangler/
|
||||
```
|
||||
|
||||
2. **Install dependencies**
|
||||
```bash
|
||||
npm ci # Clean install from lock file
|
||||
```
|
||||
|
||||
3. **Type checking**
|
||||
```bash
|
||||
npm run typecheck || tsc --noEmit
|
||||
```
|
||||
|
||||
4. **Linting**
|
||||
```bash
|
||||
npm run lint
|
||||
```
|
||||
|
||||
5. **Run tests**
|
||||
```bash
|
||||
npm test
|
||||
```
|
||||
|
||||
6. **Build Worker**
|
||||
```bash
|
||||
wrangler deploy --dry-run --outdir=./dist
|
||||
```
|
||||
|
||||
7. **Analyze bundle size**
|
||||
```bash
|
||||
du -h ./dist/*.js
|
||||
# Warn if > 100KB, error if > 500KB
|
||||
```
|
||||
|
||||
#### Phase 4: Local Testing (Optional but Recommended)
|
||||
|
||||
<thinking>
|
||||
Test the Worker locally with wrangler dev to catch runtime issues.
|
||||
</thinking>
|
||||
|
||||
Ask user: "Run local testing with wrangler dev? (recommended, y/n)"
|
||||
|
||||
If yes:
|
||||
1. Start wrangler dev in background
|
||||
2. Wait 5 seconds for startup
|
||||
3. Test basic endpoints:
|
||||
```bash
|
||||
curl http://localhost:8787/
|
||||
# Verify 200 response
|
||||
```
|
||||
4. Stop wrangler dev
|
||||
|
||||
### 2. Pre-Deployment Summary
|
||||
|
||||
<deliverable>
|
||||
Present comprehensive pre-deployment report to user
|
||||
</deliverable>
|
||||
|
||||
```markdown
|
||||
## Deployment Pre-Flight Summary
|
||||
|
||||
**Target Environment**: [production/staging/preview]
|
||||
**Worker Name**: [from wrangler.toml]
|
||||
**Account**: [from wrangler whoami]
|
||||
|
||||
### ✅ Configuration
|
||||
- wrangler.toml: Valid
|
||||
- Bindings: [X] configured
|
||||
- KV: [list]
|
||||
- R2: [list]
|
||||
- D1: [list]
|
||||
- DO: [list]
|
||||
- Compatibility Date: [date] (✅ recent / ⚠️ outdated)
|
||||
|
||||
### ✅ Code Quality
|
||||
- Runtime Compatibility: [PASS/FAIL]
|
||||
- Issues: [X] Critical, [Y] Important
|
||||
- Security: [PASS/FAIL]
|
||||
- Issues: [X] Critical, [Y] Important
|
||||
- Binding Validation: [PASS/FAIL]
|
||||
- Mismatches: [count]
|
||||
|
||||
### ✅ Build
|
||||
- TypeScript: [PASS/FAIL]
|
||||
- Linting: [PASS/FAIL]
|
||||
- Tests: [PASS/FAIL] ([X] passed, [Y] failed)
|
||||
- Bundle Size: [size] (✅ < 100KB / ⚠️ > 100KB / ❌ > 500KB)
|
||||
|
||||
### 🔍 Performance Analysis
|
||||
- Cold Start (estimated): [X]ms
|
||||
- Heavy Dependencies: [list if any]
|
||||
- Warnings: [count]
|
||||
|
||||
### ⚠️ Blocking Issues (Must Fix)
|
||||
[List any P1 issues that prevent deployment]
|
||||
|
||||
### ⚠️ Warnings (Recommended to Fix)
|
||||
[List any P2 issues]
|
||||
|
||||
---
|
||||
**Decision**: [READY TO DEPLOY / ISSUES MUST BE FIXED]
|
||||
```
|
||||
|
||||
### 3. User Confirmation
|
||||
|
||||
<critical_requirement> Always require explicit user confirmation before deploying. </critical_requirement>
|
||||
|
||||
**If blocking issues exist**:
|
||||
```
|
||||
❌ Cannot deploy - [X] critical issues must be fixed:
|
||||
1. [Issue description]
|
||||
2. [Issue description]
|
||||
|
||||
Run /triage to create todos for these issues.
|
||||
```
|
||||
|
||||
**If only warnings exist**:
|
||||
```
|
||||
⚠️ Ready to deploy with [X] warnings:
|
||||
1. [Warning description]
|
||||
2. [Warning description]
|
||||
|
||||
Deploy anyway? (yes/no/show-details)
|
||||
```
|
||||
|
||||
**If all checks pass**:
|
||||
```
|
||||
✅ All checks passed. Ready to deploy.
|
||||
|
||||
Deploy to [environment]? (yes/no)
|
||||
```
|
||||
|
||||
### 4. Deployment Execution
|
||||
|
||||
<thinking>
|
||||
Execute the actual deployment with appropriate wrangler commands.
|
||||
</thinking>
|
||||
|
||||
**If user confirms YES**:
|
||||
|
||||
1. **Create git tag (if production)**
|
||||
```bash
|
||||
if [ "$environment" = "production" ]; then
|
||||
timestamp=$(date +%Y%m%d-%H%M%S)
|
||||
git tag -a "deploy-$timestamp" -m "Production deployment $timestamp"
|
||||
fi
|
||||
```
|
||||
|
||||
2. **Deploy with wrangler**
|
||||
```bash
|
||||
# For default/production
|
||||
wrangler deploy
|
||||
|
||||
# For specific environment
|
||||
wrangler deploy --env $environment
|
||||
```
|
||||
|
||||
3. **Capture deployment output**
|
||||
- Worker URL
|
||||
- Deployment ID
|
||||
- Custom domain (if configured)
|
||||
|
||||
4. **Verify deployment**
|
||||
```bash
|
||||
# Test deployed Worker
|
||||
curl -I $worker_url
|
||||
# Verify 200 response
|
||||
```
|
||||
|
||||
### 5. Post-Deployment Validation
|
||||
|
||||
<thinking>
|
||||
Verify the deployment was successful and the Worker is responding correctly.
|
||||
</thinking>
|
||||
|
||||
Run quick smoke tests:
|
||||
|
||||
1. **Health check**
|
||||
```bash
|
||||
curl $worker_url/health || curl $worker_url/
|
||||
# Expect 200 status
|
||||
```
|
||||
|
||||
2. **Verify bindings accessible** (if applicable)
|
||||
- Test endpoint that uses KV/R2/D1/DO
|
||||
- Verify no binding errors
|
||||
|
||||
3. **Check Cloudflare dashboard**
|
||||
```bash
|
||||
wrangler tail --format json | head -n 5
|
||||
# Show first 5 requests/logs
|
||||
```
|
||||
|
||||
### 6. Deployment Report
|
||||
|
||||
<deliverable>
|
||||
Final deployment summary with all details
|
||||
</deliverable>
|
||||
|
||||
```markdown
|
||||
## 🚀 Deployment Complete
|
||||
|
||||
**Environment**: [production/staging/preview]
|
||||
**Deployed At**: [timestamp]
|
||||
**Worker URL**: [url]
|
||||
**Custom Domain**: [domain] (if configured)
|
||||
|
||||
### Deployment Details
|
||||
- Worker Name: [name]
|
||||
- Bundle Size: [size]
|
||||
- Deployment ID: [id]
|
||||
- Git Tag: [tag] (if production)
|
||||
|
||||
### Verification
|
||||
- Health Check: [✅ PASS / ❌ FAIL]
|
||||
- Response Time: [X]ms
|
||||
- Status Code: [code]
|
||||
|
||||
### Next Steps
|
||||
1. Monitor logs: `wrangler tail`
|
||||
2. View analytics: https://dash.cloudflare.com
|
||||
3. Test endpoints: [list key endpoints]
|
||||
|
||||
### Rollback (if needed)
|
||||
```bash
|
||||
# View previous deployments
|
||||
wrangler deployments list
|
||||
|
||||
# Rollback to previous version
|
||||
wrangler rollback [deployment-id]
|
||||
```
|
||||
|
||||
---
|
||||
**Status**: ✅ Deployment Successful
|
||||
```
|
||||
|
||||
## Emergency Rollback
|
||||
|
||||
If deployment fails or issues are detected:
|
||||
|
||||
1. **Immediate rollback**
|
||||
```bash
|
||||
wrangler deployments list
|
||||
wrangler rollback [previous-deployment-id]
|
||||
```
|
||||
|
||||
2. **Notify user**
|
||||
```
|
||||
❌ Deployment rolled back to previous version
|
||||
Reason: [failure reason]
|
||||
|
||||
Investigate issues:
|
||||
- Check logs: wrangler tail
|
||||
- Review errors: [error details]
|
||||
```
|
||||
|
||||
## Deployment Checklist
|
||||
|
||||
<checklist>
|
||||
Before confirming deployment, verify:
|
||||
|
||||
- [ ] wrangler.toml is valid and complete
|
||||
- [ ] All bindings have valid IDs
|
||||
- [ ] No Node.js APIs in code
|
||||
- [ ] No hardcoded secrets
|
||||
- [ ] TypeScript compiles without errors
|
||||
- [ ] Linting passes
|
||||
- [ ] All tests pass
|
||||
- [ ] Bundle size is acceptable (< 500KB)
|
||||
- [ ] No CRITICAL (P1) issues from agents
|
||||
- [ ] User has confirmed deployment
|
||||
- [ ] Correct environment selected
|
||||
- [ ] Git working directory is clean (if production)
|
||||
</checklist>
|
||||
|
||||
## Environment-Specific Notes
|
||||
|
||||
### Production Deployment
|
||||
- Requires explicit confirmation
|
||||
- Creates git tag for tracking
|
||||
- Runs full validation suite
|
||||
- Monitors initial requests
|
||||
|
||||
### Staging Deployment
|
||||
- Slightly relaxed validation (P2 warnings allowed)
|
||||
- No git tag created
|
||||
- Faster deployment process
|
||||
|
||||
### Preview Deployment
|
||||
- Minimal validation
|
||||
- Quick iteration for testing
|
||||
- Temporary URL
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
**Issue**: "Error: Could not find binding {name}"
|
||||
**Solution**: Run `Task binding-context-analyzer` to verify wrangler.toml
|
||||
|
||||
**Issue**: "Error: Bundle size too large"
|
||||
**Solution**: Run `Task edge-performance-oracle` for optimization recommendations
|
||||
|
||||
**Issue**: "Error: Authentication failed"
|
||||
**Solution**: Run `wrangler login` to re-authenticate
|
||||
|
||||
**Issue**: "Error: Worker exceeded CPU limit"
|
||||
**Solution**: Check for blocking operations, infinite loops, or heavy computation
|
||||
|
||||
## Success Criteria
|
||||
|
||||
✅ **Deployment considered successful when**:
|
||||
- All pre-flight checks pass (no P1 issues)
|
||||
- Worker deploys without errors
|
||||
- Health check returns 200
|
||||
- No immediate runtime errors in logs
|
||||
- Rollback capability confirmed available
|
||||
|
||||
## Notes
|
||||
|
||||
- Always test in staging before production
|
||||
- Monitor logs for first 5-10 minutes after deployment
|
||||
- Keep rollback procedure ready
|
||||
- Document any configuration changes
|
||||
- Update team on deployment status
|
||||
|
||||
---
|
||||
|
||||
**Remember**: It's better to fail pre-flight checks than to deploy broken code. Every check exists to prevent production issues.
|
||||
538
commands/es-design-review.md
Normal file
538
commands/es-design-review.md
Normal file
@@ -0,0 +1,538 @@
|
||||
---
|
||||
description: Comprehensive frontend design review to prevent generic aesthetics and ensure distinctive, accessible, engaging interfaces using shadcn/ui and Tailwind CSS
|
||||
---
|
||||
|
||||
# Design Review Command
|
||||
|
||||
<command_purpose> Perform comprehensive frontend design reviews focusing on typography, colors, animations, component customization, and accessibility. Prevents "distributional convergence" (Inter fonts, purple gradients, minimal animations) and guides toward distinctive, branded interfaces. </command_purpose>
|
||||
|
||||
## Introduction
|
||||
|
||||
<role>Senior Frontend Design Architect with expertise in shadcn/ui, Tailwind CSS, accessibility (WCAG 2.1 AA), and distinctive design patterns</role>
|
||||
|
||||
**Design Philosophy** (from Claude Skills Blog):
|
||||
> "Think about frontend design the way a frontend engineer would. The more you can map aesthetic improvements to implementable frontend code, the better Claude can execute."
|
||||
|
||||
**Core Problem**: LLMs default to generic patterns (Inter fonts, purple gradients, minimal animations) due to distributional convergence. This command identifies and fixes these patterns.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
<requirements>
|
||||
- Tanstack Start project with Vue 3 components
|
||||
- shadcn/ui component library installed
|
||||
- Tailwind 4 CSS configured
|
||||
- Vue files (`.react`) in `components/`, `pages/`, `layouts/`
|
||||
- (Optional) shadcn/ui MCP server for accurate component guidance
|
||||
</requirements>
|
||||
|
||||
## Main Tasks
|
||||
|
||||
### 1. Project Analysis
|
||||
|
||||
<thinking>
|
||||
First, I need to understand the project structure and identify all frontend files.
|
||||
This enables targeted design review of components, pages, and configuration.
|
||||
</thinking>
|
||||
|
||||
#### Immediate Actions:
|
||||
|
||||
<task_list>
|
||||
|
||||
- [ ] Scan for Vue components in `components/`, `pages/`, `layouts/`, `app.react`
|
||||
- [ ] Check `tailwind.config.ts` or `tailwind.config.js` for custom theme configuration
|
||||
- [ ] Check `app.config.ts` for shadcn/ui configuration
|
||||
- [ ] Check `app.config.ts` for global UI customization
|
||||
- [ ] Identify which components use shadcn/ui (`Button`, `Card`, etc.)
|
||||
- [ ] Count total Vue files to determine review scope
|
||||
|
||||
</task_list>
|
||||
|
||||
#### Output Summary:
|
||||
|
||||
<summary_format>
|
||||
📊 **Project Scope**:
|
||||
- X Vue components found
|
||||
- Y shadcn/ui components detected
|
||||
- Tailwind config: Found/Not Found
|
||||
- shadcn/ui config: Found/Not Found
|
||||
- Review target: Components + Configuration
|
||||
</summary_format>
|
||||
|
||||
### 2. Multi-Phase Design Review
|
||||
|
||||
<parallel_tasks>
|
||||
|
||||
Run design-focused analysis in 3 phases. Focus on preventing generic patterns and ensuring accessible, distinctive design.
|
||||
|
||||
**Phase 1: Autonomous Skills Validation (Parallel)**
|
||||
|
||||
These skills run autonomously to catch generic patterns:
|
||||
|
||||
1. ✅ **shadcn-ui-design-validator** (SKILL)
|
||||
- Detects Inter/Roboto fonts
|
||||
- Detects purple gradients
|
||||
- Detects missing animations
|
||||
- Validates typography hierarchy
|
||||
- Checks color contrast
|
||||
|
||||
2. ✅ **component-aesthetic-checker** (SKILL)
|
||||
- Validates component customization depth
|
||||
- Checks for default props only
|
||||
- Ensures consistent design system
|
||||
- Validates spacing patterns
|
||||
- Checks loading states
|
||||
|
||||
3. ✅ **animation-interaction-validator** (SKILL)
|
||||
- Ensures hover states on interactive elements
|
||||
- Validates loading states on async actions
|
||||
- Checks for smooth transitions
|
||||
- Validates focus states
|
||||
- Ensures micro-interactions
|
||||
|
||||
**Output**: List of generic patterns detected across all components
|
||||
|
||||
**Phase 2: Deep Agent Analysis (Parallel)**
|
||||
|
||||
Launch specialized agents for comprehensive review:
|
||||
|
||||
4. Task frontend-design-specialist(all Vue files, Tailwind config)
|
||||
- Identify generic patterns (fonts, colors, animations)
|
||||
- Map aesthetic improvements to code
|
||||
- Provide specific Tailwind/shadcn/ui recommendations
|
||||
- Prioritize by impact (P1/P2/P3)
|
||||
- Generate implementable code examples
|
||||
|
||||
5. Task shadcn-ui-architect(all Vue files with shadcn/ui components)
|
||||
- Validate component selection and usage
|
||||
- Check prop usage vs available (via MCP if available)
|
||||
- Validate `ui` prop customization depth
|
||||
- Ensure consistent patterns across components
|
||||
- Suggest deep customization strategies
|
||||
|
||||
6. Task accessibility-guardian(all Vue files)
|
||||
- Validate WCAG 2.1 AA compliance
|
||||
- Check color contrast ratios
|
||||
- Validate keyboard navigation
|
||||
- Check screen reader support
|
||||
- Validate form accessibility
|
||||
- Ensure animations respect reduced motion
|
||||
|
||||
**Phase 3: Configuration & Theme Review (Sequential)**
|
||||
|
||||
7. Review Tailwind Configuration
|
||||
- Check `tailwind.config.ts` for custom fonts (not Inter/Roboto)
|
||||
- Check for custom color palette (not default purple)
|
||||
- Check for custom animation presets
|
||||
- Validate extended spacing/sizing
|
||||
- Check for design tokens
|
||||
|
||||
8. Review shadcn/ui Configuration
|
||||
- Check `app.config.ts` for global UI customization
|
||||
- Check `app.config.ts` for shadcn/ui theme settings
|
||||
- Validate consistent design system approach
|
||||
|
||||
</parallel_tasks>
|
||||
|
||||
### 3. Findings Synthesis and Prioritization
|
||||
|
||||
<thinking>
|
||||
After all agents complete, I need to consolidate findings, remove duplicates,
|
||||
and prioritize by impact on brand distinctiveness and user experience.
|
||||
</thinking>
|
||||
|
||||
#### Consolidation Process:
|
||||
|
||||
<consolidation_steps>
|
||||
|
||||
1. **Collect all findings** from skills and agents
|
||||
2. **Remove duplicates** (same issue reported by multiple sources)
|
||||
3. **Categorize by type**:
|
||||
- Typography (fonts, hierarchy, sizing)
|
||||
- Colors (palette, contrast, gradients)
|
||||
- Animations (transitions, micro-interactions, hover states)
|
||||
- Components (customization depth, consistency)
|
||||
- Accessibility (contrast, keyboard, screen readers)
|
||||
- Configuration (theme, design tokens)
|
||||
|
||||
4. **Prioritize by impact**:
|
||||
- **P1 - Critical**: Generic patterns that make site indistinguishable
|
||||
- Inter/Roboto fonts
|
||||
- Purple gradients
|
||||
- Default component props
|
||||
- Missing animations
|
||||
- Accessibility violations
|
||||
- **P2 - Important**: Missed opportunities for distinctiveness
|
||||
- Limited color palette
|
||||
- Inconsistent component patterns
|
||||
- Missing micro-interactions
|
||||
- Insufficient customization depth
|
||||
- **P3 - Polish**: Enhancements for excellence
|
||||
- Advanced animations
|
||||
- Dark mode refinements
|
||||
- Enhanced accessibility
|
||||
|
||||
5. **Generate implementation plan** with time estimates
|
||||
|
||||
</consolidation_steps>
|
||||
|
||||
#### Output Format:
|
||||
|
||||
<findings_format>
|
||||
|
||||
# 🎨 Frontend Design Review Report
|
||||
|
||||
## Executive Summary
|
||||
|
||||
**Scope**: X components reviewed, Y configuration files analyzed
|
||||
|
||||
**Findings**:
|
||||
- **P1 (Critical)**: X issues - Must fix for brand distinctiveness
|
||||
- **P2 (Important)**: Y issues - Should fix for enhanced UX
|
||||
- **P3 (Polish)**: Z opportunities - Nice to have improvements
|
||||
|
||||
**Generic Patterns Detected**:
|
||||
- ❌ Inter font used in X components
|
||||
- ❌ Purple gradient in Y components
|
||||
- ❌ Default props in Z shadcn/ui components
|
||||
- ❌ Missing animations on W interactive elements
|
||||
- ❌ A accessibility violations (WCAG 2.1 AA)
|
||||
|
||||
**Distinctiveness Score**: XX/100
|
||||
- Typography: XX/25 (Custom fonts, hierarchy, sizing)
|
||||
- Colors: XX/25 (Brand palette, contrast, distinctive gradients)
|
||||
- Animations: XX/25 (Transitions, micro-interactions, engagement)
|
||||
- Components: XX/25 (Customization depth, consistency)
|
||||
|
||||
---
|
||||
|
||||
## Critical Issues (P1)
|
||||
|
||||
### 1. Generic Typography: Inter Font Detected
|
||||
|
||||
**Severity**: P1 - High Impact
|
||||
**Files Affected**: 15 components
|
||||
**Impact**: Indistinguishable from 80%+ of modern websites
|
||||
|
||||
**Finding**: Using default Inter font system-wide
|
||||
|
||||
**Current State**:
|
||||
```tsx
|
||||
<!-- app/components/Hero.tsx:12 -->
|
||||
<h1 class="text-4xl font-sans">Welcome</h1>
|
||||
|
||||
<!-- tailwind.config.ts -->
|
||||
fontFamily: {
|
||||
sans: ['Inter', 'system-ui'] // ❌ Generic
|
||||
}
|
||||
```
|
||||
|
||||
**Recommendation**:
|
||||
```tsx
|
||||
<!-- Updated component -->
|
||||
<h1 class="text-4xl font-heading tracking-tight">Welcome</h1>
|
||||
|
||||
<!-- tailwind.config.ts -->
|
||||
fontFamily: {
|
||||
sans: ['Space Grotesk', 'system-ui', 'sans-serif'], // Body
|
||||
heading: ['Archivo Black', 'system-ui', 'sans-serif'], // Headings
|
||||
mono: ['JetBrains Mono', 'monospace'] // Code
|
||||
}
|
||||
```
|
||||
|
||||
**Implementation**:
|
||||
1. Update `tailwind.config.ts` with custom fonts (5 min)
|
||||
2. Add font-heading class to all headings (10 min)
|
||||
3. Verify font loading in `app.config.ts` (5 min)
|
||||
**Total**: ~20 minutes
|
||||
|
||||
---
|
||||
|
||||
### 2. Purple Gradient Hero (Overused Pattern)
|
||||
|
||||
**Severity**: P1 - High Impact
|
||||
**Files Affected**: `app/components/Hero.tsx:8`
|
||||
**Impact**: "AI-generated" aesthetic, lacks brand identity
|
||||
|
||||
**Finding**: Hero section uses purple-500 to purple-600 gradient (appears in 60%+ of AI-generated sites)
|
||||
|
||||
**Current State**:
|
||||
```tsx
|
||||
<div class="bg-gradient-to-r from-purple-500 to-purple-600">
|
||||
<h1 class="text-white">Hero Title</h1>
|
||||
</div>
|
||||
```
|
||||
|
||||
**Recommendation**:
|
||||
```tsx
|
||||
<div class="relative overflow-hidden">
|
||||
<!-- Multi-layer atmospheric background -->
|
||||
<div class="absolute inset-0 bg-gradient-to-br from-brand-coral via-brand-ocean to-brand-sunset" />
|
||||
|
||||
<!-- Animated gradient orbs -->
|
||||
<div class="absolute top-0 left-0 w-96 h-96 bg-brand-coral/30 rounded-full blur-3xl animate-pulse" />
|
||||
<div class="absolute bottom-0 right-0 w-96 h-96 bg-brand-ocean/30 rounded-full blur-3xl animate-pulse" style="animation-delay: 1s;" />
|
||||
|
||||
<!-- Content -->
|
||||
<div class="relative z-10 py-24">
|
||||
<h1 class="text-white font-heading text-6xl tracking-tight">
|
||||
Hero Title
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- tailwind.config.ts: Add custom colors -->
|
||||
colors: {
|
||||
brand: {
|
||||
coral: '#FF6B6B',
|
||||
ocean: '#4ECDC4',
|
||||
sunset: '#FFE66D'
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Implementation**:
|
||||
1. Add brand colors to `tailwind.config.ts` (5 min)
|
||||
2. Update Hero component with atmospheric background (15 min)
|
||||
3. Test animations and responsiveness (5 min)
|
||||
**Total**: ~25 minutes
|
||||
|
||||
---
|
||||
|
||||
### 3. Button Components with Default Props (23 instances)
|
||||
|
||||
**Severity**: P1 - High Impact
|
||||
**Files Affected**: 8 components
|
||||
**Impact**: Generic appearance, no brand identity
|
||||
|
||||
**Finding**: 23 Button instances using default props only (no customization)
|
||||
|
||||
**Current State**:
|
||||
```tsx
|
||||
<!-- app/components/CallToAction.tsx:34 -->
|
||||
<Button onClick={handleClick">Click me</Button>
|
||||
```
|
||||
|
||||
**Recommendation**:
|
||||
```tsx
|
||||
<Button
|
||||
color="primary"
|
||||
size="lg"
|
||||
:ui="{
|
||||
font: 'font-heading tracking-wide',
|
||||
rounded: 'rounded-full',
|
||||
padding: { lg: 'px-8 py-4' },
|
||||
shadow: 'shadow-lg hover:shadow-xl'
|
||||
}"
|
||||
class="
|
||||
transition-all duration-300 ease-out
|
||||
hover:scale-105 hover:-rotate-1
|
||||
active:scale-95 active:rotate-0
|
||||
focus:outline-none
|
||||
focus-visible:ring-2 focus-visible:ring-primary-500 focus-visible:ring-offset-2
|
||||
"
|
||||
onClick={handleClick"
|
||||
>
|
||||
<span class="inline-flex items-center gap-2">
|
||||
Click me
|
||||
<Icon
|
||||
name="i-heroicons-sparkles"
|
||||
class="transition-transform duration-300 group-hover:rotate-12"
|
||||
/>
|
||||
</span>
|
||||
</Button>
|
||||
```
|
||||
|
||||
**Better Approach: Create Reusable Variants**:
|
||||
```tsx
|
||||
<!-- composables/useDesignSystem.ts -->
|
||||
export const useDesignSystem = () => {
|
||||
const button = {
|
||||
primary: {
|
||||
color: 'primary',
|
||||
size: 'lg',
|
||||
ui: {
|
||||
font: 'font-heading tracking-wide',
|
||||
rounded: 'rounded-full',
|
||||
padding: { lg: 'px-8 py-4' }
|
||||
},
|
||||
class: 'transition-all duration-300 hover:scale-105 hover:shadow-xl'
|
||||
}
|
||||
};
|
||||
|
||||
return { button };
|
||||
};
|
||||
|
||||
<!-- Usage in components -->
|
||||
const { button } = useDesignSystem();
|
||||
|
||||
<Button v-bind="button.primary" onClick={handleClick">
|
||||
Click me
|
||||
</Button>
|
||||
```
|
||||
|
||||
**Implementation**:
|
||||
1. Create `composables/useDesignSystem.ts` with button variants (15 min)
|
||||
2. Update all 23 button instances to use variants (30 min)
|
||||
3. Test all button interactions (10 min)
|
||||
**Total**: ~55 minutes
|
||||
|
||||
---
|
||||
|
||||
## Important Issues (P2)
|
||||
|
||||
### 4. Missing Hover Animations (32 interactive elements)
|
||||
|
||||
**Severity**: P2 - Medium Impact
|
||||
**Impact**: Flat UI, reduced engagement
|
||||
|
||||
**Finding**: 32 interactive elements (buttons, links, cards) without hover animations
|
||||
|
||||
**Recommendation**: Add transition utilities to all interactive elements
|
||||
```tsx
|
||||
<!-- Before -->
|
||||
<Card>Content</Card>
|
||||
|
||||
<!-- After -->
|
||||
<Card
|
||||
:ui="{ shadow: 'shadow-lg hover:shadow-2xl' }"
|
||||
class="transition-all duration-300 hover:-translate-y-1"
|
||||
>
|
||||
Content
|
||||
</Card>
|
||||
```
|
||||
|
||||
[Continue with remaining P2 issues...]
|
||||
|
||||
---
|
||||
|
||||
## Accessibility Violations (WCAG 2.1 AA)
|
||||
|
||||
### 5. Insufficient Color Contrast (4 instances)
|
||||
|
||||
**Severity**: P1 - Blocker
|
||||
**Standard**: WCAG 1.4.3 (4.5:1 for normal text, 3:1 for large text)
|
||||
|
||||
**Violations**:
|
||||
1. `app/components/Footer.tsx:23` - Gray-400 on white (2.9:1) ❌
|
||||
2. `app/routes/about.tsx:45` - Brand-coral on white (3.2:1) ❌
|
||||
3. `app/components/Badge.tsx:12` - Yellow-300 on white (1.8:1) ❌
|
||||
4. `layouts/default.tsx:67` - Blue-400 on gray-50 (2.4:1) ❌
|
||||
|
||||
**Fixes**: [Specific contrast-compliant color recommendations]
|
||||
|
||||
---
|
||||
|
||||
## Polish Opportunities (P3)
|
||||
|
||||
[List P3 improvements...]
|
||||
|
||||
---
|
||||
|
||||
## Implementation Roadmap
|
||||
|
||||
### Priority 1: Foundation (1-2 hours)
|
||||
1. ✅ Update `tailwind.config.ts` with custom fonts and colors
|
||||
2. ✅ Create `composables/useDesignSystem.ts` with reusable variants
|
||||
3. ✅ Fix critical accessibility violations (contrast)
|
||||
|
||||
### Priority 2: Component Updates (2-3 hours)
|
||||
4. ✅ Update all Button instances with design system variants
|
||||
5. ✅ Add hover animations to interactive elements
|
||||
6. ✅ Customize Card components with distinctive styling
|
||||
|
||||
### Priority 3: Polish (1-2 hours)
|
||||
7. ✅ Enhance micro-interactions
|
||||
8. ✅ Add staggered animations
|
||||
9. ✅ Implement dark mode refinements
|
||||
|
||||
**Total Time Estimate**: 4-7 hours for complete implementation
|
||||
|
||||
---
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. **Review Findings**: Team reviews this report
|
||||
2. **Prioritize Work**: Decide which issues to address
|
||||
3. **Use `/triage`**: Create todos for approved findings
|
||||
4. **Implement Changes**: Follow code examples provided
|
||||
5. **Re-run Review**: Verify improvements with `/es-design-review`
|
||||
|
||||
## Distinctiveness Score Projection
|
||||
|
||||
**Before**: 35/100 (Generic, AI-generated aesthetic)
|
||||
**After P1 Fixes**: 75/100 (Distinctive, branded)
|
||||
**After P1+P2 Fixes**: 90/100 (Excellent, highly polished)
|
||||
**After P1+P2+P3**: 95/100 (Outstanding, delightful)
|
||||
|
||||
</findings_format>
|
||||
|
||||
### 4. Create Triage-Ready Todos (Optional)
|
||||
|
||||
<thinking>
|
||||
If user wants to proceed with fixes, use /triage command to create actionable todos.
|
||||
Each todo should be specific, implementable, and include code examples.
|
||||
</thinking>
|
||||
|
||||
#### Generate Todos:
|
||||
|
||||
<todo_format>
|
||||
|
||||
For each P1 issue, create a todo in `.claude/todos/` with format:
|
||||
- `001-pending-p1-update-typography.md`
|
||||
- `002-pending-p1-fix-hero-gradient.md`
|
||||
- `003-pending-p1-customize-buttons.md`
|
||||
- etc.
|
||||
|
||||
Each todo includes:
|
||||
- **Title**: Clear, actionable
|
||||
- **Severity**: P1/P2/P3
|
||||
- **Files**: Specific file paths
|
||||
- **Current State**: Code before
|
||||
- **Target State**: Code after
|
||||
- **Implementation Steps**: Numbered checklist
|
||||
- **Time Estimate**: Minutes/hours
|
||||
|
||||
</todo_format>
|
||||
|
||||
Ask user: "Would you like me to create todos for these findings? You can then use `/triage` to work through them systematically."
|
||||
|
||||
## Success Criteria
|
||||
|
||||
✅ Design review complete when:
|
||||
- All Vue components analyzed
|
||||
- All generic patterns identified
|
||||
- All accessibility violations found
|
||||
- Findings categorized and prioritized
|
||||
- Implementation plan provided with time estimates
|
||||
- Code examples are complete and implementable
|
||||
|
||||
✅ Project ready for distinctive brand identity when:
|
||||
- 0% Inter/Roboto font usage
|
||||
- 0% purple gradient usage
|
||||
- 100% of shadcn/ui components deeply customized
|
||||
- 100% of interactive elements have animations
|
||||
- 100% WCAG 2.1 AA compliance
|
||||
- Distinctiveness score ≥ 85/100
|
||||
|
||||
## Post-Review Actions
|
||||
|
||||
After implementing fixes:
|
||||
1. **Re-run review**: `/es-design-review` to verify improvements
|
||||
2. **Validate code**: `/validate` to ensure no build/lint errors
|
||||
3. **Test manually**: Check hover states, animations, keyboard navigation
|
||||
4. **Deploy preview**: Test on actual Cloudflare Workers environment
|
||||
|
||||
## Resources
|
||||
|
||||
- Claude Skills Blog: Improving Frontend Design Through Skills
|
||||
- shadcn/ui Documentation: https://ui.shadcn.com
|
||||
- Tailwind 4 Documentation: https://tailwindcss.com/docs/v4-beta
|
||||
- WCAG 2.1 Guidelines: https://www.w3.org/WAI/WCAG21/quickref/
|
||||
- WebAIM Contrast Checker: https://webaim.org/resources/contrastchecker/
|
||||
|
||||
## Notes
|
||||
|
||||
- This command focuses on **frontend design**, not Cloudflare Workers runtime
|
||||
- Use `/review` for comprehensive code review (includes runtime, security, performance)
|
||||
- Use `/es-component` to scaffold new components with best practices
|
||||
- Use `/es-theme` to generate custom design themes
|
||||
1184
commands/es-email-setup.md
Normal file
1184
commands/es-email-setup.md
Normal file
File diff suppressed because it is too large
Load Diff
401
commands/es-issue.md
Normal file
401
commands/es-issue.md
Normal file
@@ -0,0 +1,401 @@
|
||||
---
|
||||
description: Create well-structured GitHub issues following project conventions
|
||||
---
|
||||
|
||||
# Create GitHub Issue
|
||||
|
||||
## Introduction
|
||||
|
||||
Transform feature descriptions, bug reports, or improvement ideas into well-structured markdown files issues that follow project conventions and best practices. This command provides flexible detail levels to match your needs.
|
||||
|
||||
## Feature Description
|
||||
|
||||
<feature_description> #$ARGUMENTS </feature_description>
|
||||
|
||||
## Main Tasks
|
||||
|
||||
### 1. Cloudflare Context & Binding Analysis
|
||||
|
||||
<thinking>
|
||||
First, I need to understand the Cloudflare Workers project structure, available bindings, and existing patterns. This informs architectural decisions and implementation approaches.
|
||||
</thinking>
|
||||
|
||||
**CRITICAL FIRST STEP**: Verify this is a Cloudflare Workers project:
|
||||
- Check for `wrangler.toml` file
|
||||
- If not found, warn user and ask if they want to create a new Workers project
|
||||
|
||||
Run these agents in parallel:
|
||||
|
||||
**Phase 1: Cloudflare-Specific Context (Priority)**
|
||||
|
||||
- Task binding-context-analyzer(feature_description)
|
||||
- Parse wrangler.toml for existing bindings (KV, R2, D1, DO)
|
||||
- Generate current Env interface
|
||||
- Identify available resources for reuse
|
||||
- Provide context to other agents
|
||||
|
||||
- Task cloudflare-architecture-strategist(feature_description)
|
||||
- Analyze Workers/DO/KV/R2 architecture patterns
|
||||
- Recommend storage choices based on feature requirements
|
||||
- Consider edge-first design principles
|
||||
|
||||
**Phase 2: General Research (Parallel)**
|
||||
|
||||
- Task repo-research-analyst(feature_description)
|
||||
- Research existing Workers patterns in codebase
|
||||
- Identify Cloudflare-specific conventions
|
||||
- Document Workers entry points and routing patterns
|
||||
|
||||
**Reference Collection:**
|
||||
|
||||
- [ ] Document all research findings with specific file paths (e.g., `src/index.ts:42`)
|
||||
- [ ] List existing bindings from wrangler.toml with IDs and types
|
||||
- [ ] Include URLs to Cloudflare documentation and best practices
|
||||
- [ ] Create a reference list of similar Workers implementations or PRs
|
||||
- [ ] Note any Cloudflare-specific conventions discovered in documentation
|
||||
- [ ] Document user preferences from PREFERENCES.md (Tanstack Start, Hono, Vercel AI SDK)
|
||||
|
||||
### 2. Issue Planning & Structure
|
||||
|
||||
<thinking>
|
||||
Think like a product manager - what would make this issue clear and actionable? Consider multiple perspectives
|
||||
</thinking>
|
||||
|
||||
**Title & Categorization:**
|
||||
|
||||
- [ ] Draft clear, searchable issue title using conventional format (e.g., `feat:`, `fix:`, `docs:`)
|
||||
- [ ] Identify appropriate labels from repository's label set (`gh label list`)
|
||||
- [ ] Determine issue type: enhancement, bug, refactor
|
||||
|
||||
**Stakeholder Analysis:**
|
||||
|
||||
- [ ] Identify who will be affected by this issue (end users, developers, operations)
|
||||
- [ ] Consider implementation complexity and required expertise
|
||||
|
||||
**Content Planning:**
|
||||
|
||||
- [ ] Choose appropriate detail level based on issue complexity and audience
|
||||
- [ ] List all necessary sections for the chosen template
|
||||
- [ ] Gather supporting materials (error logs, screenshots, design mockups)
|
||||
- [ ] Prepare code examples or reproduction steps if applicable, name the mock filenames in the lists
|
||||
|
||||
### 3. Choose Implementation Detail Level
|
||||
|
||||
Select how comprehensive you want the issue to be:
|
||||
|
||||
#### 📄 MINIMAL (Quick Issue)
|
||||
|
||||
**Best for:** Simple bugs, small improvements, clear features
|
||||
|
||||
**Includes:**
|
||||
|
||||
- Problem statement or feature description
|
||||
- Basic acceptance criteria
|
||||
- Essential context only
|
||||
|
||||
**Structure:**
|
||||
|
||||
````markdown
|
||||
[Brief problem/feature description]
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [ ] Core requirement 1
|
||||
- [ ] Core requirement 2
|
||||
|
||||
## Context
|
||||
|
||||
[Any critical information]
|
||||
|
||||
## MVP
|
||||
|
||||
### src/worker.ts
|
||||
|
||||
```typescript
|
||||
export default {
|
||||
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
|
||||
// Minimal implementation
|
||||
return new Response('Hello World');
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
### wrangler.toml
|
||||
|
||||
```toml
|
||||
name = "feature-name"
|
||||
main = "src/index.ts"
|
||||
compatibility_date = "2025-09-15" # Always use 2025-09-15 or later
|
||||
|
||||
# Example: KV namespace with remote binding
|
||||
[[kv_namespaces]]
|
||||
binding = "CACHE"
|
||||
id = "your-kv-namespace-id"
|
||||
remote = true # Connect to real KV during development
|
||||
```
|
||||
|
||||
## References
|
||||
|
||||
- Related issue: #[issue_number]
|
||||
- Cloudflare Docs: [relevant_docs_url]
|
||||
- Existing bindings: [from binding-context-analyzer]
|
||||
````
|
||||
|
||||
#### 📋 MORE (Standard Issue)
|
||||
|
||||
**Best for:** Most features, complex bugs, team collaboration
|
||||
|
||||
**Includes everything from MINIMAL plus:**
|
||||
|
||||
- Detailed background and motivation
|
||||
- Technical considerations
|
||||
- Success metrics
|
||||
- Dependencies and risks
|
||||
- Basic implementation suggestions
|
||||
|
||||
**Structure:**
|
||||
|
||||
```markdown
|
||||
## Overview
|
||||
|
||||
[Comprehensive description]
|
||||
|
||||
## Problem Statement / Motivation
|
||||
|
||||
[Why this matters]
|
||||
|
||||
## Proposed Solution
|
||||
|
||||
[High-level approach]
|
||||
|
||||
## Technical Considerations
|
||||
|
||||
- Architecture impacts
|
||||
- Performance implications
|
||||
- Security considerations
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [ ] Detailed requirement 1
|
||||
- [ ] Detailed requirement 2
|
||||
- [ ] Testing requirements
|
||||
|
||||
## Success Metrics
|
||||
|
||||
[How we measure success]
|
||||
|
||||
## Dependencies & Risks
|
||||
|
||||
[What could block or complicate this]
|
||||
|
||||
## References & Research
|
||||
|
||||
- Similar implementations: [file_path:line_number]
|
||||
- Best practices: [documentation_url]
|
||||
- Related PRs: #[pr_number]
|
||||
```
|
||||
|
||||
#### 📚 A LOT (Comprehensive Issue)
|
||||
|
||||
**Best for:** Major features, architectural changes, complex integrations
|
||||
|
||||
**Includes everything from MORE plus:**
|
||||
|
||||
- Detailed implementation plan with phases
|
||||
- Alternative approaches considered
|
||||
- Extensive technical specifications
|
||||
- Resource requirements and timeline
|
||||
- Future considerations and extensibility
|
||||
- Risk mitigation strategies
|
||||
- Documentation requirements
|
||||
|
||||
**Structure:**
|
||||
|
||||
```markdown
|
||||
## Overview
|
||||
|
||||
[Executive summary]
|
||||
|
||||
## Problem Statement
|
||||
|
||||
[Detailed problem analysis]
|
||||
|
||||
## Proposed Solution
|
||||
|
||||
[Comprehensive solution design]
|
||||
|
||||
## Technical Approach
|
||||
|
||||
### Architecture
|
||||
|
||||
[Detailed technical design]
|
||||
|
||||
### Implementation Phases
|
||||
|
||||
#### Phase 1: [Foundation]
|
||||
|
||||
- Tasks and deliverables
|
||||
- Success criteria
|
||||
- Estimated effort
|
||||
|
||||
#### Phase 2: [Core Implementation]
|
||||
|
||||
- Tasks and deliverables
|
||||
- Success criteria
|
||||
- Estimated effort
|
||||
|
||||
#### Phase 3: [Polish & Optimization]
|
||||
|
||||
- Tasks and deliverables
|
||||
- Success criteria
|
||||
- Estimated effort
|
||||
|
||||
## Alternative Approaches Considered
|
||||
|
||||
[Other solutions evaluated and why rejected]
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
### Functional Requirements
|
||||
|
||||
- [ ] Detailed functional criteria
|
||||
|
||||
### Non-Functional Requirements
|
||||
|
||||
- [ ] Performance targets
|
||||
- [ ] Security requirements
|
||||
- [ ] Accessibility standards
|
||||
|
||||
### Quality Gates
|
||||
|
||||
- [ ] Test coverage requirements
|
||||
- [ ] Documentation completeness
|
||||
- [ ] Code review approval
|
||||
|
||||
## Success Metrics
|
||||
|
||||
[Detailed KPIs and measurement methods]
|
||||
|
||||
## Dependencies & Prerequisites
|
||||
|
||||
[Detailed dependency analysis]
|
||||
|
||||
## Risk Analysis & Mitigation
|
||||
|
||||
[Comprehensive risk assessment]
|
||||
|
||||
## Resource Requirements
|
||||
|
||||
[Team, time, infrastructure needs]
|
||||
|
||||
## Future Considerations
|
||||
|
||||
[Extensibility and long-term vision]
|
||||
|
||||
## Documentation Plan
|
||||
|
||||
[What docs need updating]
|
||||
|
||||
## References & Research
|
||||
|
||||
### Internal References
|
||||
|
||||
- Architecture decisions: [file_path:line_number]
|
||||
- Similar features: [file_path:line_number]
|
||||
- Configuration: [file_path:line_number]
|
||||
|
||||
### External References
|
||||
|
||||
- Framework documentation: [url]
|
||||
- Best practices guide: [url]
|
||||
- Industry standards: [url]
|
||||
|
||||
### Related Work
|
||||
|
||||
- Previous PRs: #[pr_numbers]
|
||||
- Related issues: #[issue_numbers]
|
||||
- Design documents: [links]
|
||||
```
|
||||
|
||||
### 4. Issue Creation & Formatting
|
||||
|
||||
<thinking>
|
||||
Apply best practices for clarity and actionability, making the issue easy to scan and understand
|
||||
</thinking>
|
||||
|
||||
**Content Formatting:**
|
||||
|
||||
- [ ] Use clear, descriptive headings with proper hierarchy (##, ###)
|
||||
- [ ] Include code examples in triple backticks with language syntax highlighting
|
||||
- [ ] Add screenshots/mockups if UI-related (drag & drop or use image hosting)
|
||||
- [ ] Use task lists (- [ ]) for trackable items that can be checked off
|
||||
- [ ] Add collapsible sections for lengthy logs or optional details using `<details>` tags
|
||||
- [ ] Apply appropriate emoji for visual scanning (🐛 bug, ✨ feature, 📚 docs, ♻️ refactor)
|
||||
|
||||
**Cross-Referencing:**
|
||||
|
||||
- [ ] Link to related issues/PRs using #number format
|
||||
- [ ] Reference specific commits with SHA hashes when relevant
|
||||
- [ ] Link to code using GitHub's permalink feature (press 'y' for permanent link)
|
||||
- [ ] Mention relevant team members with @username if needed
|
||||
- [ ] Add links to external resources with descriptive text
|
||||
|
||||
**Code & Examples:**
|
||||
|
||||
```markdown
|
||||
# Good example with syntax highlighting and line references
|
||||
|
||||
\`\`\`ruby
|
||||
|
||||
# app/services/user_service.rb:42
|
||||
|
||||
def process_user(user)
|
||||
|
||||
# Implementation here
|
||||
|
||||
end \`\`\`
|
||||
|
||||
# Collapsible error logs
|
||||
|
||||
<details>
|
||||
<summary>Full error stacktrace</summary>
|
||||
|
||||
\`\`\` Error details here... \`\`\`
|
||||
|
||||
</details>
|
||||
```
|
||||
|
||||
**AI-Era Considerations:**
|
||||
|
||||
- [ ] Account for accelerated development with AI pair programming
|
||||
- [ ] Include prompts or instructions that worked well during research
|
||||
- [ ] Note which AI tools were used for initial exploration (Claude, Copilot, etc.)
|
||||
- [ ] Emphasize comprehensive testing given rapid implementation
|
||||
- [ ] Document any AI-generated code that needs human review
|
||||
|
||||
### 5. Final Review & Submission
|
||||
|
||||
**Pre-submission Checklist:**
|
||||
|
||||
- [ ] Title is searchable and descriptive
|
||||
- [ ] Labels accurately categorize the issue
|
||||
- [ ] All template sections are complete
|
||||
- [ ] Links and references are working
|
||||
- [ ] Acceptance criteria are measurable
|
||||
- [ ] Add names of files in pseudo code examples and todo lists
|
||||
- [ ] Add an ERD mermaid diagram if applicable for new model changes
|
||||
|
||||
## Output Format
|
||||
|
||||
Present the complete issue content within `<github_issue>` tags, ready for GitHub CLI:
|
||||
|
||||
```bash
|
||||
gh issue create --title "[TITLE]" --body "[CONTENT]" --label "[LABELS]"
|
||||
```
|
||||
|
||||
## Thinking Approaches
|
||||
|
||||
- **Analytical:** Break down complex features into manageable components
|
||||
- **User-Centric:** Consider end-user impact and experience
|
||||
- **Technical:** Evaluate implementation complexity and architecture fit
|
||||
- **Strategic:** Align with project goals and roadmap
|
||||
1007
commands/es-migrate.md
Normal file
1007
commands/es-migrate.md
Normal file
File diff suppressed because it is too large
Load Diff
91
commands/es-plan.md
Normal file
91
commands/es-plan.md
Normal file
@@ -0,0 +1,91 @@
|
||||
---
|
||||
description: Plan Cloudflare Workers projects with architectural guidance
|
||||
---
|
||||
|
||||
You are a **Senior Software Architect and Product Manager at Cloudflare**. Your expertise is in designing serverless applications on the Cloudflare Developer Platform.
|
||||
|
||||
## Your Environment
|
||||
|
||||
All projects MUST be built on **serverless Cloudflare Workers** and supporting technologies:
|
||||
- **Workers**: Serverless JavaScript/TypeScript execution
|
||||
- **Durable Objects**: Stateful serverless objects with strong consistency
|
||||
- **KV**: Low-latency key-value storage
|
||||
- **R2**: S3-compatible object storage
|
||||
- **D1**: SQLite database at the edge
|
||||
- **Queues**: Message queues for async processing
|
||||
- **Vectorize**: Vector database for embeddings
|
||||
- **AI**: Inference API for AI models
|
||||
|
||||
## Your Task
|
||||
|
||||
Help the user plan a new feature or application by:
|
||||
|
||||
1. **Understanding the Requirements**
|
||||
- Ask clarifying questions to understand the user's goals
|
||||
- Identify the core functionality needed
|
||||
- Understand scale requirements and constraints
|
||||
- Determine what existing infrastructure they have (if any)
|
||||
|
||||
2. **Architecture Design**
|
||||
- Provide a high-level architectural plan
|
||||
- Identify the necessary Cloudflare resources
|
||||
- Example: "You will need one Worker for the API, a KV namespace for caching, an R2 bucket for file storage, and a Durable Object for real-time collaboration state"
|
||||
- Consider data flow and integration points
|
||||
|
||||
3. **File Structure Planning**
|
||||
- Define the main Worker and Durable Object files needed
|
||||
- Outline their core responsibilities
|
||||
- Suggest how they should interact
|
||||
- Example:
|
||||
```
|
||||
src/
|
||||
index.ts # Main Worker: handles HTTP routing
|
||||
auth.ts # Authentication logic
|
||||
storage.ts # R2 and KV operations
|
||||
objects/
|
||||
Counter.ts # Durable Object: maintains counters
|
||||
Session.ts # Durable Object: user sessions
|
||||
```
|
||||
|
||||
4. **Configuration Planning**
|
||||
- List the bindings that will be needed in wrangler.toml
|
||||
- Specify environment variables
|
||||
- Note any secrets that need to be configured
|
||||
|
||||
5. **Implementation Roadmap**
|
||||
- Provide a step-by-step implementation plan
|
||||
- Prioritize what to build first
|
||||
- Suggest testing strategies
|
||||
|
||||
## Critical Guardrails
|
||||
|
||||
**YOU MUST NOT:**
|
||||
- Write implementation code (your deliverable is a plan, not a codebase)
|
||||
- Suggest using Node.js-specific APIs (like `fs`, `path`, `process.env`)
|
||||
- Recommend non-Cloudflare solutions (no Express, no traditional servers)
|
||||
- Propose changes to wrangler.toml or package.json directly
|
||||
|
||||
**YOU MUST:**
|
||||
- Think in terms of serverless, edge-first architecture
|
||||
- Use Workers runtime APIs (fetch, Response, Request, etc.)
|
||||
- Respect the Workers execution model (fast cold starts, no persistent connections)
|
||||
- Consider geographic distribution and edge caching
|
||||
|
||||
## Response Format
|
||||
|
||||
Provide your plan in clear sections:
|
||||
1. **Project Overview**: Brief description of what will be built
|
||||
2. **Architecture**: High-level design with Cloudflare services
|
||||
3. **File Structure**: Proposed directory layout with responsibilities
|
||||
4. **Bindings Required**: List of wrangler.toml bindings needed
|
||||
5. **Implementation Steps**: Ordered roadmap for development
|
||||
6. **Testing Strategy**: How to validate the implementation
|
||||
7. **Deployment Considerations**: Production readiness checklist
|
||||
|
||||
Keep your plan concise but comprehensive. Focus on the "what" and "why" rather than the "how" (save implementation details for later).
|
||||
|
||||
---
|
||||
|
||||
**User's Request:**
|
||||
|
||||
{{PROMPT}}
|
||||
67
commands/es-resolve-parallel.md
Normal file
67
commands/es-resolve-parallel.md
Normal file
@@ -0,0 +1,67 @@
|
||||
---
|
||||
description: Resolve all TODOs and GitHub issues using parallel processing with multiple agents
|
||||
---
|
||||
|
||||
Resolve all TODO files and GitHub issues using parallel processing.
|
||||
|
||||
## Workflow
|
||||
|
||||
### 1. Analyze
|
||||
|
||||
Get all unresolved items from multiple sources:
|
||||
|
||||
**TODO Files:**
|
||||
- Get all unresolved TODOs from the `/todos/*.md` directory
|
||||
|
||||
**GitHub Issues:**
|
||||
- Fetch open GitHub issues via `gh issue list --json number,title,labels,body,url`
|
||||
- Parse and extract actionable items from issues
|
||||
|
||||
### 2. Plan
|
||||
|
||||
Create a TodoWrite list of all unresolved items grouped by source (TODO files vs GitHub issues) and type.
|
||||
|
||||
**Dependency Analysis:**
|
||||
- Look at dependencies that might occur and prioritize the ones needed by others
|
||||
- For example, if you need to change a name, you must wait to do the others
|
||||
- Consider cross-dependencies between file TODOs and GitHub issues
|
||||
|
||||
**Visualization:**
|
||||
- Output a mermaid flow diagram showing the resolution flow
|
||||
- Can we do everything in parallel? Do we need to do one first that leads to others in parallel?
|
||||
- Put the items in the mermaid diagram flow-wise so the agent knows how to proceed in order
|
||||
|
||||
### 3. Implement (PARALLEL)
|
||||
|
||||
Spawn appropriate agents for each unresolved item in parallel, using the right agent type for each source:
|
||||
|
||||
**For TODO files:**
|
||||
- Spawn a pr-comment-resolver agent for each unresolved TODO item
|
||||
|
||||
**For GitHub issues:**
|
||||
- Spawn a general-purpose agent for each issue
|
||||
- Pass issue number, title, and body to the agent
|
||||
|
||||
**Example:**
|
||||
If there are 2 TODO items and 3 GitHub issues, spawn 5 agents in parallel:
|
||||
|
||||
1. Task pr-comment-resolver(todo1)
|
||||
2. Task pr-comment-resolver(todo2)
|
||||
3. Task general-purpose(issue1)
|
||||
4. Task general-purpose(issue2)
|
||||
5. Task general-purpose(issue3)
|
||||
|
||||
Always run all in parallel subagents/Tasks for each item (respecting dependencies from Step 2).
|
||||
|
||||
### 4. Commit & Resolve
|
||||
|
||||
**For TODO files:**
|
||||
- Remove the TODO from the file and mark it as resolved
|
||||
|
||||
**For GitHub issues:**
|
||||
- Close the issue via `gh issue close <number> --comment "Resolved in commit <sha>"`
|
||||
- Reference the commit that resolves the issue
|
||||
|
||||
**Final steps:**
|
||||
- Commit all changes with descriptive message
|
||||
- Push to remote repository
|
||||
546
commands/es-review.md
Normal file
546
commands/es-review.md
Normal file
@@ -0,0 +1,546 @@
|
||||
---
|
||||
description: Perform exhaustive code reviews using multi-agent analysis and Git worktrees
|
||||
---
|
||||
|
||||
# Review Command
|
||||
|
||||
<command_purpose> Perform exhaustive code reviews using multi-agent analysis, ultra-thinking, and Git worktrees for deep local inspection. </command_purpose>
|
||||
|
||||
## Introduction
|
||||
|
||||
<role>Senior Code Review Architect with expertise in security, performance, architecture, and quality assurance</role>
|
||||
|
||||
## Prerequisites
|
||||
|
||||
<requirements>
|
||||
- Git repository with GitHub CLI (`gh`) installed and authenticated
|
||||
- Clean main/master branch
|
||||
- Proper permissions to create worktrees and access the repository
|
||||
- For document reviews: Path to a markdown file or document
|
||||
</requirements>
|
||||
|
||||
## Main Tasks
|
||||
|
||||
### 1. Worktree Creation and Branch Checkout (ALWAYS FIRST)
|
||||
|
||||
<review_target> #$ARGUMENTS </review_target>
|
||||
|
||||
<critical_requirement> MUST create worktree FIRST to enable local code analysis. No exceptions. </critical_requirement>
|
||||
|
||||
<thinking>
|
||||
First, I need to determine the review target type and set up the worktree.
|
||||
This enables all subsequent agents to analyze actual code, not just diffs.
|
||||
</thinking>
|
||||
|
||||
#### Immediate Actions:
|
||||
|
||||
<task_list>
|
||||
|
||||
- [ ] Determine review type: PR number (numeric), GitHub URL, file path (.md), or empty (latest PR)
|
||||
- [ ] Create worktree directory structure at `$git_root/.worktrees/reviews/pr-$identifier`
|
||||
- [ ] Check out PR branch in isolated worktree using `gh pr checkout`
|
||||
- [ ] Navigate to worktree - ALL subsequent analysis happens here
|
||||
|
||||
- Fetch PR metadata using `gh pr view --json` for title, body, files, linked issues
|
||||
- Clone PR branch into worktree with full history `gh pr checkout $identifier`
|
||||
- Set up language-specific analysis tools
|
||||
- Prepare security scanning environment
|
||||
|
||||
Ensure that the worktree is set up correctly and that the PR is checked out. ONLY then proceed to the next step.
|
||||
|
||||
</task_list>
|
||||
|
||||
#### Verify Cloudflare Workers Project
|
||||
|
||||
<thinking>
|
||||
Confirm this is a Cloudflare Workers project by checking for wrangler.toml.
|
||||
All Cloudflare-specific agents will be used regardless of language (TypeScript/JavaScript).
|
||||
</thinking>
|
||||
|
||||
<project_verification>
|
||||
|
||||
Check for Cloudflare Workers indicators:
|
||||
|
||||
**Required**:
|
||||
- `wrangler.toml` - Cloudflare Workers configuration
|
||||
|
||||
**Common**:
|
||||
- `package.json` with `wrangler` dependency
|
||||
- TypeScript/JavaScript files (`.ts`, `.js`)
|
||||
- Worker entry point (typically `src/index.ts` or `src/worker.ts`)
|
||||
|
||||
If not a Cloudflare Workers project, warn user and ask to confirm.
|
||||
|
||||
</project_verification>
|
||||
|
||||
#### Parallel Agents to review the PR:
|
||||
|
||||
<parallel_tasks>
|
||||
|
||||
Run ALL these agents in parallel. Cloudflare Workers projects are primarily TypeScript/JavaScript with edge-specific concerns.
|
||||
|
||||
**Phase 1: Context Gathering (3 agents in parallel)**
|
||||
|
||||
1. Task binding-context-analyzer(PR content)
|
||||
- Parse wrangler.toml for bindings
|
||||
- Generate TypeScript Env interface
|
||||
- Provide context to other agents
|
||||
|
||||
2. Task git-history-analyzer(PR content)
|
||||
- Analyze commit history and patterns
|
||||
- Identify code evolution
|
||||
|
||||
3. Task repo-research-analyst(PR content)
|
||||
- Research codebase patterns
|
||||
- Document conventions
|
||||
|
||||
**Phase 2: Cloudflare-Specific Review (5 agents in parallel)**
|
||||
|
||||
4. Task workers-runtime-guardian(PR content)
|
||||
- Runtime compatibility (V8, not Node.js)
|
||||
- Detect forbidden APIs (fs, process, Buffer)
|
||||
- Validate env parameter patterns
|
||||
|
||||
5. Task durable-objects-architect(PR content)
|
||||
- DO lifecycle and state management
|
||||
- Hibernation patterns
|
||||
- WebSocket handling
|
||||
|
||||
6. Task cloudflare-security-sentinel(PR content)
|
||||
- Workers security model
|
||||
- Secret management (wrangler secret)
|
||||
- CORS, CSP, auth patterns
|
||||
|
||||
7. Task edge-performance-oracle(PR content)
|
||||
- Cold start optimization
|
||||
- Bundle size analysis
|
||||
- Edge caching strategies
|
||||
|
||||
8. Task cloudflare-pattern-specialist(PR content)
|
||||
- Cloudflare-specific patterns
|
||||
- Anti-patterns (stateful Workers, KV for strong consistency)
|
||||
- Idiomatic Cloudflare code
|
||||
|
||||
**Phase 2.5: Frontend Design Review (3 agents in parallel - if shadcn/ui components detected)**
|
||||
|
||||
If the PR includes React components with shadcn/ui:
|
||||
|
||||
9a. Task frontend-design-specialist(PR content)
|
||||
- Identify generic patterns (Inter fonts, purple gradients, minimal animations)
|
||||
- Map aesthetic improvements to Tailwind/shadcn/ui code
|
||||
- Prioritize distinctiveness opportunities
|
||||
- Ensure brand identity vs generic "AI aesthetic"
|
||||
|
||||
9b. Task shadcn-ui-architect(PR content)
|
||||
- Validate shadcn/ui component usage and props (via MCP if available)
|
||||
- Check customization depth (`ui` prop usage)
|
||||
- Ensure consistent component patterns
|
||||
- Prevent prop hallucination
|
||||
|
||||
9c. Task accessibility-guardian(PR content)
|
||||
- WCAG 2.1 AA compliance validation
|
||||
- Color contrast checking
|
||||
- Keyboard navigation validation
|
||||
- Screen reader support
|
||||
- Ensure distinctive design remains accessible
|
||||
|
||||
**Phase 3: Architecture & Data (5 agents in parallel)**
|
||||
|
||||
9. Task cloudflare-architecture-strategist(PR content)
|
||||
- Workers/DO/KV/R2 architecture
|
||||
- Service binding strategies
|
||||
- Edge-first design
|
||||
|
||||
10. Task cloudflare-data-guardian(PR content)
|
||||
- KV/D1/R2 data integrity
|
||||
- Consistency models
|
||||
- Storage selection
|
||||
|
||||
11. Task kv-optimization-specialist(PR content)
|
||||
- TTL strategies
|
||||
- Key naming patterns
|
||||
- Batch operations
|
||||
|
||||
12. Task r2-storage-architect(PR content)
|
||||
- Upload patterns (multipart, streaming)
|
||||
- CDN integration
|
||||
- Lifecycle management
|
||||
|
||||
13. Task edge-caching-optimizer(PR content)
|
||||
- Cache hierarchies
|
||||
- Invalidation strategies
|
||||
- Performance optimization
|
||||
|
||||
**Phase 4: Specialized (3 agents in parallel)**
|
||||
|
||||
14. Task workers-ai-specialist(PR content)
|
||||
- Vercel AI SDK patterns
|
||||
- Cloudflare AI Agents
|
||||
- RAG implementations
|
||||
|
||||
15. Task code-simplicity-reviewer(PR content)
|
||||
- YAGNI enforcement
|
||||
- Complexity reduction
|
||||
- Minimalism review
|
||||
|
||||
16. Task feedback-codifier(PR content)
|
||||
- Extract patterns from review
|
||||
- Update agent knowledge
|
||||
- Self-improvement loop
|
||||
|
||||
</parallel_tasks>
|
||||
|
||||
### 4. Ultra-Thinking Deep Dive Phases
|
||||
|
||||
<ultrathink_instruction> For each phase below, spend maximum cognitive effort. Think step by step. Consider all angles. Question assumptions. And bring all reviews in a synthesis to the user.</ultrathink_instruction>
|
||||
|
||||
<deliverable>
|
||||
Complete system context map with component interactions
|
||||
</deliverable>
|
||||
|
||||
#### Phase 3: Stakeholder Perspective Analysis
|
||||
|
||||
<thinking_prompt> ULTRA-THINK: Put yourself in each stakeholder's shoes. What matters to them? What are their pain points? </thinking_prompt>
|
||||
|
||||
<stakeholder_perspectives>
|
||||
|
||||
1. **Developer Perspective** <questions>
|
||||
|
||||
- How easy is this to understand and modify?
|
||||
- Are the APIs intuitive?
|
||||
- Is debugging straightforward?
|
||||
- Can I test this easily? </questions>
|
||||
|
||||
2. **Operations Perspective** <questions>
|
||||
|
||||
- How do I deploy this safely?
|
||||
- What metrics and logs are available?
|
||||
- How do I troubleshoot issues?
|
||||
- What are the resource requirements? </questions>
|
||||
|
||||
3. **End User Perspective** <questions>
|
||||
|
||||
- Is the feature intuitive?
|
||||
- Are error messages helpful?
|
||||
- Is performance acceptable?
|
||||
- Does it solve my problem? </questions>
|
||||
|
||||
4. **Security Team Perspective** <questions>
|
||||
|
||||
- What's the attack surface?
|
||||
- Are there compliance requirements?
|
||||
- How is data protected?
|
||||
- What are the audit capabilities? </questions>
|
||||
|
||||
5. **Business Perspective** <questions>
|
||||
- What's the ROI?
|
||||
- Are there legal/compliance risks?
|
||||
- How does this affect time-to-market?
|
||||
- What's the total cost of ownership? </questions> </stakeholder_perspectives>
|
||||
|
||||
#### Phase 4: Scenario Exploration
|
||||
|
||||
<thinking_prompt> ULTRA-THINK: Explore edge cases and failure scenarios. What could go wrong? How does the system behave under stress? </thinking_prompt>
|
||||
|
||||
<scenario_checklist>
|
||||
|
||||
- [ ] **Happy Path**: Normal operation with valid inputs
|
||||
- [ ] **Invalid Inputs**: Null, empty, malformed data
|
||||
- [ ] **Boundary Conditions**: Min/max values, empty collections
|
||||
- [ ] **Concurrent Access**: Race conditions, deadlocks
|
||||
- [ ] **Scale Testing**: 10x, 100x, 1000x normal load
|
||||
- [ ] **Network Issues**: Timeouts, partial failures
|
||||
- [ ] **Resource Exhaustion**: Memory, disk, connections
|
||||
- [ ] **Security Attacks**: Injection, overflow, DoS
|
||||
- [ ] **Data Corruption**: Partial writes, inconsistency
|
||||
- [ ] **Cascading Failures**: Downstream service issues </scenario_checklist>
|
||||
|
||||
### 6. Multi-Angle Review Perspectives
|
||||
|
||||
#### Technical Excellence Angle
|
||||
|
||||
- Code craftsmanship evaluation
|
||||
- Engineering best practices
|
||||
- Technical documentation quality
|
||||
- Tooling and automation assessment
|
||||
|
||||
#### Business Value Angle
|
||||
|
||||
- Feature completeness validation
|
||||
- Performance impact on users
|
||||
- Cost-benefit analysis
|
||||
- Time-to-market considerations
|
||||
|
||||
#### Risk Management Angle
|
||||
|
||||
- Security risk assessment
|
||||
- Operational risk evaluation
|
||||
- Compliance risk verification
|
||||
- Technical debt accumulation
|
||||
|
||||
#### Team Dynamics Angle
|
||||
|
||||
- Code review etiquette
|
||||
- Knowledge sharing effectiveness
|
||||
- Collaboration patterns
|
||||
- Mentoring opportunities
|
||||
|
||||
### 4. Simplification and Minimalism Review
|
||||
|
||||
Run the Task code-simplicity-reviewer() to see if we can simplify the code.
|
||||
|
||||
### 5. Findings Synthesis and Todo Creation
|
||||
|
||||
<critical_requirement> All findings MUST be converted to actionable todos in the CLI todo system </critical_requirement>
|
||||
|
||||
#### Step 1: Synthesize All Findings
|
||||
|
||||
<thinking>
|
||||
Consolidate all agent reports into a categorized list of findings.
|
||||
Remove duplicates, prioritize by severity and impact.
|
||||
Apply confidence scoring to filter false positives.
|
||||
</thinking>
|
||||
|
||||
<synthesis_tasks>
|
||||
- [ ] Collect findings from all parallel agents
|
||||
- [ ] Categorize by type: security, performance, architecture, quality, etc.
|
||||
- [ ] **Apply confidence scoring (0-100) to each finding**
|
||||
- [ ] **Filter out findings below 80 confidence threshold**
|
||||
- [ ] Assign severity levels: 🔴 CRITICAL (P1), 🟡 IMPORTANT (P2), 🔵 NICE-TO-HAVE (P3)
|
||||
- [ ] Remove duplicate or overlapping findings
|
||||
- [ ] Estimate effort for each finding (Small/Medium/Large)
|
||||
</synthesis_tasks>
|
||||
|
||||
#### Confidence Scoring System (Adopted from Anthropic's code-review plugin)
|
||||
|
||||
Each finding receives an independent confidence score:
|
||||
|
||||
| Score | Meaning | Action |
|
||||
|-------|---------|--------|
|
||||
| **0-25** | Not confident; likely false positive | Auto-filter (don't show) |
|
||||
| **26-50** | Somewhat confident; might be valid | Auto-filter (don't show) |
|
||||
| **51-79** | Moderately confident; real but uncertain | Auto-filter (don't show) |
|
||||
| **80-89** | Highly confident; real and important | ✅ Show to user |
|
||||
| **90-100** | Absolutely certain; definitely real | ✅ Show to user (prioritize) |
|
||||
|
||||
**Confidence Threshold: 80** - Only findings scoring 80+ are surfaced to the user.
|
||||
|
||||
<confidence_criteria>
|
||||
When scoring a finding, consider:
|
||||
|
||||
1. **Evidence Quality** (+20 points each):
|
||||
- [ ] Specific file and line number identified
|
||||
- [ ] Code snippet demonstrates the issue
|
||||
- [ ] Issue is in changed code (not pre-existing)
|
||||
- [ ] Clear violation of documented standard
|
||||
|
||||
2. **False Positive Indicators** (-20 points each):
|
||||
- [ ] Issue exists in unchanged code
|
||||
- [ ] Would be caught by linter/type checker
|
||||
- [ ] Has explicit ignore comment
|
||||
- [ ] Is a style preference, not a bug
|
||||
|
||||
3. **Verification** (+10 points each):
|
||||
- [ ] Multiple agents flagged same issue
|
||||
- [ ] CLAUDE.md or PREFERENCES.md mentions this pattern
|
||||
- [ ] Issue matches known Cloudflare anti-pattern
|
||||
|
||||
Example scoring:
|
||||
```
|
||||
Finding: Using process.env in Worker
|
||||
- Specific location: src/index.ts:45 (+20)
|
||||
- Code snippet shows violation (+20)
|
||||
- In changed code (+20)
|
||||
- Violates Workers runtime rules (+20)
|
||||
- Multiple agents flagged (+10)
|
||||
= 90 confidence ✅ SHOW
|
||||
```
|
||||
|
||||
```
|
||||
Finding: Consider adding more comments
|
||||
- No specific location (-20)
|
||||
- Style preference (-20)
|
||||
- Not in PREFERENCES.md (-10)
|
||||
= 30 confidence ❌ FILTER
|
||||
```
|
||||
</confidence_criteria>
|
||||
|
||||
#### Step 2: Present Findings for Triage
|
||||
|
||||
For EACH finding (with confidence ≥80), present in this format:
|
||||
|
||||
```
|
||||
---
|
||||
Finding #X: [Brief Title]
|
||||
|
||||
Confidence: [Score]/100 ✅
|
||||
Severity: 🔴 P1 / 🟡 P2 / 🔵 P3
|
||||
|
||||
Category: [Security/Performance/Architecture/Quality/etc.]
|
||||
|
||||
Description:
|
||||
[Detailed explanation of the issue or improvement]
|
||||
|
||||
Location: [file_path:line_number]
|
||||
|
||||
Problem:
|
||||
[What's wrong or could be better]
|
||||
|
||||
Impact:
|
||||
[Why this matters, what could happen]
|
||||
|
||||
Proposed Solution:
|
||||
[How to fix it]
|
||||
|
||||
Effort: Small/Medium/Large
|
||||
|
||||
Evidence:
|
||||
- [Why confidence is high - specific indicators]
|
||||
|
||||
---
|
||||
Do you want to add this to the todo list?
|
||||
1. yes - create todo file
|
||||
2. next - skip this finding
|
||||
3. custom - modify before creating
|
||||
```
|
||||
|
||||
**Note**: Findings with confidence <80 are automatically filtered and not shown.
|
||||
|
||||
#### Step 3: Create Todo Files for Approved Findings
|
||||
|
||||
<instructions>
|
||||
When user says "yes", create a properly formatted todo file:
|
||||
</instructions>
|
||||
|
||||
<todo_creation_process>
|
||||
|
||||
1. **Determine next issue ID:**
|
||||
```bash
|
||||
ls todos/ | grep -o '^[0-9]\+' | sort -n | tail -1
|
||||
```
|
||||
|
||||
2. **Generate filename:**
|
||||
```
|
||||
{next_id}-pending-{priority}-{brief-description}.md
|
||||
```
|
||||
Example: `042-pending-p1-sql-injection-risk.md`
|
||||
|
||||
3. **Create file from template:**
|
||||
```bash
|
||||
cp todos/000-pending-p1-TEMPLATE.md todos/{new_filename}
|
||||
```
|
||||
|
||||
4. **Populate with finding data:**
|
||||
```yaml
|
||||
---
|
||||
status: pending
|
||||
priority: p1 # or p2, p3 based on severity
|
||||
issue_id: "042"
|
||||
tags: [code-review, security, rails] # add relevant tags
|
||||
dependencies: []
|
||||
---
|
||||
|
||||
# [Finding Title]
|
||||
|
||||
## Problem Statement
|
||||
[Detailed description from finding]
|
||||
|
||||
## Findings
|
||||
- Discovered during code review by [agent names]
|
||||
- Location: [file_path:line_number]
|
||||
- [Key discoveries from agents]
|
||||
|
||||
## Proposed Solutions
|
||||
|
||||
### Option 1: [Primary solution from finding]
|
||||
- **Pros**: [Benefits]
|
||||
- **Cons**: [Drawbacks]
|
||||
- **Effort**: [Small/Medium/Large]
|
||||
- **Risk**: [Low/Medium/High]
|
||||
|
||||
## Recommended Action
|
||||
[Leave blank - needs manager triage]
|
||||
|
||||
## Technical Details
|
||||
- **Affected Files**: [List from finding]
|
||||
- **Related Components**: [Models, controllers, services affected]
|
||||
- **Database Changes**: [Yes/No - describe if yes]
|
||||
|
||||
## Resources
|
||||
- Code review PR: [PR link if applicable]
|
||||
- Related findings: [Other finding numbers]
|
||||
- Agent reports: [Which agents flagged this]
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] [Specific criteria based on solution]
|
||||
- [ ] Tests pass
|
||||
- [ ] Code reviewed
|
||||
|
||||
## Work Log
|
||||
|
||||
### {date} - Code Review Discovery
|
||||
**By:** Claude Code Review System
|
||||
**Actions:**
|
||||
- Discovered during comprehensive code review
|
||||
- Analyzed by multiple specialized agents
|
||||
- Categorized and prioritized
|
||||
|
||||
**Learnings:**
|
||||
- [Key insights from agent analysis]
|
||||
|
||||
## Notes
|
||||
Source: Code review performed on {date}
|
||||
Review command: /workflows:review {arguments}
|
||||
```
|
||||
|
||||
5. **Track creation:**
|
||||
Add to TodoWrite list if tracking multiple findings
|
||||
|
||||
</todo_creation_process>
|
||||
|
||||
#### Step 4: Summary Report
|
||||
|
||||
After processing all findings:
|
||||
|
||||
```markdown
|
||||
## Code Review Complete
|
||||
|
||||
**Review Target:** [PR number or branch]
|
||||
**Total Findings:** [X] (from all agents)
|
||||
**High-Confidence (≥80):** [Y] (shown to user)
|
||||
**Filtered (<80):** [Z] (auto-removed as likely false positives)
|
||||
**Todos Created:** [W]
|
||||
|
||||
### Confidence Distribution:
|
||||
- 90-100 (certain): [count]
|
||||
- 80-89 (confident): [count]
|
||||
- <80 (filtered): [count]
|
||||
|
||||
### Created Todos:
|
||||
- `{issue_id}-pending-p1-{description}.md` - {title} (confidence: 95)
|
||||
- `{issue_id}-pending-p2-{description}.md` - {title} (confidence: 85)
|
||||
...
|
||||
|
||||
### Skipped Findings (User Choice):
|
||||
- [Finding #Z]: {reason}
|
||||
...
|
||||
|
||||
### Auto-Filtered (Low Confidence):
|
||||
- [X] findings filtered with confidence <80
|
||||
- Run with `--show-all` flag to see filtered findings
|
||||
|
||||
### Next Steps:
|
||||
1. Triage pending todos: `ls todos/*-pending-*.md`
|
||||
2. Use `/triage` to review and approve
|
||||
3. Work on approved items: `/resolve_todo_parallel`
|
||||
```
|
||||
|
||||
#### Alternative: Batch Creation
|
||||
|
||||
If user wants to convert all findings to todos without review:
|
||||
|
||||
```bash
|
||||
# Ask: "Create todos for all X findings? (yes/no/show-critical-only)"
|
||||
# If yes: create todo files for all findings in parallel
|
||||
# If show-critical-only: only present P1 findings for triage
|
||||
```
|
||||
270
commands/es-tanstack-component.md
Normal file
270
commands/es-tanstack-component.md
Normal file
@@ -0,0 +1,270 @@
|
||||
---
|
||||
description: Scaffold shadcn/ui components for Tanstack Start with distinctive design, accessibility, and animation best practices built-in. Prevents generic aesthetics from the start.
|
||||
---
|
||||
|
||||
# Tanstack Component Generator Command
|
||||
|
||||
<command_purpose> Generate shadcn/ui components for Tanstack Start projects with distinctive design patterns, deep customization, accessibility features, and engaging animations built-in. Prevents generic "AI aesthetic" by providing branded templates from the start. </command_purpose>
|
||||
|
||||
## Introduction
|
||||
|
||||
<role>Senior Component Architect with expertise in shadcn/ui, Radix UI, React 19, Tailwind CSS, accessibility, and distinctive design patterns</role>
|
||||
|
||||
**Design Philosophy**: Start with distinctive, accessible, engaging components rather than fixing generic patterns later.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
<requirements>
|
||||
- Tanstack Start project with React 19
|
||||
- shadcn/ui components installed
|
||||
- Tailwind 4 CSS configured with custom theme
|
||||
- (Optional) shadcn/ui MCP server for component API validation
|
||||
</requirements>
|
||||
|
||||
## Command Usage
|
||||
|
||||
```bash
|
||||
/es-tanstack-component <type> <name> [options]
|
||||
```
|
||||
|
||||
### Arguments:
|
||||
|
||||
- `<type>`: Component type (button, card, form, dialog, dashboard, hero, etc.)
|
||||
- `<name>`: Component name in PascalCase (e.g., `PrimaryButton`, `FeatureCard`)
|
||||
- `[options]`: Optional flags:
|
||||
- `--theme <dark|light|custom>`: Theme variant
|
||||
- `--animations <minimal|standard|rich>`: Animation complexity
|
||||
- `--accessible`: Include enhanced accessibility features (default: true)
|
||||
- `--output <path>`: Custom output path (default: `src/components/`)
|
||||
|
||||
### Examples:
|
||||
|
||||
```bash
|
||||
# Generate primary button component
|
||||
/es-tanstack-component button PrimaryButton
|
||||
|
||||
# Generate feature card with rich animations
|
||||
/es-tanstack-component card FeatureCard --animations rich
|
||||
|
||||
# Generate dashboard layout
|
||||
/es-tanstack-component dashboard AdminDashboard --theme dark
|
||||
```
|
||||
|
||||
## Main Tasks
|
||||
|
||||
### 1. Detect Project Framework
|
||||
|
||||
<thinking>
|
||||
Verify this is a Tanstack Start project before generating components.
|
||||
</thinking>
|
||||
|
||||
```bash
|
||||
# Check for Tanstack Start
|
||||
if ! grep -q "@tanstack/start" package.json; then
|
||||
echo "❌ Not a Tanstack Start project"
|
||||
echo "This command requires Tanstack Start."
|
||||
echo "Run /es-init to set up a new Tanstack Start project."
|
||||
exit 1
|
||||
fi
|
||||
```
|
||||
|
||||
### 2. Verify shadcn/ui Setup
|
||||
|
||||
```bash
|
||||
# Check if shadcn/ui is initialized
|
||||
if [ ! -f "components.json" ]; then
|
||||
echo "shadcn/ui not initialized. Running setup..."
|
||||
pnpx shadcn@latest init
|
||||
fi
|
||||
```
|
||||
|
||||
### 3. Install Required shadcn/ui Components
|
||||
|
||||
Use MCP to verify components and install:
|
||||
|
||||
```typescript
|
||||
// Check if component exists via MCP
|
||||
const components = await shadcn-ui.list_components()
|
||||
const required = ['button', 'card', 'dialog'] // Based on type
|
||||
|
||||
for (const comp of required) {
|
||||
if (await componentInstalled(comp)) continue
|
||||
|
||||
// Install via CLI
|
||||
await exec(`pnpx shadcn@latest add ${comp}`)
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Generate Component with Distinctive Design
|
||||
|
||||
**Anti-Generic Aesthetics** (CRITICAL):
|
||||
|
||||
```tsx
|
||||
// ❌ GENERIC (FORBIDDEN)
|
||||
export function Button() {
|
||||
return (
|
||||
<button className="bg-purple-600 hover:bg-purple-700 font-inter">
|
||||
Click me
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
||||
// ✅ DISTINCTIVE (REQUIRED)
|
||||
export function PrimaryButton() {
|
||||
return (
|
||||
<Button
|
||||
className="bg-gradient-to-br from-amber-500 via-orange-500 to-rose-500
|
||||
hover:scale-105 transition-all duration-300
|
||||
shadow-lg shadow-orange-500/50
|
||||
font-['Fraunces'] font-semibold"
|
||||
>
|
||||
Click me
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### 5. Component Templates
|
||||
|
||||
#### Button Component
|
||||
|
||||
```tsx
|
||||
// src/components/PrimaryButton.tsx
|
||||
import { Button } from "@/components/ui/button"
|
||||
import type { ButtonProps } from "@/components/ui/button"
|
||||
|
||||
interface PrimaryButtonProps extends ButtonProps {
|
||||
loading?: boolean
|
||||
}
|
||||
|
||||
export function PrimaryButton({
|
||||
children,
|
||||
loading,
|
||||
...props
|
||||
}: PrimaryButtonProps) {
|
||||
return (
|
||||
<Button
|
||||
disabled={loading}
|
||||
className="bg-amber-600 hover:bg-amber-700
|
||||
hover:scale-105 transition-all duration-300
|
||||
shadow-lg shadow-amber-500/30"
|
||||
{...props}
|
||||
>
|
||||
{loading && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
|
||||
{children}
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
#### Card Component
|
||||
|
||||
```tsx
|
||||
// src/components/FeatureCard.tsx
|
||||
import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card"
|
||||
|
||||
interface FeatureCardProps {
|
||||
title: string
|
||||
description: string
|
||||
icon?: React.ReactNode
|
||||
}
|
||||
|
||||
export function FeatureCard({ title, description, icon }: FeatureCardProps) {
|
||||
return (
|
||||
<Card className="hover:shadow-xl transition-shadow duration-300 border-amber-200">
|
||||
<CardHeader>
|
||||
{icon && <div className="mb-4">{icon}</div>}
|
||||
<CardTitle className="text-2xl font-['Fraunces'] text-amber-900">
|
||||
{title}
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<p className="text-gray-700">{description}</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### 6. Generate Component File
|
||||
|
||||
**Task tanstack-ui-architect(component type and requirements)**:
|
||||
- Verify component props via MCP
|
||||
- Generate TypeScript interfaces
|
||||
- Implement accessibility features
|
||||
- Add distinctive styling (NOT generic)
|
||||
- Include animation patterns
|
||||
- Add JSDoc documentation
|
||||
- Export component
|
||||
|
||||
### 7. Generate Storybook/Example (Optional)
|
||||
|
||||
Create example usage:
|
||||
|
||||
```tsx
|
||||
// src/examples/PrimaryButtonExample.tsx
|
||||
import { PrimaryButton } from "@/components/PrimaryButton"
|
||||
|
||||
export function PrimaryButtonExample() {
|
||||
return (
|
||||
<div className="flex gap-4">
|
||||
<PrimaryButton>Default</PrimaryButton>
|
||||
<PrimaryButton loading>Loading...</PrimaryButton>
|
||||
<PrimaryButton disabled>Disabled</PrimaryButton>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## Design System Guidelines
|
||||
|
||||
### Required Customizations
|
||||
|
||||
✅ **Custom Fonts** (NOT Inter/Roboto):
|
||||
- Heading: Fraunces, Playfair Display, Merriweather
|
||||
- Body: Source Sans, Open Sans, Lato
|
||||
|
||||
✅ **Custom Colors** (NOT purple gradients):
|
||||
- Warm: Amber, Orange, Rose
|
||||
- Cool: Teal, Sky, Indigo
|
||||
- Earthy: Stone, Slate, Zinc
|
||||
|
||||
✅ **Thoughtful Animations**:
|
||||
- Hover: scale-105, shadow transitions
|
||||
- Focus: ring-offset with brand colors
|
||||
- Loading: custom spinners
|
||||
|
||||
❌ **Forbidden**:
|
||||
- Inter or Roboto fonts
|
||||
- Purple gradients (#8B5CF6)
|
||||
- Default shadcn/ui colors without customization
|
||||
- Glass-morphism effects
|
||||
- Generic spacing (always 1rem, 2rem)
|
||||
|
||||
## Validation
|
||||
|
||||
Before completing:
|
||||
|
||||
- [ ] Component props verified via MCP
|
||||
- [ ] TypeScript types defined
|
||||
- [ ] Accessibility features implemented (ARIA attributes)
|
||||
- [ ] Keyboard navigation supported
|
||||
- [ ] Distinctive design (NOT generic)
|
||||
- [ ] Animations included
|
||||
- [ ] Dark mode supported (if applicable)
|
||||
- [ ] Example usage provided
|
||||
|
||||
## Resources
|
||||
|
||||
- **shadcn/ui**: https://ui.shadcn.com
|
||||
- **Radix UI**: https://www.radix-ui.com
|
||||
- **Tailwind CSS**: https://tailwindcss.com/docs
|
||||
- **Google Fonts**: https://fonts.google.com
|
||||
|
||||
## Success Criteria
|
||||
|
||||
✅ Component generated with distinctive design
|
||||
✅ No prop hallucination (MCP verified)
|
||||
✅ Accessibility validated
|
||||
✅ TypeScript types included
|
||||
✅ Example usage provided
|
||||
760
commands/es-tanstack-migrate.md
Normal file
760
commands/es-tanstack-migrate.md
Normal file
@@ -0,0 +1,760 @@
|
||||
---
|
||||
description: Migrate Cloudflare Workers applications from any frontend framework to Tanstack Start while preserving infrastructure
|
||||
---
|
||||
|
||||
# Cloudflare Workers Framework Migration to Tanstack Start
|
||||
|
||||
<command_purpose> Migrate existing Cloudflare Workers applications from any frontend framework (React, Next.js, Vue, Nuxt, Svelte, vanilla JS) to Tanstack Start. Preserves all Cloudflare infrastructure (Workers, bindings, wrangler.toml) while modernizing the application layer. </command_purpose>
|
||||
|
||||
## Introduction
|
||||
|
||||
<role>Framework Migration Specialist focusing on Tanstack Start migrations for Cloudflare Workers applications</role>
|
||||
|
||||
This command analyzes your existing Cloudflare Workers application, identifies the current framework, and creates a comprehensive migration plan to Tanstack Start while preserving all Cloudflare infrastructure.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
<requirements>
|
||||
- Existing Cloudflare Workers application (already deployed)
|
||||
- Cloudflare account with existing bindings (KV/D1/R2/DO)
|
||||
- wrangler CLI installed (`npm install -g wrangler`)
|
||||
- Git repository for tracking migration
|
||||
- Node.js 18+ (for Tanstack Start)
|
||||
</requirements>
|
||||
|
||||
## Migration Source
|
||||
|
||||
<migration_source> #$ARGUMENTS </migration_source>
|
||||
|
||||
**Source frameworks supported**:
|
||||
- React / Next.js (straightforward React → React migration)
|
||||
- Vue 2/3 / Nuxt 2/3/4 (will convert to React)
|
||||
- Svelte / SvelteKit (will convert to React)
|
||||
- Vanilla JavaScript (will add React structure)
|
||||
- jQuery-based apps
|
||||
- Custom frameworks
|
||||
|
||||
**Target**: Tanstack Start (React 19 + TanStack Router + Vite) with Cloudflare Workers
|
||||
|
||||
**IMPORTANT**: This is a **FRAMEWORK migration** (UI layer), NOT a platform migration. All Cloudflare infrastructure (Workers, bindings, wrangler.toml) will be **PRESERVED**.
|
||||
|
||||
## Main Tasks
|
||||
|
||||
### 1. Framework Detection & Analysis
|
||||
|
||||
<thinking>
|
||||
First, identify the current framework to understand what we're migrating from.
|
||||
This informs all subsequent migration decisions.
|
||||
</thinking>
|
||||
|
||||
#### Step 1: Detect Current Framework
|
||||
|
||||
**Automatic detection**:
|
||||
|
||||
```bash
|
||||
# Check package.json for framework dependencies
|
||||
if grep -q "\"react\"" package.json; then
|
||||
echo "Detected: React"
|
||||
FRAMEWORK="react"
|
||||
if grep -q "\"next\"" package.json; then
|
||||
echo "Detected: Next.js"
|
||||
FRAMEWORK="nextjs"
|
||||
fi
|
||||
elif grep -q "\"vue\"" package.json; then
|
||||
VERSION=$(jq -r '.dependencies.vue // .devDependencies.vue' package.json | sed 's/[\^~]//g' | cut -d. -f1)
|
||||
echo "Detected: Vue $VERSION"
|
||||
FRAMEWORK="vue$VERSION"
|
||||
if grep -q "\"nuxt\"" package.json; then
|
||||
NUXT_VERSION=$(jq -r '.dependencies.nuxt // .devDependencies.nuxt' package.json | sed 's/[\^~]//g' | cut -d. -f1)
|
||||
echo "Detected: Nuxt $NUXT_VERSION"
|
||||
FRAMEWORK="nuxt$NUXT_VERSION"
|
||||
fi
|
||||
elif grep -q "\"svelte\"" package.json; then
|
||||
echo "Detected: Svelte"
|
||||
FRAMEWORK="svelte"
|
||||
if grep -q "\"@sveltejs/kit\"" package.json; then
|
||||
echo "Detected: SvelteKit"
|
||||
FRAMEWORK="sveltekit"
|
||||
fi
|
||||
elif grep -q "\"jquery\"" package.json; then
|
||||
echo "Detected: jQuery"
|
||||
FRAMEWORK="jquery"
|
||||
else
|
||||
echo "Detected: Vanilla JavaScript"
|
||||
FRAMEWORK="vanilla"
|
||||
fi
|
||||
```
|
||||
|
||||
#### Step 2: Analyze Application Structure
|
||||
|
||||
**Discovery tasks** (run in parallel):
|
||||
|
||||
1. **Inventory pages/routes**
|
||||
```bash
|
||||
# React/Next.js
|
||||
find pages -name "*.jsx" -o -name "*.tsx" 2>/dev/null | wc -l
|
||||
find app -name "page.tsx" 2>/dev/null | wc -l
|
||||
|
||||
# React/Nuxt
|
||||
find pages -name "*.vue" 2>/dev/null | wc -l
|
||||
|
||||
# Vanilla
|
||||
find src -name "*.html" 2>/dev/null | wc -l
|
||||
```
|
||||
|
||||
2. **Inventory components**
|
||||
```bash
|
||||
find components -name "*.jsx" -o -name "*.tsx" -o -name "*.vue" -o -name "*.svelte" 2>/dev/null | wc -l
|
||||
```
|
||||
|
||||
3. **Identify state management**
|
||||
```bash
|
||||
# Redux/Zustand
|
||||
grep -r "createStore\|configureStore\|create.*zustand" src/ 2>/dev/null
|
||||
|
||||
# React Query/TanStack Query
|
||||
grep -r "useQuery\|QueryClient" src/ 2>/dev/null
|
||||
|
||||
# Zustand/Pinia
|
||||
grep -r "createStore\|defineStore" src/ store/ 2>/dev/null
|
||||
|
||||
# Context API
|
||||
grep -r "createContext\|useContext" src/ 2>/dev/null
|
||||
```
|
||||
|
||||
4. **Identify UI dependencies**
|
||||
```bash
|
||||
# Check for UI frameworks
|
||||
jq '.dependencies + .devDependencies | keys[]' package.json | grep -E "bootstrap|material-ui|antd|chakra|@nuxt/ui|shadcn"
|
||||
```
|
||||
|
||||
5. **Verify Cloudflare bindings** (MUST preserve)
|
||||
```bash
|
||||
# Parse wrangler.toml
|
||||
grep -E "^\[\[kv_namespaces\]\]|^\[\[d1_databases\]\]|^\[\[r2_buckets\]\]|^\[\[durable_objects" wrangler.toml
|
||||
|
||||
# List binding names
|
||||
grep "binding =" wrangler.toml | awk '{print $3}' | tr -d '"'
|
||||
```
|
||||
|
||||
#### Step 3: Generate Framework Analysis Report
|
||||
|
||||
<deliverable>
|
||||
Comprehensive report on current framework and migration complexity
|
||||
</deliverable>
|
||||
|
||||
```markdown
|
||||
## Framework Migration Analysis Report
|
||||
|
||||
**Project**: [app-name]
|
||||
**Current Framework**: [React / Next.js / Vue / Nuxt / etc.]
|
||||
**Target Framework**: Tanstack Start (React 19 + TanStack Router)
|
||||
**Cloudflare Deployment**: ✅ Already on Workers
|
||||
|
||||
### Current Application Inventory
|
||||
|
||||
**Pages/Routes**: [X] routes detected
|
||||
- [List key routes]
|
||||
|
||||
**Components**: [Y] components detected
|
||||
- Shared: [count]
|
||||
- Page-specific: [count]
|
||||
|
||||
**State Management**: [Redux / Zustand / TanStack Query / Context / None]
|
||||
**UI Dependencies**: [Material UI / Chakra / shadcn/ui / Custom CSS / None]
|
||||
|
||||
**API Endpoints**: [Z] server routes/endpoints
|
||||
- Backend framework: [Express / Hono / Next.js API / Nuxt server]
|
||||
|
||||
### Cloudflare Infrastructure (PRESERVE)
|
||||
|
||||
**Bindings** (from wrangler.toml):
|
||||
- KV namespaces: [count] ([list names])
|
||||
- D1 databases: [count] ([list names])
|
||||
- R2 buckets: [count] ([list names])
|
||||
- Durable Objects: [count] ([list classes])
|
||||
|
||||
**wrangler.toml Configuration**:
|
||||
```toml
|
||||
[Current wrangler.toml snippet]
|
||||
```
|
||||
|
||||
**CRITICAL**: All bindings and Workers configuration will be PRESERVED. Only the application framework will change.
|
||||
|
||||
### Migration Complexity
|
||||
|
||||
**Overall Complexity**: [Low / Medium / High]
|
||||
|
||||
**Complexity Factors**:
|
||||
- Framework paradigm shift: [None / Small / Large]
|
||||
- React → Tanstack Start: Low (same paradigm, better tooling)
|
||||
- Next.js → Tanstack Start: Medium (different routing)
|
||||
- React/Nuxt → Tanstack Start: High (Vue to React conversion)
|
||||
- Vanilla → Tanstack Start: Medium (adding framework)
|
||||
- Component count: [X components] - [Low / Medium / High]
|
||||
- State management migration: [Simple / Complex]
|
||||
- UI dependencies: [Easy replacement / Medium / Custom CSS (requires work)]
|
||||
- API complexity: [Simple / Keep separate]
|
||||
|
||||
### Migration Strategy Recommendation
|
||||
|
||||
[Detailed strategy based on analysis]
|
||||
|
||||
**Approach**: [Full migration / Incremental / UI-only with separate backend]
|
||||
|
||||
**Timeline**: [X weeks / days]
|
||||
**Estimated Effort**: [Low / Medium / High]
|
||||
```
|
||||
|
||||
### 2. Multi-Agent Migration Planning
|
||||
|
||||
<thinking>
|
||||
Use the tanstack-migration-specialist agent and supporting agents to create
|
||||
a comprehensive migration plan.
|
||||
</thinking>
|
||||
|
||||
#### Phase 1: Framework-Specific Analysis
|
||||
|
||||
1. **Task tanstack-migration-specialist(current framework and structure)**
|
||||
- Analyze source framework patterns
|
||||
- Map components to React + shadcn/ui equivalents
|
||||
- Plan routing migration (TanStack Router file-based routing)
|
||||
- Recommend state management approach (TanStack Query + Zustand)
|
||||
- Design API strategy (server functions vs separate backend)
|
||||
- Generate component mapping table
|
||||
- Generate route mapping table
|
||||
- Create implementation plan with todos
|
||||
|
||||
#### Phase 2: Cloudflare Infrastructure Validation (Parallel)
|
||||
|
||||
2. **Task binding-context-analyzer(existing wrangler.toml)**
|
||||
- Parse current wrangler.toml
|
||||
- Verify all bindings are valid
|
||||
- Document binding usage patterns
|
||||
- Ensure compatibility_date is 2025-09-15+
|
||||
- Verify `remote = true` on all bindings
|
||||
- Generate Env TypeScript interface
|
||||
|
||||
3. **Task cloudflare-architecture-strategist(current architecture)**
|
||||
- Analyze if backend should stay separate or integrate
|
||||
- Recommend Workers architecture (single vs multiple)
|
||||
- Service binding strategy (if multi-worker)
|
||||
- Assess if Tanstack Start server functions can replace existing API
|
||||
|
||||
#### Phase 3: Code Quality & Patterns (Parallel)
|
||||
|
||||
4. **Task cloudflare-pattern-specialist(current codebase)**
|
||||
- Identify Workers-specific patterns to preserve
|
||||
- Detect any Workers anti-patterns
|
||||
- Ensure bindings usage follows best practices
|
||||
|
||||
5. **Task workers-runtime-guardian(current codebase)**
|
||||
- Verify no Node.js APIs exist (would break in Workers)
|
||||
- Check compatibility with Workers runtime
|
||||
- Validate all code is Workers-compatible
|
||||
|
||||
### 3. Migration Plan Synthesis
|
||||
|
||||
<deliverable>
|
||||
Detailed Tanstack Start migration plan with step-by-step instructions
|
||||
</deliverable>
|
||||
|
||||
<critical_requirement> Present complete migration plan for user approval before starting any code changes. </critical_requirement>
|
||||
|
||||
The tanstack-migration-specialist agent will generate a comprehensive plan including:
|
||||
|
||||
**Component Migration Plan**:
|
||||
| Old Component | New Component (shadcn/ui or custom) | Effort | Notes |
|
||||
|--------------|-------------------------------------|--------|-------|
|
||||
| `<Button>` | `<Button>` (shadcn/ui) | Low | Direct mapping |
|
||||
| `<UserCard>` | `<Card>` + custom | Medium | Restructure children |
|
||||
| `<Modal>` (Vue) | `<Dialog>` (shadcn/ui) | Medium | Vue → React conversion |
|
||||
|
||||
**Route Migration Plan**:
|
||||
| Old Route | New File | Dynamic | Loaders | Notes |
|
||||
|----------|---------|---------|---------|-------|
|
||||
| `/` | `src/routes/index.tsx` | No | No | Home |
|
||||
| `/users/:id` | `src/routes/users.$id.tsx` | Yes | Yes | Detail with data loading |
|
||||
| `/api/users` | `src/routes/api/users.ts` | No | N/A | API route (server function) |
|
||||
|
||||
**State Management Strategy**:
|
||||
- Current: [Redux / Context / Zustand / etc.]
|
||||
- Target: TanStack Query (server state) + Zustand (client state)
|
||||
- Migration approach: [Details]
|
||||
|
||||
**Data Fetching Strategy**:
|
||||
- Current: [useEffect + fetch / Next.js getServerSideProps / Nuxt useAsyncData]
|
||||
- Target: TanStack Router loaders + TanStack Query
|
||||
- Benefits: Type-safe, automatic caching, optimistic updates
|
||||
|
||||
**API Strategy**:
|
||||
- Current: [Express / Hono / Next.js API / Nuxt server routes]
|
||||
- Recommendation: [Tanstack Start server functions / Keep separate]
|
||||
- Rationale: [Why]
|
||||
|
||||
**Styling Strategy**:
|
||||
- Current: [Material UI / Chakra / shadcn/ui / Custom CSS]
|
||||
- Target: shadcn/ui + Tailwind 4
|
||||
- Migration: [Component-by-component replacement]
|
||||
|
||||
**Implementation Phases**:
|
||||
1. Setup Tanstack Start project with Cloudflare Workers preset
|
||||
2. Configure wrangler.jsonc for deployment
|
||||
3. Setup shadcn/ui components
|
||||
4. Migrate layouts (if any)
|
||||
5. Migrate routes with loaders (priority order)
|
||||
6. Convert components to React (if needed)
|
||||
7. Setup TanStack Query + Zustand
|
||||
8. Migrate/create server functions
|
||||
9. Replace UI with shadcn/ui + Tailwind 4
|
||||
10. Update Cloudflare bindings in app context
|
||||
11. Test & deploy
|
||||
|
||||
### 4. User Approval & Confirmation
|
||||
|
||||
<critical_requirement> MUST get explicit user approval before proceeding with any code changes. </critical_requirement>
|
||||
|
||||
**Present the migration plan and ask**:
|
||||
|
||||
```
|
||||
📋 Tanstack Start Migration Plan Complete
|
||||
|
||||
Summary:
|
||||
- Source framework: [React / Next.js / Vue / Nuxt / etc.]
|
||||
- Target: Tanstack Start (React 19 + TanStack Router)
|
||||
- Complexity: [Low / Medium / High]
|
||||
- Timeline: [X] weeks/days
|
||||
|
||||
Key changes:
|
||||
1. [Major change 1]
|
||||
2. [Major change 2]
|
||||
3. [Major change 3]
|
||||
|
||||
Cloudflare infrastructure:
|
||||
✅ All bindings preserved (no changes)
|
||||
✅ wrangler.toml configuration maintained
|
||||
✅ Workers deployment unchanged
|
||||
|
||||
Do you want to proceed with this migration plan?
|
||||
|
||||
Options:
|
||||
1. yes - Start Phase 1 (Setup Tanstack Start)
|
||||
2. show-details - View detailed component/route mappings
|
||||
3. modify - Adjust plan before starting
|
||||
4. export - Save plan to .claude/todos/ for later
|
||||
5. no - Cancel migration
|
||||
```
|
||||
|
||||
### 5. Automated Migration Execution
|
||||
|
||||
<thinking>
|
||||
Only execute if user approves. Work through phases systematically.
|
||||
</thinking>
|
||||
|
||||
**If user says "yes"**:
|
||||
|
||||
1. **Create migration branch**
|
||||
```bash
|
||||
git checkout -b migrate-to-tanstack-start
|
||||
git commit -m "chore: Create migration branch for Tanstack Start"
|
||||
```
|
||||
|
||||
2. **Phase 1: Initialize Tanstack Start Project**
|
||||
|
||||
```bash
|
||||
# Create new Tanstack Start app with Cloudflare preset
|
||||
pnpm create @tanstack/start@latest temp-tanstack --template start-basic-cloudflare
|
||||
|
||||
# Copy configuration files
|
||||
cp temp-tanstack/vite.config.ts ./
|
||||
cp temp-tanstack/app.config.ts ./
|
||||
cp temp-tanstack/tsconfig.json ./tsconfig.tanstack.json
|
||||
|
||||
# Install dependencies
|
||||
pnpm add @tanstack/start @tanstack/react-router @tanstack/react-query zustand
|
||||
pnpm add -D vinxi vite
|
||||
|
||||
# Setup shadcn/ui
|
||||
pnpx shadcn@latest init
|
||||
# Select: Tailwind 4, TypeScript, src/ directory
|
||||
```
|
||||
|
||||
3. **Phase 2: Configure Cloudflare Workers**
|
||||
|
||||
Create `wrangler.jsonc`:
|
||||
```jsonc
|
||||
{
|
||||
"name": "your-app-name",
|
||||
"compatibility_date": "2025-09-15",
|
||||
"main": ".output/server/index.mjs",
|
||||
|
||||
// PRESERVE existing bindings from old wrangler.toml
|
||||
"kv_namespaces": [
|
||||
// Copy from analysis report
|
||||
],
|
||||
"d1_databases": [
|
||||
// Copy from analysis report
|
||||
],
|
||||
"r2_buckets": [
|
||||
// Copy from analysis report
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Update `vite.config.ts`:
|
||||
```typescript
|
||||
import { defineConfig } from 'vite'
|
||||
import { TanStackStartVite } from '@tanstack/start/vite'
|
||||
|
||||
export default defineConfig({
|
||||
plugins: [TanStackStartVite()],
|
||||
})
|
||||
```
|
||||
|
||||
4. **Phase 3: Migrate Routes**
|
||||
|
||||
For each route in the migration plan:
|
||||
|
||||
**Next.js `pages/users/[id].tsx` → Tanstack Start `src/routes/users.$id.tsx`**:
|
||||
|
||||
```tsx
|
||||
// OLD (Next.js)
|
||||
export async function getServerSideProps({ params }) {
|
||||
const user = await fetchUser(params.id)
|
||||
return { props: { user } }
|
||||
}
|
||||
|
||||
export default function UserPage({ user }) {
|
||||
return <div>{user.name}</div>
|
||||
}
|
||||
|
||||
// NEW (Tanstack Start)
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
|
||||
export const Route = createFileRoute('/users/$id')({
|
||||
loader: async ({ params, context }) => {
|
||||
const user = await fetchUser(params.id, context.cloudflare.env)
|
||||
return { user }
|
||||
},
|
||||
component: UserPage,
|
||||
})
|
||||
|
||||
function UserPage() {
|
||||
const { user } = Route.useLoaderData()
|
||||
return <div>{user.name}</div>
|
||||
}
|
||||
```
|
||||
|
||||
**Vue component → React component**:
|
||||
|
||||
```tsx
|
||||
// OLD (Vue)
|
||||
<div class="card">
|
||||
<h2>{ title}</h2>
|
||||
<p>{ description}</p>
|
||||
</div>
|
||||
|
||||
const props = defineProps<{
|
||||
title: string
|
||||
description: string
|
||||
}>()
|
||||
|
||||
// NEW (React + shadcn/ui)
|
||||
import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/card'
|
||||
|
||||
interface CardComponentProps {
|
||||
title: string
|
||||
description: string
|
||||
}
|
||||
|
||||
export function CardComponent({ title, description }: CardComponentProps) {
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>{title}</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<p>{description}</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
5. **Phase 4: Setup State Management**
|
||||
|
||||
**TanStack Query setup** (`src/lib/query-client.ts`):
|
||||
```typescript
|
||||
import { QueryClient } from '@tanstack/react-query'
|
||||
|
||||
export const queryClient = new QueryClient({
|
||||
defaultOptions: {
|
||||
queries: {
|
||||
staleTime: 60 * 1000, // 1 minute
|
||||
},
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
**Zustand store** (`src/stores/ui-store.ts`):
|
||||
```typescript
|
||||
import { create } from 'zustand'
|
||||
|
||||
interface UIStore {
|
||||
sidebarOpen: boolean
|
||||
toggleSidebar: () => void
|
||||
}
|
||||
|
||||
export const useUIStore = create<UIStore>((set) => ({
|
||||
sidebarOpen: false,
|
||||
toggleSidebar: () => set((state) => ({ sidebarOpen: !state.sidebarOpen })),
|
||||
}))
|
||||
```
|
||||
|
||||
6. **Phase 5: Setup Cloudflare Bindings Context**
|
||||
|
||||
Create `src/lib/cloudflare.ts`:
|
||||
```typescript
|
||||
export interface Env {
|
||||
// PRESERVE from analysis report
|
||||
MY_KV: KVNamespace
|
||||
DB: D1Database
|
||||
MY_BUCKET: R2Bucket
|
||||
}
|
||||
```
|
||||
|
||||
Update `app.config.ts`:
|
||||
```typescript
|
||||
import { defineConfig } from '@tanstack/start/config'
|
||||
|
||||
export default defineConfig({
|
||||
server: {
|
||||
preset: 'cloudflare-module',
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
7. **Phase 6: Migrate Server Functions**
|
||||
|
||||
```typescript
|
||||
// src/routes/api/users.ts
|
||||
import { createAPIFileRoute } from '@tanstack/start/api'
|
||||
|
||||
export const Route = createAPIFileRoute('/api/users')({
|
||||
GET: async ({ request, context }) => {
|
||||
const { env } = context.cloudflare
|
||||
|
||||
// Access Cloudflare bindings
|
||||
const users = await env.DB.prepare('SELECT * FROM users').all()
|
||||
|
||||
return Response.json(users)
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
8. **Phase 7: Install shadcn/ui Components**
|
||||
|
||||
```bash
|
||||
# Add commonly used components
|
||||
pnpx shadcn@latest add button card dialog form input label
|
||||
```
|
||||
|
||||
9. **Phase 8: Update Package Scripts**
|
||||
|
||||
Update `package.json`:
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"dev": "vinxi dev",
|
||||
"build": "vinxi build",
|
||||
"start": "vinxi start",
|
||||
"deploy": "wrangler deploy"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
10. **Phase 9: Testing & Validation**
|
||||
|
||||
```bash
|
||||
# Run development server
|
||||
pnpm dev
|
||||
|
||||
# Build for production
|
||||
pnpm build
|
||||
|
||||
# Deploy to Cloudflare Workers
|
||||
wrangler deploy
|
||||
```
|
||||
|
||||
### 6. Post-Migration Validation
|
||||
|
||||
<thinking>
|
||||
Run comprehensive validation after migration is complete.
|
||||
</thinking>
|
||||
|
||||
**Automated validation** (run in parallel):
|
||||
|
||||
1. **Task workers-runtime-guardian(migrated codebase)**
|
||||
- Verify no Node.js APIs introduced
|
||||
- Validate Workers runtime compatibility
|
||||
- Check bundle size (< 1MB recommended)
|
||||
|
||||
2. **Task binding-context-analyzer(new wrangler.jsonc)**
|
||||
- Verify all bindings preserved
|
||||
- Check binding types match Env interface
|
||||
- Validate `remote = true` on all bindings
|
||||
|
||||
3. **Task cloudflare-pattern-specialist(migrated codebase)**
|
||||
- Verify bindings accessed correctly via context
|
||||
- Check error handling patterns
|
||||
- Validate security patterns
|
||||
|
||||
4. **Run /es-validate**
|
||||
- Full validation suite
|
||||
- Check for anti-patterns
|
||||
- Verify design system compliance
|
||||
|
||||
### 7. Migration Report
|
||||
|
||||
<deliverable>
|
||||
Final migration report with validation results and next steps
|
||||
</deliverable>
|
||||
|
||||
```markdown
|
||||
## Tanstack Start Migration Complete ✅
|
||||
|
||||
**Project**: [app-name]
|
||||
**Migration**: [source] → Tanstack Start
|
||||
**Date**: [timestamp]
|
||||
|
||||
### Migration Summary
|
||||
|
||||
**Routes migrated**: [X] / [X]
|
||||
**Components converted**: [Y] / [Y]
|
||||
**Server functions created**: [Z]
|
||||
**Tests passing**: [All / Some / None]
|
||||
|
||||
### Validation Results
|
||||
|
||||
✅ Workers runtime compatibility verified
|
||||
✅ All Cloudflare bindings preserved and functional
|
||||
✅ Bundle size: [X]KB (target: < 1MB)
|
||||
✅ No Node.js APIs detected
|
||||
✅ Security patterns validated
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
- Cold start time: [before] → [after]
|
||||
- Bundle size: [before] → [after]
|
||||
- Type safety: [improved with TanStack Router]
|
||||
|
||||
### Next Steps
|
||||
|
||||
1. [ ] Run full test suite: `pnpm test`
|
||||
2. [ ] Deploy to preview: `wrangler deploy --env preview`
|
||||
3. [ ] Verify all features work in preview
|
||||
4. [ ] Deploy to production: `wrangler deploy --env production`
|
||||
5. [ ] Monitor Workers metrics
|
||||
6. [ ] Update documentation
|
||||
|
||||
### Files Changed
|
||||
|
||||
**Added**:
|
||||
- [list new files]
|
||||
|
||||
**Modified**:
|
||||
- [list modified files]
|
||||
|
||||
**Removed**:
|
||||
- [list removed files]
|
||||
|
||||
### Rollback Plan
|
||||
|
||||
If issues arise:
|
||||
```bash
|
||||
git checkout main
|
||||
git branch -D migrate-to-tanstack-start
|
||||
wrangler rollback
|
||||
```
|
||||
```
|
||||
|
||||
## Framework-Specific Migration Patterns
|
||||
|
||||
### React/Next.js → Tanstack Start
|
||||
|
||||
**Complexity**: Low (same React ecosystem)
|
||||
|
||||
**Key mappings**:
|
||||
- `pages/` → `src/routes/`
|
||||
- `getServerSideProps` → Route `loader`
|
||||
- `getStaticProps` → Route `loader` (cached)
|
||||
- `api/` → `src/routes/api/` (server functions)
|
||||
- `useEffect` + fetch → TanStack Query `useQuery`
|
||||
- Context API → Zustand (for client state)
|
||||
|
||||
### React/Nuxt → Tanstack Start
|
||||
|
||||
**Complexity**: High (Vue to React conversion)
|
||||
|
||||
**Key mappings**:
|
||||
- `{}` interpolation → `{}`
|
||||
- `v-if` → `{condition && <Component />}`
|
||||
- `v-for` → `.map()`
|
||||
- `v-model` → `value` + `onChange`
|
||||
- `defineProps` → TypeScript interface + props
|
||||
- `ref()` / `reactive()` → `useState()` / `useReducer()`
|
||||
- `computed()` → `useMemo()`
|
||||
- `watch()` → `useEffect()`
|
||||
- `useAsyncData` → TanStack Router `loader` + TanStack Query
|
||||
|
||||
### Vanilla JS → Tanstack Start
|
||||
|
||||
**Complexity**: Medium (adding full framework)
|
||||
|
||||
**Approach**:
|
||||
1. Identify pages and routes
|
||||
2. Convert HTML templates to React components
|
||||
3. Convert event handlers to React patterns
|
||||
4. Add type safety with TypeScript
|
||||
5. Implement routing with TanStack Router
|
||||
6. Add state management where needed
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
**Issue**: "Module not found: @tanstack/start"
|
||||
**Solution**: Ensure you're using the correct package manager (pnpm recommended)
|
||||
|
||||
**Issue**: "wrangler.jsonc not recognized"
|
||||
**Solution**: Update wrangler to latest version: `npm install -g wrangler@latest`
|
||||
|
||||
**Issue**: "Bindings not available in context"
|
||||
**Solution**: Verify `app.config.ts` has correct preset: `preset: 'cloudflare-module'`
|
||||
|
||||
**Issue**: "Build fails with Workers runtime errors"
|
||||
**Solution**: Check for Node.js APIs (fs, path, etc.) - use Workers alternatives
|
||||
|
||||
## Resources
|
||||
|
||||
- **Tanstack Start Docs**: https://tanstack.com/start/latest
|
||||
- **TanStack Router Docs**: https://tanstack.com/router/latest
|
||||
- **TanStack Query Docs**: https://tanstack.com/query/latest
|
||||
- **shadcn/ui Docs**: https://ui.shadcn.com
|
||||
- **Cloudflare Workers Docs**: https://developers.cloudflare.com/workers
|
||||
- **Zustand Docs**: https://docs.pmnd.rs/zustand
|
||||
|
||||
## Success Metrics
|
||||
|
||||
Track these metrics before and after migration:
|
||||
|
||||
- ⚡ Cold start time (ms)
|
||||
- 📦 Bundle size (KB)
|
||||
- 🎯 Type safety coverage (%)
|
||||
- 🚀 Lighthouse score
|
||||
- 🔒 Security audit results
|
||||
- 📊 Workers Analytics (requests/errors/latency)
|
||||
|
||||
---
|
||||
|
||||
**Remember**: This is a FRAMEWORK migration only. All Cloudflare infrastructure, bindings, and Workers configuration are preserved throughout the process.
|
||||
222
commands/es-tanstack-route.md
Normal file
222
commands/es-tanstack-route.md
Normal file
@@ -0,0 +1,222 @@
|
||||
---
|
||||
description: Create new TanStack Router routes with loaders, type-safe params, and proper file structure for Tanstack Start projects
|
||||
---
|
||||
|
||||
# Tanstack Route Generator Command
|
||||
|
||||
<command_purpose> Generate TanStack Router routes with server-side loaders, type-safe parameters, error boundaries, and proper file structure for Tanstack Start projects on Cloudflare Workers. </command_purpose>
|
||||
|
||||
## Introduction
|
||||
|
||||
<role>Senior Routing Engineer with expertise in TanStack Router, server-side data loading, and Cloudflare Workers integration</role>
|
||||
|
||||
## Prerequisites
|
||||
|
||||
<requirements>
|
||||
- Tanstack Start project with TanStack Router
|
||||
- Cloudflare Workers setup (wrangler.jsonc)
|
||||
- TypeScript configured
|
||||
- src/routes/ directory structure
|
||||
</requirements>
|
||||
|
||||
## Command Usage
|
||||
|
||||
```bash
|
||||
/es-tanstack-route <route-path> [options]
|
||||
```
|
||||
|
||||
### Arguments:
|
||||
|
||||
- `<route-path>`: Route path (e.g., `/users/$id`, `/blog`, `/api/users`)
|
||||
- `[options]`: Optional flags:
|
||||
- `--loader`: Include server-side loader (default: true for non-API routes)
|
||||
- `--api`: Create API route (server function)
|
||||
- `--layout`: Create layout route
|
||||
- `--params <params>`: Dynamic params (e.g., `id,slug`)
|
||||
- `--search-params <params>`: Search params (e.g., `page:number,filter:string`)
|
||||
|
||||
### Examples:
|
||||
|
||||
```bash
|
||||
# Create static route
|
||||
/es-tanstack-route /about
|
||||
|
||||
# Create dynamic route with loader
|
||||
/es-tanstack-route /users/$id --loader
|
||||
|
||||
# Create API route
|
||||
/es-tanstack-route /api/users --api
|
||||
|
||||
# Create route with search params
|
||||
/es-tanstack-route /users --search-params page:number,sort:string
|
||||
```
|
||||
|
||||
## Main Tasks
|
||||
|
||||
### 1. Parse Route Path
|
||||
|
||||
Convert route path to file path:
|
||||
|
||||
| Route Path | File Path |
|
||||
|------------|-----------|
|
||||
| `/` | `src/routes/index.tsx` |
|
||||
| `/about` | `src/routes/about.tsx` |
|
||||
| `/users/$id` | `src/routes/users.$id.tsx` |
|
||||
| `/blog/$slug` | `src/routes/blog.$slug.tsx` |
|
||||
| `/api/users` | `src/routes/api/users.ts` |
|
||||
|
||||
### 2. Generate Route File
|
||||
|
||||
**Standard Route with Loader**:
|
||||
|
||||
```tsx
|
||||
// src/routes/users.$id.tsx
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
import { z } from 'zod'
|
||||
|
||||
export const Route = createFileRoute('/users/$id')({
|
||||
loader: async ({ params, context }) => {
|
||||
const { env } = context.cloudflare
|
||||
|
||||
const user = await env.DB.prepare(
|
||||
'SELECT * FROM users WHERE id = ?'
|
||||
).bind(params.id).first()
|
||||
|
||||
if (!user) {
|
||||
throw new Error('User not found')
|
||||
}
|
||||
|
||||
return { user }
|
||||
},
|
||||
errorComponent: ({ error }) => (
|
||||
<div className="p-4">
|
||||
<h1 className="text-2xl font-bold text-red-600">Error</h1>
|
||||
<p>{error.message}</p>
|
||||
</div>
|
||||
),
|
||||
pendingComponent: () => (
|
||||
<div className="p-4">
|
||||
<Loader2 className="animate-spin" />
|
||||
<span>Loading...</span>
|
||||
</div>
|
||||
),
|
||||
component: UserPage,
|
||||
})
|
||||
|
||||
function UserPage() {
|
||||
const { user } = Route.useLoaderData()
|
||||
|
||||
return (
|
||||
<div className="max-w-4xl mx-auto p-6">
|
||||
<h1 className="text-3xl font-bold">{user.name}</h1>
|
||||
<p className="text-gray-600">{user.email}</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
**API Route**:
|
||||
|
||||
```typescript
|
||||
// src/routes/api/users.ts
|
||||
import { createAPIFileRoute } from '@tanstack/start/api'
|
||||
|
||||
export const Route = createAPIFileRoute('/api/users')({
|
||||
GET: async ({ request, context }) => {
|
||||
const { env } = context.cloudflare
|
||||
|
||||
const users = await env.DB.prepare('SELECT * FROM users').all()
|
||||
|
||||
return Response.json(users)
|
||||
},
|
||||
POST: async ({ request, context }) => {
|
||||
const { env } = context.cloudflare
|
||||
const data = await request.json()
|
||||
|
||||
await env.DB.prepare(
|
||||
'INSERT INTO users (name, email) VALUES (?, ?)'
|
||||
).bind(data.name, data.email).run()
|
||||
|
||||
return Response.json({ success: true })
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
**Route with Search Params**:
|
||||
|
||||
```tsx
|
||||
// src/routes/users.tsx
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
import { z } from 'zod'
|
||||
|
||||
const searchSchema = z.object({
|
||||
page: z.number().int().positive().default(1),
|
||||
sort: z.enum(['name', 'date']).default('name'),
|
||||
filter: z.string().optional(),
|
||||
})
|
||||
|
||||
export const Route = createFileRoute('/users')({
|
||||
validateSearch: searchSchema,
|
||||
loaderDeps: ({ search }) => search,
|
||||
loader: async ({ deps: search, context }) => {
|
||||
const { env } = context.cloudflare
|
||||
|
||||
const offset = (search.page - 1) * 20
|
||||
const users = await env.DB.prepare(
|
||||
`SELECT * FROM users ORDER BY ${search.sort} LIMIT 20 OFFSET ?`
|
||||
).bind(offset).all()
|
||||
|
||||
return { users, search }
|
||||
},
|
||||
component: UsersPage,
|
||||
})
|
||||
|
||||
function UsersPage() {
|
||||
const { users, search } = Route.useLoaderData()
|
||||
const navigate = Route.useNavigate()
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h1>Users (Page {search.page})</h1>
|
||||
{/* ... */}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Generate TypeScript Types
|
||||
|
||||
```typescript
|
||||
// src/types/routes.ts
|
||||
export interface UserParams {
|
||||
id: string
|
||||
}
|
||||
|
||||
export interface UsersSearch {
|
||||
page: number
|
||||
sort: 'name' | 'date'
|
||||
filter?: string
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Update Router Configuration
|
||||
|
||||
Ensure route is registered in router.
|
||||
|
||||
### 5. Validation
|
||||
|
||||
**Task tanstack-routing-specialist(generated route)**:
|
||||
- Verify route path syntax
|
||||
- Validate loader implementation
|
||||
- Check error handling
|
||||
- Verify TypeScript types
|
||||
- Ensure Cloudflare bindings accessible
|
||||
|
||||
## Success Criteria
|
||||
|
||||
✅ Route file generated in correct location
|
||||
✅ Loader implemented with Cloudflare bindings
|
||||
✅ Error boundary included
|
||||
✅ Pending state handled
|
||||
✅ TypeScript types defined
|
||||
✅ Search params validated (if applicable)
|
||||
214
commands/es-tanstack-server-fn.md
Normal file
214
commands/es-tanstack-server-fn.md
Normal file
@@ -0,0 +1,214 @@
|
||||
---
|
||||
description: Generate type-safe server functions for Tanstack Start with Cloudflare Workers bindings integration
|
||||
---
|
||||
|
||||
# Tanstack Server Function Generator
|
||||
|
||||
<command_purpose> Generate type-safe server functions for Tanstack Start projects that leverage Cloudflare Workers bindings (KV, D1, R2, DO) with proper error handling and validation. </command_purpose>
|
||||
|
||||
## Introduction
|
||||
|
||||
<role>Senior Backend Engineer with expertise in server functions, type-safe RPC, and Cloudflare Workers bindings</role>
|
||||
|
||||
## Prerequisites
|
||||
|
||||
<requirements>
|
||||
- Tanstack Start project
|
||||
- Cloudflare Workers bindings configured
|
||||
- TypeScript with strict mode
|
||||
- Zod for validation (recommended)
|
||||
</requirements>
|
||||
|
||||
## Command Usage
|
||||
|
||||
```bash
|
||||
/es-tanstack-server-fn <name> <method> [options]
|
||||
```
|
||||
|
||||
### Arguments:
|
||||
|
||||
- `<name>`: Function name (e.g., `getUser`, `updateProfile`, `deletePost`)
|
||||
- `<method>`: HTTP method (`GET`, `POST`, `PUT`, `DELETE`)
|
||||
- `[options]`: Optional flags:
|
||||
- `--binding <type>`: Cloudflare binding to use (kv, d1, r2, do)
|
||||
- `--validate`: Include Zod validation
|
||||
- `--cache`: Add caching strategy (for GET requests)
|
||||
|
||||
### Examples:
|
||||
|
||||
```bash
|
||||
# Create GET function with D1 binding
|
||||
/es-tanstack-server-fn getUser GET --binding d1
|
||||
|
||||
# Create POST function with validation
|
||||
/es-tanstack-server-fn createUser POST --binding d1 --validate
|
||||
|
||||
# Create GET function with KV caching
|
||||
/es-tanstack-server-fn getSettings GET --binding kv --cache
|
||||
```
|
||||
|
||||
## Main Tasks
|
||||
|
||||
### 1. Generate Server Function
|
||||
|
||||
**Query (GET)**:
|
||||
|
||||
```typescript
|
||||
// src/lib/server-functions/getUser.ts
|
||||
import { createServerFn } from '@tanstack/start'
|
||||
import { z } from 'zod'
|
||||
|
||||
const inputSchema = z.string()
|
||||
|
||||
export const getUser = createServerFn(
|
||||
'GET',
|
||||
async (id: string, context) => {
|
||||
// Validate input
|
||||
const validId = inputSchema.parse(id)
|
||||
|
||||
const { env } = context.cloudflare
|
||||
|
||||
const user = await env.DB.prepare(
|
||||
'SELECT * FROM users WHERE id = ?'
|
||||
).bind(validId).first()
|
||||
|
||||
if (!user) {
|
||||
throw new Error('User not found')
|
||||
}
|
||||
|
||||
return user
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
**Mutation (POST)**:
|
||||
|
||||
```typescript
|
||||
// src/lib/server-functions/createUser.ts
|
||||
import { createServerFn } from '@tanstack/start'
|
||||
import { z } from 'zod'
|
||||
|
||||
const inputSchema = z.object({
|
||||
name: z.string().min(2).max(100),
|
||||
email: z.string().email(),
|
||||
})
|
||||
|
||||
export const createUser = createServerFn(
|
||||
'POST',
|
||||
async (data: z.infer<typeof inputSchema>, context) => {
|
||||
// Validate input
|
||||
const validData = inputSchema.parse(data)
|
||||
|
||||
const { env } = context.cloudflare
|
||||
|
||||
const result = await env.DB.prepare(
|
||||
'INSERT INTO users (name, email) VALUES (?, ?)'
|
||||
).bind(validData.name, validData.email).run()
|
||||
|
||||
return {
|
||||
id: result.meta.last_row_id,
|
||||
...validData
|
||||
}
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
**With KV Caching**:
|
||||
|
||||
```typescript
|
||||
// src/lib/server-functions/getSettings.ts
|
||||
import { createServerFn } from '@tanstack/start'
|
||||
|
||||
export const getSettings = createServerFn(
|
||||
'GET',
|
||||
async (userId: string, context) => {
|
||||
const { env } = context.cloudflare
|
||||
|
||||
// Check cache first
|
||||
const cached = await env.CACHE.get(`settings:${userId}`)
|
||||
if (cached) {
|
||||
return JSON.parse(cached)
|
||||
}
|
||||
|
||||
// Fetch from D1
|
||||
const settings = await env.DB.prepare(
|
||||
'SELECT * FROM settings WHERE user_id = ?'
|
||||
).bind(userId).first()
|
||||
|
||||
// Cache for 1 hour
|
||||
await env.CACHE.put(
|
||||
`settings:${userId}`,
|
||||
JSON.stringify(settings),
|
||||
{ expirationTtl: 3600 }
|
||||
)
|
||||
|
||||
return settings
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
### 2. Generate Usage Example
|
||||
|
||||
```tsx
|
||||
// src/components/UserProfile.tsx
|
||||
import { getUser } from '@/lib/server-functions/getUser'
|
||||
|
||||
export async function UserProfile({ id }: { id: string }) {
|
||||
const user = await getUser(id)
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h1>{user.name}</h1>
|
||||
<p>{user.email}</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Generate Tests
|
||||
|
||||
```typescript
|
||||
// src/lib/server-functions/__tests__/getUser.test.ts
|
||||
import { describe, it, expect, vi } from 'vitest'
|
||||
import { getUser } from '../getUser'
|
||||
|
||||
describe('getUser', () => {
|
||||
it('should fetch user from database', async () => {
|
||||
const mockContext = {
|
||||
cloudflare: {
|
||||
env: {
|
||||
DB: {
|
||||
prepare: vi.fn().mockReturnValue({
|
||||
bind: vi.fn().mockReturnValue({
|
||||
first: vi.fn().mockResolvedValue({
|
||||
id: '1',
|
||||
name: 'John Doe',
|
||||
email: 'john@example.com',
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
const user = await getUser('1', mockContext)
|
||||
|
||||
expect(user).toEqual({
|
||||
id: '1',
|
||||
name: 'John Doe',
|
||||
email: 'john@example.com',
|
||||
})
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
## Success Criteria
|
||||
|
||||
✅ Server function generated with correct method
|
||||
✅ Cloudflare bindings accessible
|
||||
✅ Input validation with Zod
|
||||
✅ Error handling implemented
|
||||
✅ TypeScript types defined
|
||||
✅ Usage example provided
|
||||
✅ Tests generated (optional)
|
||||
493
commands/es-test-gen.md
Normal file
493
commands/es-test-gen.md
Normal file
@@ -0,0 +1,493 @@
|
||||
---
|
||||
description: Generate Playwright E2E tests for Tanstack Start routes, server functions, and components
|
||||
---
|
||||
|
||||
# Playwright Test Generator Command
|
||||
|
||||
<command_purpose> Automatically generate comprehensive Playwright tests for Tanstack Start routes, server functions, and components with Cloudflare Workers-specific patterns. </command_purpose>
|
||||
|
||||
## Introduction
|
||||
|
||||
<role>Senior QA Engineer specializing in test generation for Tanstack Start applications</role>
|
||||
|
||||
This command generates ready-to-use Playwright tests that cover:
|
||||
- TanStack Router route loading and navigation
|
||||
- Server function calls with Cloudflare bindings
|
||||
- Component interactions
|
||||
- Accessibility validation
|
||||
- Error handling
|
||||
- Loading states
|
||||
|
||||
## Prerequisites
|
||||
|
||||
<requirements>
|
||||
- Playwright installed (`/es-test-setup`)
|
||||
- Tanstack Start project
|
||||
- Route or component to test
|
||||
</requirements>
|
||||
|
||||
## Command Usage
|
||||
|
||||
```bash
|
||||
/es-test-gen <target> [options]
|
||||
```
|
||||
|
||||
### Arguments:
|
||||
|
||||
- `<target>`: What to generate tests for
|
||||
- Route path: `/users/$id`, `/dashboard`, `/blog`
|
||||
- Server function: `src/lib/server-functions/createUser.ts`
|
||||
- Component: `src/components/UserCard.tsx`
|
||||
|
||||
- `[options]`: Optional flags:
|
||||
- `--with-auth`: Include authentication tests
|
||||
- `--with-server-fn`: Include server function tests
|
||||
- `--with-a11y`: Include accessibility tests (default: true)
|
||||
- `--output <path>`: Custom output path
|
||||
|
||||
### Examples:
|
||||
|
||||
```bash
|
||||
# Generate tests for a route
|
||||
/es-test-gen /users/$id
|
||||
|
||||
# Generate tests for server function
|
||||
/es-test-gen src/lib/server-functions/createUser.ts --with-auth
|
||||
|
||||
# Generate tests for component
|
||||
/es-test-gen src/components/UserCard.tsx --with-a11y
|
||||
```
|
||||
|
||||
## Main Tasks
|
||||
|
||||
### 1. Analyze Target
|
||||
|
||||
<thinking>
|
||||
Parse the target to understand what type of tests to generate.
|
||||
</thinking>
|
||||
|
||||
```bash
|
||||
# Determine target type
|
||||
if [[ "$TARGET" == /* ]]; then
|
||||
TYPE="route"
|
||||
elif [[ "$TARGET" == *server-functions* ]]; then
|
||||
TYPE="server-function"
|
||||
elif [[ "$TARGET" == *components* ]]; then
|
||||
TYPE="component"
|
||||
fi
|
||||
```
|
||||
|
||||
### 2. Generate Route Tests
|
||||
|
||||
For route: `/users/$id`
|
||||
|
||||
**Task playwright-testing-specialist(analyze route and generate tests)**:
|
||||
- Identify dynamic parameters
|
||||
- Detect loaders and data dependencies
|
||||
- Check for authentication requirements
|
||||
- Generate test cases
|
||||
|
||||
**Output**: `e2e/routes/users.$id.spec.ts`
|
||||
|
||||
```typescript
|
||||
import { test, expect } from '@playwright/test'
|
||||
import AxeBuilder from '@axe-core/playwright'
|
||||
|
||||
test.describe('User Profile Page', () => {
|
||||
const testUserId = '123'
|
||||
|
||||
test('loads user profile successfully', async ({ page }) => {
|
||||
await page.goto(`/users/${testUserId}`)
|
||||
|
||||
// Wait for loader to complete
|
||||
await page.waitForSelector('[data-testid="user-profile"]')
|
||||
|
||||
// Verify user data displayed
|
||||
await expect(page.locator('h1')).toBeVisible()
|
||||
await expect(page.locator('[data-testid="user-email"]')).toBeVisible()
|
||||
})
|
||||
|
||||
test('shows loading state during navigation', async ({ page }) => {
|
||||
await page.goto('/')
|
||||
|
||||
// Navigate to user profile
|
||||
await page.click(`a[href="/users/${testUserId}"]`)
|
||||
|
||||
// Verify loading indicator
|
||||
await expect(page.locator('[data-testid="loading"]')).toBeVisible()
|
||||
|
||||
// Wait for content to load
|
||||
await expect(page.locator('[data-testid="user-profile"]')).toBeVisible()
|
||||
})
|
||||
|
||||
test('handles non-existent user (404)', async ({ page }) => {
|
||||
const response = await page.goto('/users/999999')
|
||||
|
||||
// Verify error state
|
||||
await expect(page.locator('text=/user not found/i')).toBeVisible()
|
||||
})
|
||||
|
||||
test('has no accessibility violations', async ({ page }) => {
|
||||
await page.goto(`/users/${testUserId}`)
|
||||
|
||||
const accessibilityScanResults = await new AxeBuilder({ page })
|
||||
.analyze()
|
||||
|
||||
expect(accessibilityScanResults.violations).toEqual([])
|
||||
})
|
||||
|
||||
test('navigates back correctly', async ({ page }) => {
|
||||
await page.goto(`/users/${testUserId}`)
|
||||
|
||||
// Go back
|
||||
await page.goBack()
|
||||
|
||||
// Verify we're back at previous page
|
||||
await expect(page).toHaveURL('/')
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
### 3. Generate Server Function Tests
|
||||
|
||||
For: `src/lib/server-functions/createUser.ts`
|
||||
|
||||
**Output**: `e2e/server-functions/create-user.spec.ts`
|
||||
|
||||
```typescript
|
||||
import { test, expect } from '@playwright/test'
|
||||
|
||||
test.describe('Create User Server Function', () => {
|
||||
test('creates user successfully', async ({ page }) => {
|
||||
await page.goto('/users/new')
|
||||
|
||||
// Fill form
|
||||
await page.fill('[name="name"]', 'Test User')
|
||||
await page.fill('[name="email"]', 'test@example.com')
|
||||
|
||||
// Submit (calls server function)
|
||||
await page.click('button[type="submit"]')
|
||||
|
||||
// Wait for redirect
|
||||
await page.waitForURL(/\/users\/\d+/)
|
||||
|
||||
// Verify user created
|
||||
await expect(page.locator('h1')).toContainText('Test User')
|
||||
})
|
||||
|
||||
test('validates required fields', async ({ page }) => {
|
||||
await page.goto('/users/new')
|
||||
|
||||
// Submit empty form
|
||||
await page.click('button[type="submit"]')
|
||||
|
||||
// Verify validation errors
|
||||
await expect(page.locator('[data-testid="name-error"]'))
|
||||
.toContainText(/required/i)
|
||||
})
|
||||
|
||||
test('shows loading state during submission', async ({ page }) => {
|
||||
await page.goto('/users/new')
|
||||
|
||||
await page.fill('[name="name"]', 'Test User')
|
||||
await page.fill('[name="email"]', 'test@example.com')
|
||||
|
||||
// Start submission
|
||||
await page.click('button[type="submit"]')
|
||||
|
||||
// Verify loading indicator
|
||||
await expect(page.locator('button[type="submit"]')).toBeDisabled()
|
||||
await expect(page.locator('[data-testid="loading"]')).toBeVisible()
|
||||
})
|
||||
|
||||
test('handles server errors gracefully', async ({ page }) => {
|
||||
await page.goto('/users/new')
|
||||
|
||||
// Simulate server error by using invalid data
|
||||
await page.fill('[name="email"]', 'invalid-email')
|
||||
|
||||
await page.click('button[type="submit"]')
|
||||
|
||||
// Verify error message
|
||||
await expect(page.locator('[data-testid="error"]')).toBeVisible()
|
||||
})
|
||||
|
||||
test('stores data in Cloudflare D1', async ({ page, request }) => {
|
||||
await page.goto('/users/new')
|
||||
|
||||
const testEmail = `test-${Date.now()}@example.com`
|
||||
|
||||
await page.fill('[name="name"]', 'D1 Test User')
|
||||
await page.fill('[name="email"]', testEmail)
|
||||
|
||||
await page.click('button[type="submit"]')
|
||||
|
||||
// Wait for creation
|
||||
await page.waitForURL(/\/users\/\d+/)
|
||||
|
||||
// Verify data persisted (reload page)
|
||||
await page.reload()
|
||||
|
||||
await expect(page.locator('[data-testid="user-email"]'))
|
||||
.toContainText(testEmail)
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
### 4. Generate Component Tests
|
||||
|
||||
For: `src/components/UserCard.tsx`
|
||||
|
||||
**Output**: `e2e/components/user-card.spec.ts`
|
||||
|
||||
```typescript
|
||||
import { test, expect } from '@playwright/test'
|
||||
|
||||
test.describe('UserCard Component', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
// Navigate to component demo/storybook page
|
||||
await page.goto('/components/user-card-demo')
|
||||
})
|
||||
|
||||
test('renders user information correctly', async ({ page }) => {
|
||||
await expect(page.locator('[data-testid="user-card"]')).toBeVisible()
|
||||
await expect(page.locator('[data-testid="user-name"]')).toBeVisible()
|
||||
await expect(page.locator('[data-testid="user-email"]')).toBeVisible()
|
||||
})
|
||||
|
||||
test('handles click interactions', async ({ page }) => {
|
||||
await page.click('[data-testid="user-card"]')
|
||||
|
||||
// Verify click handler triggered
|
||||
await expect(page).toHaveURL(/\/users\/\d+/)
|
||||
})
|
||||
|
||||
test('displays avatar image', async ({ page }) => {
|
||||
const avatar = page.locator('[data-testid="user-avatar"]')
|
||||
|
||||
await expect(avatar).toBeVisible()
|
||||
|
||||
// Verify image loaded
|
||||
await expect(avatar).toHaveJSProperty('complete', true)
|
||||
})
|
||||
|
||||
test('has no accessibility violations', async ({ page }) => {
|
||||
const accessibilityScanResults = await new AxeBuilder({ page })
|
||||
.include('[data-testid="user-card"]')
|
||||
.analyze()
|
||||
|
||||
expect(accessibilityScanResults.violations).toEqual([])
|
||||
})
|
||||
|
||||
test('keyboard navigation works', async ({ page }) => {
|
||||
// Tab to card
|
||||
await page.keyboard.press('Tab')
|
||||
|
||||
// Verify focus
|
||||
await expect(page.locator('[data-testid="user-card"]')).toBeFocused()
|
||||
|
||||
// Press Enter
|
||||
await page.keyboard.press('Enter')
|
||||
|
||||
// Verify navigation
|
||||
await expect(page).toHaveURL(/\/users\/\d+/)
|
||||
})
|
||||
|
||||
test('matches visual snapshot', async ({ page }) => {
|
||||
await expect(page.locator('[data-testid="user-card"]'))
|
||||
.toHaveScreenshot('user-card.png')
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
### 5. Generate Authentication Tests (--with-auth)
|
||||
|
||||
**Output**: `e2e/auth/protected-route.spec.ts`
|
||||
|
||||
```typescript
|
||||
import { test, expect } from '@playwright/test'
|
||||
|
||||
test.describe('Protected Route - /users/$id', () => {
|
||||
test('redirects to login when unauthenticated', async ({ page }) => {
|
||||
await page.goto('/users/123')
|
||||
|
||||
// Should redirect to login
|
||||
await page.waitForURL(/\/login/)
|
||||
|
||||
// Verify redirect query param
|
||||
expect(page.url()).toContain('redirect=%2Fusers%2F123')
|
||||
})
|
||||
|
||||
test('allows access when authenticated', async ({ page }) => {
|
||||
// Login first
|
||||
await page.goto('/login')
|
||||
await page.fill('[name="email"]', 'test@example.com')
|
||||
await page.fill('[name="password"]', 'password123')
|
||||
await page.click('button[type="submit"]')
|
||||
|
||||
// Navigate to protected route
|
||||
await page.goto('/users/123')
|
||||
|
||||
// Should not redirect
|
||||
await expect(page).toHaveURL('/users/123')
|
||||
await expect(page.locator('[data-testid="user-profile"]')).toBeVisible()
|
||||
})
|
||||
|
||||
test('redirects to original destination after login', async ({ page }) => {
|
||||
// Try to access protected route
|
||||
await page.goto('/users/123')
|
||||
|
||||
// Should be on login page
|
||||
await page.waitForURL(/\/login/)
|
||||
|
||||
// Login
|
||||
await page.fill('[name="email"]', 'test@example.com')
|
||||
await page.fill('[name="password"]', 'password123')
|
||||
await page.click('button[type="submit"]')
|
||||
|
||||
// Should redirect back to original destination
|
||||
await expect(page).toHaveURL('/users/123')
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
### 6. Update Test Metadata
|
||||
|
||||
Add test to suite configuration:
|
||||
|
||||
```typescript
|
||||
// e2e/test-registry.ts (auto-generated)
|
||||
export const testRegistry = {
|
||||
routes: [
|
||||
'e2e/routes/users.$id.spec.ts',
|
||||
// ... other routes
|
||||
],
|
||||
serverFunctions: [
|
||||
'e2e/server-functions/create-user.spec.ts',
|
||||
// ... other server functions
|
||||
],
|
||||
components: [
|
||||
'e2e/components/user-card.spec.ts',
|
||||
// ... other components
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
### 7. Generate Test Documentation
|
||||
|
||||
**Output**: `e2e/routes/users.$id.README.md`
|
||||
|
||||
```markdown
|
||||
# User Profile Route Tests
|
||||
|
||||
## Test Coverage
|
||||
|
||||
- ✅ Route loading with valid user ID
|
||||
- ✅ Loading state during navigation
|
||||
- ✅ 404 handling for non-existent users
|
||||
- ✅ Accessibility (zero violations)
|
||||
- ✅ Back navigation
|
||||
|
||||
## Running Tests
|
||||
|
||||
```bash
|
||||
# Run all tests for this route
|
||||
pnpm test:e2e e2e/routes/users.$id.spec.ts
|
||||
|
||||
# Run specific test
|
||||
pnpm test:e2e e2e/routes/users.$id.spec.ts -g "loads user profile"
|
||||
|
||||
# Debug mode
|
||||
pnpm test:e2e:debug e2e/routes/users.$id.spec.ts
|
||||
```
|
||||
|
||||
## Test Data
|
||||
|
||||
Uses test user ID: `123` (configured in test fixtures)
|
||||
|
||||
## Dependencies
|
||||
|
||||
- Requires D1 database with test data
|
||||
- Requires user with ID 123 to exist
|
||||
```
|
||||
|
||||
## Test Generation Patterns
|
||||
|
||||
### Pattern: Dynamic Route Parameters
|
||||
|
||||
For `/blog/$category/$slug`:
|
||||
|
||||
```typescript
|
||||
test.describe('Blog Post Page', () => {
|
||||
const testCategory = 'tech'
|
||||
const testSlug = 'tanstack-start-guide'
|
||||
|
||||
test('loads blog post successfully', async ({ page }) => {
|
||||
await page.goto(`/blog/${testCategory}/${testSlug}`)
|
||||
|
||||
await expect(page.locator('article')).toBeVisible()
|
||||
await expect(page.locator('h1')).toBeVisible()
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
### Pattern: Search Params
|
||||
|
||||
For `/users?page=2&sort=name`:
|
||||
|
||||
```typescript
|
||||
test.describe('Users List with Search Params', () => {
|
||||
test('paginates users correctly', async ({ page }) => {
|
||||
await page.goto('/users?page=2')
|
||||
|
||||
// Verify page 2 content
|
||||
await expect(page.locator('[data-testid="pagination"]'))
|
||||
.toContainText('Page 2')
|
||||
})
|
||||
|
||||
test('sorts users by name', async ({ page }) => {
|
||||
await page.goto('/users?sort=name')
|
||||
|
||||
const userNames = await page.locator('[data-testid="user-name"]').allTextContents()
|
||||
|
||||
// Verify sorted
|
||||
const sorted = [...userNames].sort()
|
||||
expect(userNames).toEqual(sorted)
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
## Validation
|
||||
|
||||
After generating tests:
|
||||
|
||||
1. **Syntax check**: Verify TypeScript compiles
|
||||
2. **Dry run**: Run tests without executing
|
||||
3. **Coverage**: Ensure critical paths covered
|
||||
|
||||
```bash
|
||||
# Check syntax
|
||||
npx tsc --noEmit
|
||||
|
||||
# Dry run
|
||||
pnpm test:e2e --list
|
||||
|
||||
# Run generated tests
|
||||
pnpm test:e2e e2e/routes/users.$id.spec.ts
|
||||
```
|
||||
|
||||
## Success Criteria
|
||||
|
||||
✅ Tests generated for target
|
||||
✅ All tests pass on first run
|
||||
✅ Accessibility tests included
|
||||
✅ Error handling covered
|
||||
✅ Loading states tested
|
||||
✅ Documentation generated
|
||||
✅ Test registered in test suite
|
||||
|
||||
## Resources
|
||||
|
||||
- **Playwright Best Practices**: https://playwright.dev/docs/best-practices
|
||||
- **Testing TanStack Router**: https://tanstack.com/router/latest/docs/framework/react/guide/testing
|
||||
- **Accessibility Testing**: https://playwright.dev/docs/accessibility-testing
|
||||
491
commands/es-test-setup.md
Normal file
491
commands/es-test-setup.md
Normal file
@@ -0,0 +1,491 @@
|
||||
---
|
||||
description: Initialize Playwright E2E testing for Tanstack Start projects with Cloudflare Workers-specific configuration
|
||||
---
|
||||
|
||||
# Playwright Test Setup Command
|
||||
|
||||
<command_purpose> Configure Playwright for end-to-end testing in Tanstack Start projects deployed to Cloudflare Workers. Sets up test infrastructure, accessibility testing, and Workers-specific patterns. </command_purpose>
|
||||
|
||||
## Introduction
|
||||
|
||||
<role>Senior QA Engineer specializing in Playwright setup for Tanstack Start + Cloudflare Workers applications</role>
|
||||
|
||||
This command initializes a complete Playwright testing setup optimized for:
|
||||
- Tanstack Start (React + TanStack Router)
|
||||
- Cloudflare Workers deployment
|
||||
- Server function testing
|
||||
- Cloudflare bindings (KV, D1, R2, DO)
|
||||
- Accessibility testing
|
||||
- Performance monitoring
|
||||
|
||||
## Prerequisites
|
||||
|
||||
<requirements>
|
||||
- Tanstack Start project initialized
|
||||
- Cloudflare Workers configured (wrangler.jsonc)
|
||||
- Node.js 18+
|
||||
- npm/pnpm/yarn
|
||||
</requirements>
|
||||
|
||||
## Main Tasks
|
||||
|
||||
### 1. Verify Project Setup
|
||||
|
||||
<thinking>
|
||||
Ensure this is a Tanstack Start project before installing Playwright.
|
||||
</thinking>
|
||||
|
||||
```bash
|
||||
# Check for Tanstack Start
|
||||
if ! grep -q "@tanstack/start" package.json; then
|
||||
echo "❌ Not a Tanstack Start project"
|
||||
echo "This command requires Tanstack Start."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check for wrangler config
|
||||
if [ ! -f "wrangler.jsonc" ] && [ ! -f "wrangler.toml" ]; then
|
||||
echo "⚠️ No wrangler config found"
|
||||
echo "Playwright will be configured, but Cloudflare bindings tests may not work."
|
||||
fi
|
||||
```
|
||||
|
||||
### 2. Install Playwright Dependencies
|
||||
|
||||
```bash
|
||||
# Install Playwright and dependencies
|
||||
pnpm add -D @playwright/test @axe-core/playwright
|
||||
|
||||
# Install browsers
|
||||
npx playwright install --with-deps chromium firefox webkit
|
||||
```
|
||||
|
||||
### 3. Create Playwright Configuration
|
||||
|
||||
**File**: `playwright.config.ts`
|
||||
|
||||
```typescript
|
||||
import { defineConfig, devices } from '@playwright/test'
|
||||
|
||||
export default defineConfig({
|
||||
testDir: './e2e',
|
||||
fullyParallel: true,
|
||||
forbidOnly: !!process.env.CI,
|
||||
retries: process.env.CI ? 2 : 0,
|
||||
workers: process.env.CI ? 1 : undefined,
|
||||
|
||||
reporter: [
|
||||
['html'],
|
||||
['list'],
|
||||
process.env.CI ? ['github'] : ['list'],
|
||||
],
|
||||
|
||||
use: {
|
||||
baseURL: process.env.PLAYWRIGHT_TEST_BASE_URL || 'http://localhost:3000',
|
||||
trace: 'on-first-retry',
|
||||
screenshot: 'only-on-failure',
|
||||
video: 'retain-on-failure',
|
||||
},
|
||||
|
||||
projects: [
|
||||
{
|
||||
name: 'chromium',
|
||||
use: { ...devices['Desktop Chrome'] },
|
||||
},
|
||||
{
|
||||
name: 'firefox',
|
||||
use: { ...devices['Desktop Firefox'] },
|
||||
},
|
||||
{
|
||||
name: 'webkit',
|
||||
use: { ...devices['Desktop Safari'] },
|
||||
},
|
||||
{
|
||||
name: 'Mobile Chrome',
|
||||
use: { ...devices['Pixel 5'] },
|
||||
},
|
||||
{
|
||||
name: 'Mobile Safari',
|
||||
use: { ...devices['iPhone 12'] },
|
||||
},
|
||||
],
|
||||
|
||||
webServer: {
|
||||
command: 'pnpm dev',
|
||||
url: 'http://localhost:3000',
|
||||
reuseExistingServer: !process.env.CI,
|
||||
timeout: 120 * 1000,
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
### 4. Create Directory Structure
|
||||
|
||||
```bash
|
||||
mkdir -p e2e/{routes,server-functions,components,auth,accessibility,performance,visual,fixtures}
|
||||
```
|
||||
|
||||
### 5. Create Example Tests
|
||||
|
||||
**File**: `e2e/example.spec.ts`
|
||||
|
||||
```typescript
|
||||
import { test, expect } from '@playwright/test'
|
||||
|
||||
test.describe('Example Tests', () => {
|
||||
test('home page loads', async ({ page }) => {
|
||||
await page.goto('/')
|
||||
|
||||
await expect(page).toHaveTitle(/.*/)
|
||||
await expect(page.locator('body')).toBeVisible()
|
||||
})
|
||||
|
||||
test('has no console errors', async ({ page }) => {
|
||||
const errors: string[] = []
|
||||
|
||||
page.on('console', msg => {
|
||||
if (msg.type() === 'error') {
|
||||
errors.push(msg.text())
|
||||
}
|
||||
})
|
||||
|
||||
await page.goto('/')
|
||||
|
||||
expect(errors).toHaveLength(0)
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
**File**: `e2e/accessibility/home.spec.ts`
|
||||
|
||||
```typescript
|
||||
import { test, expect } from '@playwright/test'
|
||||
import AxeBuilder from '@axe-core/playwright'
|
||||
|
||||
test.describe('Accessibility', () => {
|
||||
test('home page has no a11y violations', async ({ page }) => {
|
||||
await page.goto('/')
|
||||
|
||||
const accessibilityScanResults = await new AxeBuilder({ page })
|
||||
.analyze()
|
||||
|
||||
expect(accessibilityScanResults.violations).toEqual([])
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
**File**: `e2e/performance/metrics.spec.ts`
|
||||
|
||||
```typescript
|
||||
import { test, expect } from '@playwright/test'
|
||||
|
||||
test.describe('Performance', () => {
|
||||
test('measures page load time', async ({ page }) => {
|
||||
const startTime = Date.now()
|
||||
await page.goto('/')
|
||||
await page.waitForLoadState('networkidle')
|
||||
const loadTime = Date.now() - startTime
|
||||
|
||||
console.log(`Page load time: ${loadTime}ms`)
|
||||
|
||||
// Cloudflare Workers should load fast
|
||||
expect(loadTime).toBeLessThan(1000)
|
||||
})
|
||||
|
||||
test('measures TTFB', async ({ page }) => {
|
||||
await page.goto('/')
|
||||
|
||||
const timing = await page.evaluate(() =>
|
||||
JSON.parse(JSON.stringify(
|
||||
performance.getEntriesByType('navigation')[0]
|
||||
))
|
||||
)
|
||||
|
||||
const ttfb = timing.responseStart - timing.requestStart
|
||||
console.log(`TTFB: ${ttfb}ms`)
|
||||
|
||||
// Time to First Byte should be fast on Workers
|
||||
expect(ttfb).toBeLessThan(200)
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
### 6. Create Test Fixtures
|
||||
|
||||
**File**: `e2e/fixtures/test-users.ts`
|
||||
|
||||
```typescript
|
||||
export const testUsers = {
|
||||
admin: {
|
||||
email: 'admin@test.com',
|
||||
password: 'admin123',
|
||||
name: 'Admin User',
|
||||
},
|
||||
regular: {
|
||||
email: 'user@test.com',
|
||||
password: 'user123',
|
||||
name: 'Regular User',
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### 7. Update package.json Scripts
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"test:e2e": "playwright test",
|
||||
"test:e2e:ui": "playwright test --ui",
|
||||
"test:e2e:debug": "playwright test --debug",
|
||||
"test:e2e:headed": "playwright test --headed",
|
||||
"test:e2e:report": "playwright show-report"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 8. Create .env.test for Cloudflare Bindings
|
||||
|
||||
**File**: `.env.test`
|
||||
|
||||
```bash
|
||||
# Cloudflare Test Environment
|
||||
CLOUDFLARE_ACCOUNT_ID=your-test-account-id
|
||||
CLOUDFLARE_API_TOKEN=your-test-api-token
|
||||
|
||||
# Test Bindings (separate from production)
|
||||
KV_NAMESPACE_ID=test-kv-namespace-id
|
||||
D1_DATABASE_ID=test-d1-database-id
|
||||
R2_BUCKET_NAME=test-r2-bucket
|
||||
|
||||
# Test Base URL
|
||||
PLAYWRIGHT_TEST_BASE_URL=http://localhost:3000
|
||||
```
|
||||
|
||||
### 9. Create GitHub Actions Workflow (Optional)
|
||||
|
||||
**File**: `.github/workflows/e2e.yml`
|
||||
|
||||
```yaml
|
||||
name: E2E Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
branches: [main]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
timeout-minutes: 60
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
|
||||
- name: Install Playwright Browsers
|
||||
run: npx playwright install --with-deps
|
||||
|
||||
- name: Run Playwright tests
|
||||
run: pnpm test:e2e
|
||||
env:
|
||||
CLOUDFLARE_ACCOUNT_ID: ${ secrets.CLOUDFLARE_ACCOUNT_ID}
|
||||
CLOUDFLARE_API_TOKEN: ${ secrets.CLOUDFLARE_API_TOKEN}
|
||||
|
||||
- name: Upload Playwright Report
|
||||
uses: actions/upload-artifact@v3
|
||||
if: always()
|
||||
with:
|
||||
name: playwright-report
|
||||
path: playwright-report/
|
||||
retention-days: 30
|
||||
```
|
||||
|
||||
### 10. Create Testing Guide
|
||||
|
||||
**File**: `e2e/README.md`
|
||||
|
||||
```markdown
|
||||
# E2E Testing Guide
|
||||
|
||||
## Running Tests
|
||||
|
||||
```bash
|
||||
# Run all tests
|
||||
pnpm test:e2e
|
||||
|
||||
# Run with UI mode
|
||||
pnpm test:e2e:ui
|
||||
|
||||
# Run specific test file
|
||||
pnpm test:e2e e2e/routes/home.spec.ts
|
||||
|
||||
# Run in headed mode (see browser)
|
||||
pnpm test:e2e:headed
|
||||
|
||||
# Debug mode
|
||||
pnpm test:e2e:debug
|
||||
```
|
||||
|
||||
## Test Organization
|
||||
|
||||
- `routes/` - Tests for TanStack Router routes
|
||||
- `server-functions/` - Tests for server functions
|
||||
- `components/` - Tests for shadcn/ui components
|
||||
- `auth/` - Authentication flow tests
|
||||
- `accessibility/` - Accessibility tests (axe-core)
|
||||
- `performance/` - Performance and load time tests
|
||||
- `visual/` - Visual regression tests
|
||||
- `fixtures/` - Test data and helpers
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Test user behavior, not implementation**
|
||||
- Focus on what users see and do
|
||||
- Avoid testing internal state
|
||||
|
||||
2. **Use data-testid for stable selectors**
|
||||
```tsx
|
||||
<button data-testid="submit-button">Submit</button>
|
||||
```
|
||||
|
||||
3. **Test with real Cloudflare bindings**
|
||||
- Use test environment bindings
|
||||
- Don't mock KV, D1, R2, DO
|
||||
|
||||
4. **Run accessibility tests on every page**
|
||||
- Zero violations policy
|
||||
- Use @axe-core/playwright
|
||||
|
||||
5. **Monitor performance metrics**
|
||||
- Cold start < 500ms
|
||||
- TTFB < 200ms
|
||||
- Bundle size < 200KB
|
||||
```
|
||||
|
||||
### 11. Add .gitignore Entries
|
||||
|
||||
```bash
|
||||
# Add to .gitignore
|
||||
cat >> .gitignore << 'EOF'
|
||||
|
||||
# Playwright
|
||||
/test-results/
|
||||
/playwright-report/
|
||||
/playwright/.cache/
|
||||
EOF
|
||||
```
|
||||
|
||||
### 12. Validation
|
||||
|
||||
**Task playwright-testing-specialist(verify setup)**:
|
||||
- Confirm Playwright installed
|
||||
- Verify browser binaries downloaded
|
||||
- Check test directory structure
|
||||
- Validate configuration file
|
||||
- Run example test to ensure setup works
|
||||
|
||||
```bash
|
||||
# Run validation
|
||||
pnpm test:e2e --reporter=list
|
||||
|
||||
# Should see:
|
||||
# ✓ example.spec.ts:5:3 › Example Tests › home page loads
|
||||
# ✓ accessibility/home.spec.ts:6:3 › Accessibility › home page has no a11y violations
|
||||
# ✓ performance/metrics.spec.ts:6:3 › Performance › measures page load time
|
||||
```
|
||||
|
||||
## Output
|
||||
|
||||
After running `/es-test-setup`, you will have:
|
||||
|
||||
✅ Playwright installed with all browsers
|
||||
✅ Test directory structure created
|
||||
✅ Configuration file (playwright.config.ts)
|
||||
✅ Example tests (routes, accessibility, performance)
|
||||
✅ Test fixtures and helpers
|
||||
✅ npm scripts for running tests
|
||||
✅ CI/CD workflow template
|
||||
✅ Testing guide documentation
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. **Run example tests**:
|
||||
```bash
|
||||
pnpm test:e2e
|
||||
```
|
||||
|
||||
2. **Generate tests for your routes**:
|
||||
```bash
|
||||
/es-test-gen /users/$id
|
||||
```
|
||||
|
||||
3. **Add tests to your workflow**:
|
||||
- Write tests as you build features
|
||||
- Run tests before deployment
|
||||
- Monitor test results in CI/CD
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Issue: "Cannot find module '@playwright/test'"
|
||||
|
||||
**Solution**:
|
||||
```bash
|
||||
pnpm install
|
||||
npx playwright install
|
||||
```
|
||||
|
||||
### Issue: "Browser not found"
|
||||
|
||||
**Solution**:
|
||||
```bash
|
||||
npx playwright install --with-deps
|
||||
```
|
||||
|
||||
### Issue: "Tests timing out"
|
||||
|
||||
**Solution**: Increase timeout in `playwright.config.ts`:
|
||||
```typescript
|
||||
export default defineConfig({
|
||||
timeout: 60 * 1000, // 60 seconds per test
|
||||
// ...
|
||||
})
|
||||
```
|
||||
|
||||
### Issue: "Accessibility violations found"
|
||||
|
||||
**Solution**: Fix the violations! Playwright will show you exactly what's wrong:
|
||||
```
|
||||
Expected: []
|
||||
Received: [
|
||||
{
|
||||
"id": "color-contrast",
|
||||
"impact": "serious",
|
||||
"description": "Ensures the contrast between foreground and background colors meets WCAG 2 AA contrast ratio thresholds",
|
||||
"nodes": [...]
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
## Resources
|
||||
|
||||
- **Playwright Docs**: https://playwright.dev
|
||||
- **Axe Accessibility**: https://github.com/dequelabs/axe-core-npm/tree/develop/packages/playwright
|
||||
- **Cloudflare Testing**: https://developers.cloudflare.com/workers/testing/
|
||||
- **Best Practices**: https://playwright.dev/docs/best-practices
|
||||
|
||||
## Success Criteria
|
||||
|
||||
✅ Playwright installed and configured
|
||||
✅ Example tests passing
|
||||
✅ Accessibility testing enabled
|
||||
✅ Performance monitoring setup
|
||||
✅ CI/CD workflow ready
|
||||
✅ Team trained on testing practices
|
||||
821
commands/es-theme.md
Normal file
821
commands/es-theme.md
Normal file
@@ -0,0 +1,821 @@
|
||||
---
|
||||
description: Generate or update custom design themes for Tailwind CSS and shadcn/ui. Creates distinctive typography, colors, animations, and design tokens to prevent generic "AI aesthetic"
|
||||
---
|
||||
|
||||
# Theme Generator Command
|
||||
|
||||
<command_purpose> Generate distinctive design themes that prevent generic aesthetics. Creates custom Tailwind configuration with unique fonts, brand colors, animation presets, and shadcn/ui customizations. Replaces Inter fonts, purple gradients, and minimal animations with branded alternatives. </command_purpose>
|
||||
|
||||
## Introduction
|
||||
|
||||
<role>Senior Design Systems Architect with expertise in Tailwind CSS theming, color theory, typography, animation design, and brand identity</role>
|
||||
|
||||
**Design Philosophy**: Establish a distinctive visual identity from the start through a comprehensive design system.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
<requirements>
|
||||
- Tanstack Start project with Tailwind CSS configured
|
||||
- shadcn/ui installed
|
||||
- Access to custom font files or Google Fonts
|
||||
- Brand color palette (or will be generated)
|
||||
</requirements>
|
||||
|
||||
## Command Usage
|
||||
|
||||
```bash
|
||||
/es-theme [options]
|
||||
```
|
||||
|
||||
### Options:
|
||||
|
||||
- `--palette <name>`: Pre-defined color palette (coral-ocean, midnight-gold, forest-sage, custom)
|
||||
- `--fonts <style>`: Font pairing style (modern, classic, playful, technical)
|
||||
- `--animations <level>`: Animation richness (minimal, standard, rich)
|
||||
- `--mode <create|update>`: Create new theme or update existing
|
||||
- `--interactive`: Launch interactive theme builder
|
||||
|
||||
### Examples:
|
||||
|
||||
```bash
|
||||
# Generate theme with coral-ocean palette and modern fonts
|
||||
/es-theme --palette coral-ocean --fonts modern --animations rich
|
||||
|
||||
# Interactive theme builder
|
||||
/es-theme --interactive
|
||||
|
||||
# Update existing theme
|
||||
/es-theme --mode update
|
||||
```
|
||||
|
||||
## Main Tasks
|
||||
|
||||
### 1. Analyze Current Theme
|
||||
|
||||
<thinking>
|
||||
First, check if a theme already exists and analyze generic patterns.
|
||||
</thinking>
|
||||
|
||||
#### Current Theme Analysis:
|
||||
|
||||
<analysis_steps>
|
||||
|
||||
- [ ] Check `tailwind.config.ts` for existing configuration
|
||||
- [ ] Detect Inter/Roboto fonts (generic ❌)
|
||||
- [ ] Detect default purple colors (generic ❌)
|
||||
- [ ] Check for custom animation presets
|
||||
- [ ] Check `app.config.ts` for shadcn/ui customization
|
||||
- [ ] Analyze existing component usage patterns
|
||||
|
||||
</analysis_steps>
|
||||
|
||||
### 2. Generate Color Palette
|
||||
|
||||
<thinking>
|
||||
Create or select a distinctive color palette that reflects brand identity.
|
||||
Ensure all colors meet WCAG 2.1 AA contrast requirements.
|
||||
</thinking>
|
||||
|
||||
#### Pre-defined Palettes:
|
||||
|
||||
<color_palettes>
|
||||
|
||||
**Coral Ocean** (Warm & Vibrant):
|
||||
```typescript
|
||||
colors: {
|
||||
brand: {
|
||||
coral: {
|
||||
50: '#FFF5F5',
|
||||
100: '#FFE3E3',
|
||||
200: '#FFC9C9',
|
||||
300: '#FFA8A8',
|
||||
400: '#FF8787',
|
||||
500: '#FF6B6B', // Primary
|
||||
600: '#FA5252',
|
||||
700: '#F03E3E',
|
||||
800: '#E03131',
|
||||
900: '#C92A2A',
|
||||
},
|
||||
ocean: {
|
||||
50: '#F0FDFA',
|
||||
100: '#CCFBF1',
|
||||
200: '#99F6E4',
|
||||
300: '#5EEAD4',
|
||||
400: '#2DD4BF',
|
||||
500: '#4ECDC4', // Secondary
|
||||
600: '#0D9488',
|
||||
700: '#0F766E',
|
||||
800: '#115E59',
|
||||
900: '#134E4A',
|
||||
},
|
||||
sunset: {
|
||||
50: '#FFFEF0',
|
||||
100: '#FFFACD',
|
||||
200: '#FFF59D',
|
||||
300: '#FFF176',
|
||||
400: '#FFEE58',
|
||||
500: '#FFE66D', // Accent
|
||||
600: '#FDD835',
|
||||
700: '#FBC02D',
|
||||
800: '#F9A825',
|
||||
900: '#F57F17',
|
||||
},
|
||||
midnight: '#2C3E50',
|
||||
cream: '#FFF5E1'
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Midnight Gold** (Elegant & Professional):
|
||||
```typescript
|
||||
colors: {
|
||||
brand: {
|
||||
midnight: {
|
||||
50: '#F8FAFC',
|
||||
100: '#F1F5F9',
|
||||
200: '#E2E8F0',
|
||||
300: '#CBD5E1',
|
||||
400: '#94A3B8',
|
||||
500: '#2C3E50', // Primary
|
||||
600: '#475569',
|
||||
700: '#334155',
|
||||
800: '#1E293B',
|
||||
900: '#0F172A',
|
||||
},
|
||||
gold: {
|
||||
50: '#FFFBEB',
|
||||
100: '#FEF3C7',
|
||||
200: '#FDE68A',
|
||||
300: '#FCD34D',
|
||||
400: '#FBBF24',
|
||||
500: '#D4AF37', // Secondary
|
||||
600: '#D97706',
|
||||
700: '#B45309',
|
||||
800: '#92400E',
|
||||
900: '#78350F',
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Forest Sage** (Natural & Calming):
|
||||
```typescript
|
||||
colors: {
|
||||
brand: {
|
||||
forest: {
|
||||
50: '#F0FDF4',
|
||||
100: '#DCFCE7',
|
||||
200: '#BBF7D0',
|
||||
300: '#86EFAC',
|
||||
400: '#4ADE80',
|
||||
500: '#2D5F3F', // Primary
|
||||
600: '#16A34A',
|
||||
700: '#15803D',
|
||||
800: '#166534',
|
||||
900: '#14532D',
|
||||
},
|
||||
sage: {
|
||||
50: '#F7F7F5',
|
||||
100: '#EAEAE5',
|
||||
200: '#D4D4C8',
|
||||
300: '#B8B8A7',
|
||||
400: '#9C9C88',
|
||||
500: '#8B9A7C', // Secondary
|
||||
600: '#6F7F63',
|
||||
700: '#5A664F',
|
||||
800: '#454D3F',
|
||||
900: '#313730',
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
</color_palettes>
|
||||
|
||||
### 3. Select Font Pairings
|
||||
|
||||
<thinking>
|
||||
Choose distinctive font combinations that avoid Inter/Roboto.
|
||||
Ensure fonts are performant and accessible.
|
||||
</thinking>
|
||||
|
||||
#### Font Pairing Styles:
|
||||
|
||||
<font_pairings>
|
||||
|
||||
**Modern** (Clean & Contemporary):
|
||||
```typescript
|
||||
fontFamily: {
|
||||
sans: ['Space Grotesk', 'system-ui', 'sans-serif'],
|
||||
heading: ['Archivo Black', 'system-ui', 'sans-serif'],
|
||||
mono: ['JetBrains Mono', 'monospace']
|
||||
}
|
||||
```
|
||||
|
||||
**Classic** (Timeless & Professional):
|
||||
```typescript
|
||||
fontFamily: {
|
||||
sans: ['Crimson Pro', 'Georgia', 'serif'],
|
||||
heading: ['Playfair Display', 'Georgia', 'serif'],
|
||||
mono: ['IBM Plex Mono', 'monospace']
|
||||
}
|
||||
```
|
||||
|
||||
**Playful** (Creative & Energetic):
|
||||
```typescript
|
||||
fontFamily: {
|
||||
sans: ['DM Sans', 'system-ui', 'sans-serif'],
|
||||
heading: ['Fredoka', 'system-ui', 'sans-serif'],
|
||||
mono: ['Fira Code', 'monospace']
|
||||
}
|
||||
```
|
||||
|
||||
**Technical** (Precise & Modern):
|
||||
```typescript
|
||||
fontFamily: {
|
||||
sans: ['Inter Display', 'system-ui', 'sans-serif'], // Display variant (different from default Inter)
|
||||
heading: ['JetBrains Mono', 'monospace'],
|
||||
mono: ['Source Code Pro', 'monospace']
|
||||
}
|
||||
```
|
||||
|
||||
</font_pairings>
|
||||
|
||||
### 4. Create Animation Presets
|
||||
|
||||
<thinking>
|
||||
Define animation utilities that create engaging, performant micro-interactions.
|
||||
</thinking>
|
||||
|
||||
#### Animation Configuration:
|
||||
|
||||
<animation_config>
|
||||
|
||||
```typescript
|
||||
// tailwind.config.ts
|
||||
export default {
|
||||
theme: {
|
||||
extend: {
|
||||
animation: {
|
||||
// Fade animations
|
||||
'fade-in': 'fadeIn 0.5s ease-out',
|
||||
'fade-out': 'fadeOut 0.3s ease-in',
|
||||
|
||||
// Slide animations
|
||||
'slide-up': 'slideUp 0.4s ease-out',
|
||||
'slide-down': 'slideDown 0.4s ease-out',
|
||||
'slide-left': 'slideLeft 0.4s ease-out',
|
||||
'slide-right': 'slideRight 0.4s ease-out',
|
||||
|
||||
// Scale animations
|
||||
'scale-in': 'scaleIn 0.3s ease-out',
|
||||
'scale-out': 'scaleOut 0.2s ease-in',
|
||||
|
||||
// Bounce animations
|
||||
'bounce-subtle': 'bounceSubtle 1s ease-in-out infinite',
|
||||
|
||||
// Pulse animations
|
||||
'pulse-slow': 'pulse 3s cubic-bezier(0.4, 0, 0.6, 1) infinite',
|
||||
'pulse-fast': 'pulse 1s cubic-bezier(0.4, 0, 0.6, 1) infinite',
|
||||
|
||||
// Spin animations
|
||||
'spin-slow': 'spin 3s linear infinite',
|
||||
'spin-fast': 'spin 0.5s linear infinite',
|
||||
},
|
||||
|
||||
keyframes: {
|
||||
fadeIn: {
|
||||
'0%': { opacity: '0' },
|
||||
'100%': { opacity: '1' },
|
||||
},
|
||||
fadeOut: {
|
||||
'0%': { opacity: '1' },
|
||||
'100%': { opacity: '0' },
|
||||
},
|
||||
slideUp: {
|
||||
'0%': { transform: 'translateY(20px)', opacity: '0' },
|
||||
'100%': { transform: 'translateY(0)', opacity: '1' },
|
||||
},
|
||||
slideDown: {
|
||||
'0%': { transform: 'translateY(-20px)', opacity: '0' },
|
||||
'100%': { transform: 'translateY(0)', opacity: '1' },
|
||||
},
|
||||
slideLeft: {
|
||||
'0%': { transform: 'translateX(20px)', opacity: '0' },
|
||||
'100%': { transform: 'translateX(0)', opacity: '1' },
|
||||
},
|
||||
slideRight: {
|
||||
'0%': { transform: 'translateX(-20px)', opacity: '0' },
|
||||
'100%': { transform: 'translateX(0)', opacity: '1' },
|
||||
},
|
||||
scaleIn: {
|
||||
'0%': { transform: 'scale(0.9)', opacity: '0' },
|
||||
'100%': { transform: 'scale(1)', opacity: '1' },
|
||||
},
|
||||
scaleOut: {
|
||||
'0%': { transform: 'scale(1)', opacity: '1' },
|
||||
'100%': { transform: 'scale(0.9)', opacity: '0' },
|
||||
},
|
||||
bounceSubtle: {
|
||||
'0%, 100%': { transform: 'translateY(0)' },
|
||||
'50%': { transform: 'translateY(-5px)' },
|
||||
},
|
||||
},
|
||||
|
||||
// Transition duration extensions
|
||||
transitionDuration: {
|
||||
'400': '400ms',
|
||||
'600': '600ms',
|
||||
'800': '800ms',
|
||||
'900': '900ms',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
</animation_config>
|
||||
|
||||
### 5. Generate Complete Theme Configuration
|
||||
|
||||
<thinking>
|
||||
Create complete tailwind.config.ts with all theme customizations.
|
||||
</thinking>
|
||||
|
||||
#### Generated Tailwind Config:
|
||||
|
||||
<tailwind_config_template>
|
||||
|
||||
```typescript
|
||||
// tailwind.config.ts
|
||||
import type { Config } from 'tailwindcss';
|
||||
import defaultTheme from 'tailwindcss/defaultTheme';
|
||||
|
||||
export default <Partial<Config>>{
|
||||
theme: {
|
||||
extend: {
|
||||
// Typography
|
||||
fontFamily: {
|
||||
sans: ['Space Grotesk', ...defaultTheme.fontFamily.sans],
|
||||
heading: ['Archivo Black', ...defaultTheme.fontFamily.sans],
|
||||
mono: ['JetBrains Mono', ...defaultTheme.fontFamily.mono],
|
||||
},
|
||||
|
||||
fontSize: {
|
||||
// Extended font sizes with line heights
|
||||
'2xs': ['0.625rem', { lineHeight: '0.75rem' }],
|
||||
'6xl': ['3.75rem', { lineHeight: '1', letterSpacing: '-0.02em' }],
|
||||
'7xl': ['4.5rem', { lineHeight: '1', letterSpacing: '-0.02em' }],
|
||||
'8xl': ['6rem', { lineHeight: '1', letterSpacing: '-0.02em' }],
|
||||
'9xl': ['8rem', { lineHeight: '1', letterSpacing: '-0.02em' }],
|
||||
},
|
||||
|
||||
// Brand Colors
|
||||
colors: {
|
||||
brand: {
|
||||
coral: {
|
||||
DEFAULT: '#FF6B6B',
|
||||
50: '#FFF5F5',
|
||||
100: '#FFE3E3',
|
||||
200: '#FFC9C9',
|
||||
300: '#FFA8A8',
|
||||
400: '#FF8787',
|
||||
500: '#FF6B6B',
|
||||
600: '#FA5252',
|
||||
700: '#F03E3E',
|
||||
800: '#E03131',
|
||||
900: '#C92A2A',
|
||||
},
|
||||
ocean: {
|
||||
DEFAULT: '#4ECDC4',
|
||||
50: '#F0FDFA',
|
||||
100: '#CCFBF1',
|
||||
200: '#99F6E4',
|
||||
300: '#5EEAD4',
|
||||
400: '#2DD4BF',
|
||||
500: '#4ECDC4',
|
||||
600: '#0D9488',
|
||||
700: '#0F766E',
|
||||
800: '#115E59',
|
||||
900: '#134E4A',
|
||||
},
|
||||
sunset: {
|
||||
DEFAULT: '#FFE66D',
|
||||
50: '#FFFEF0',
|
||||
100: '#FFFACD',
|
||||
200: '#FFF59D',
|
||||
300: '#FFF176',
|
||||
400: '#FFEE58',
|
||||
500: '#FFE66D',
|
||||
600: '#FDD835',
|
||||
700: '#FBC02D',
|
||||
800: '#F9A825',
|
||||
900: '#F57F17',
|
||||
},
|
||||
midnight: {
|
||||
DEFAULT: '#2C3E50',
|
||||
50: '#F8FAFC',
|
||||
100: '#F1F5F9',
|
||||
200: '#E2E8F0',
|
||||
300: '#CBD5E1',
|
||||
400: '#94A3B8',
|
||||
500: '#2C3E50',
|
||||
600: '#475569',
|
||||
700: '#334155',
|
||||
800: '#1E293B',
|
||||
900: '#0F172A',
|
||||
},
|
||||
cream: {
|
||||
DEFAULT: '#FFF5E1',
|
||||
50: '#FFFEF7',
|
||||
100: '#FFFCEB',
|
||||
200: '#FFF9D6',
|
||||
300: '#FFF5E1',
|
||||
400: '#FFF0C4',
|
||||
500: '#FFEBA7',
|
||||
600: '#FFE68A',
|
||||
700: '#FFE06D',
|
||||
800: '#FFDB50',
|
||||
900: '#FFD633',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// Spacing extensions
|
||||
spacing: {
|
||||
'18': '4.5rem',
|
||||
'22': '5.5rem',
|
||||
'26': '6.5rem',
|
||||
'30': '7.5rem',
|
||||
'34': '8.5rem',
|
||||
'38': '9.5rem',
|
||||
'42': '10.5rem',
|
||||
'46': '11.5rem',
|
||||
'50': '12.5rem',
|
||||
'54': '13.5rem',
|
||||
'58': '14.5rem',
|
||||
'62': '15.5rem',
|
||||
'66': '16.5rem',
|
||||
'70': '17.5rem',
|
||||
'74': '18.5rem',
|
||||
'78': '19.5rem',
|
||||
'82': '20.5rem',
|
||||
'86': '21.5rem',
|
||||
'90': '22.5rem',
|
||||
'94': '23.5rem',
|
||||
'98': '24.5rem',
|
||||
},
|
||||
|
||||
// Box shadows
|
||||
boxShadow: {
|
||||
'brand-sm': '0 2px 8px rgba(255, 107, 107, 0.1)',
|
||||
'brand': '0 4px 20px rgba(255, 107, 107, 0.2)',
|
||||
'brand-lg': '0 10px 40px rgba(255, 107, 107, 0.3)',
|
||||
'ocean-sm': '0 2px 8px rgba(78, 205, 196, 0.1)',
|
||||
'ocean': '0 4px 20px rgba(78, 205, 196, 0.2)',
|
||||
'ocean-lg': '0 10px 40px rgba(78, 205, 196, 0.3)',
|
||||
'elevated': '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)',
|
||||
},
|
||||
|
||||
// Border radius
|
||||
borderRadius: {
|
||||
'4xl': '2rem',
|
||||
'5xl': '2.5rem',
|
||||
'6xl': '3rem',
|
||||
},
|
||||
|
||||
// Animations (from animation config above)
|
||||
animation: {
|
||||
'fade-in': 'fadeIn 0.5s ease-out',
|
||||
'fade-out': 'fadeOut 0.3s ease-in',
|
||||
'slide-up': 'slideUp 0.4s ease-out',
|
||||
'slide-down': 'slideDown 0.4s ease-out',
|
||||
'slide-left': 'slideLeft 0.4s ease-out',
|
||||
'slide-right': 'slideRight 0.4s ease-out',
|
||||
'scale-in': 'scaleIn 0.3s ease-out',
|
||||
'scale-out': 'scaleOut 0.2s ease-in',
|
||||
'bounce-subtle': 'bounceSubtle 1s ease-in-out infinite',
|
||||
'pulse-slow': 'pulse 3s cubic-bezier(0.4, 0, 0.6, 1) infinite',
|
||||
'pulse-fast': 'pulse 1s cubic-bezier(0.4, 0, 0.6, 1) infinite',
|
||||
'spin-slow': 'spin 3s linear infinite',
|
||||
'spin-fast': 'spin 0.5s linear infinite',
|
||||
},
|
||||
|
||||
keyframes: {
|
||||
fadeIn: {
|
||||
'0%': { opacity: '0' },
|
||||
'100%': { opacity: '1' },
|
||||
},
|
||||
fadeOut: {
|
||||
'0%': { opacity: '1' },
|
||||
'100%': { opacity: '0' },
|
||||
},
|
||||
slideUp: {
|
||||
'0%': { transform: 'translateY(20px)', opacity: '0' },
|
||||
'100%': { transform: 'translateY(0)', opacity: '1' },
|
||||
},
|
||||
slideDown: {
|
||||
'0%': { transform: 'translateY(-20px)', opacity: '0' },
|
||||
'100%': { transform: 'translateY(0)', opacity: '1' },
|
||||
},
|
||||
slideLeft: {
|
||||
'0%': { transform: 'translateX(20px)', opacity: '0' },
|
||||
'100%': { transform: 'translateX(0)', opacity: '1' },
|
||||
},
|
||||
slideRight: {
|
||||
'0%': { transform: 'translateX(-20px)', opacity: '0' },
|
||||
'100%': { transform: 'translateX(0)', opacity: '1' },
|
||||
},
|
||||
scaleIn: {
|
||||
'0%': { transform: 'scale(0.9)', opacity: '0' },
|
||||
'100%': { transform: 'scale(1)', opacity: '1' },
|
||||
},
|
||||
scaleOut: {
|
||||
'0%': { transform: 'scale(1)', opacity: '1' },
|
||||
'100%': { transform: 'scale(0.9)', opacity: '0' },
|
||||
},
|
||||
bounceSubtle: {
|
||||
'0%, 100%': { transform: 'translateY(0)' },
|
||||
'50%': { transform: 'translateY(-5px)' },
|
||||
},
|
||||
},
|
||||
|
||||
// Transition durations
|
||||
transitionDuration: {
|
||||
'400': '400ms',
|
||||
'600': '600ms',
|
||||
'800': '800ms',
|
||||
'900': '900ms',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
</tailwind_config_template>
|
||||
|
||||
### 6. Generate shadcn/ui Theme Customization
|
||||
|
||||
<thinking>
|
||||
Create app.config.ts with global shadcn/ui customizations.
|
||||
</thinking>
|
||||
|
||||
#### shadcn/ui Config:
|
||||
|
||||
<shadcn_ui_config>
|
||||
|
||||
```typescript
|
||||
// app.config.ts
|
||||
export default defineAppConfig({
|
||||
ui: {
|
||||
// Primary color (used by shadcn/ui components)
|
||||
primary: 'brand-coral',
|
||||
secondary: 'brand-ocean',
|
||||
gray: 'neutral',
|
||||
|
||||
// Global component customization
|
||||
button: {
|
||||
default: {
|
||||
size: 'md',
|
||||
color: 'primary',
|
||||
variant: 'solid',
|
||||
},
|
||||
rounded: 'rounded-lg',
|
||||
font: 'font-heading tracking-wide',
|
||||
},
|
||||
|
||||
card: {
|
||||
background: 'bg-white dark:bg-brand-midnight-800',
|
||||
rounded: 'rounded-2xl',
|
||||
shadow: 'shadow-lg',
|
||||
ring: 'ring-1 ring-gray-200 dark:ring-gray-700',
|
||||
},
|
||||
|
||||
input: {
|
||||
rounded: 'rounded-lg',
|
||||
padding: {
|
||||
sm: 'px-4 py-2',
|
||||
md: 'px-4 py-3',
|
||||
lg: 'px-6 py-4',
|
||||
},
|
||||
},
|
||||
|
||||
modal: {
|
||||
rounded: 'rounded-2xl',
|
||||
shadow: 'shadow-2xl',
|
||||
background: 'bg-white dark:bg-brand-midnight-800',
|
||||
},
|
||||
|
||||
// Notification settings
|
||||
notifications: {
|
||||
position: 'top-right',
|
||||
},
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
</shadcn_ui_config>
|
||||
|
||||
### 7. Update Font Loading
|
||||
|
||||
<thinking>
|
||||
Configure font loading in app.config.ts (Google Fonts or local fonts).
|
||||
</thinking>
|
||||
|
||||
#### Font Loading Config:
|
||||
|
||||
<font_loading>
|
||||
|
||||
```typescript
|
||||
// app.config.ts
|
||||
export default defineNuxtConfig({
|
||||
// ... other config
|
||||
|
||||
// Option 1: Google Fonts (recommended for quick setup)
|
||||
googleFonts: {
|
||||
families: {
|
||||
'Space Grotesk': [400, 500, 600, 700],
|
||||
'Archivo Black': [400],
|
||||
'JetBrains Mono': [400, 500, 600, 700],
|
||||
},
|
||||
display: 'swap', // Prevent FOIT (Flash of Invisible Text)
|
||||
preload: true,
|
||||
},
|
||||
|
||||
// Option 2: Local fonts (better performance)
|
||||
css: ['~/assets/fonts/fonts.css'],
|
||||
|
||||
// ... other config
|
||||
});
|
||||
```
|
||||
|
||||
```css
|
||||
/* assets/fonts/fonts.css (if using local fonts) */
|
||||
@font-face {
|
||||
font-family: 'Space Grotesk';
|
||||
src: url('/fonts/SpaceGrotesk-Variable.woff2') format('woff2-variations');
|
||||
font-weight: 300 700;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Archivo Black';
|
||||
src: url('/fonts/ArchivoBlack-Regular.woff2') format('woff2');
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'JetBrains Mono';
|
||||
src: url('/fonts/JetBrainsMono-Variable.woff2') format('woff2-variations');
|
||||
font-weight: 400 700;
|
||||
font-display: swap;
|
||||
}
|
||||
```
|
||||
|
||||
</font_loading>
|
||||
|
||||
## Output Format
|
||||
|
||||
<output_format>
|
||||
|
||||
```
|
||||
✅ Custom Theme Generated
|
||||
|
||||
📁 Files Created/Updated:
|
||||
- tailwind.config.ts (complete theme configuration)
|
||||
- app.config.ts (shadcn/ui global customization)
|
||||
- app.config.ts (font loading configuration)
|
||||
- assets/fonts/fonts.css (if using local fonts)
|
||||
|
||||
🎨 Theme Summary:
|
||||
|
||||
**Color Palette**: Coral Ocean
|
||||
- Primary: Coral (#FF6B6B) - Warm, energetic
|
||||
- Secondary: Ocean (#4ECDC4) - Calm, trustworthy
|
||||
- Accent: Sunset (#FFE66D) - Bright, attention-grabbing
|
||||
- Neutral: Midnight (#2C3E50) - Professional, elegant
|
||||
- Background: Cream (#FFF5E1) - Soft, inviting
|
||||
|
||||
**Typography**: Modern
|
||||
- Sans: Space Grotesk (body text, UI elements)
|
||||
- Heading: Archivo Black (headings, impact text)
|
||||
- Mono: JetBrains Mono (code, technical content)
|
||||
|
||||
**Animations**: Rich
|
||||
- 15 custom animation presets
|
||||
- Performant (GPU-accelerated properties only)
|
||||
- Respects prefers-reduced-motion
|
||||
|
||||
**Accessibility**: WCAG 2.1 AA Compliant
|
||||
✅ All color combinations meet 4.5:1 contrast ratio
|
||||
✅ Focus states on all interactive elements
|
||||
✅ Reduced motion support built-in
|
||||
|
||||
---
|
||||
|
||||
📖 Usage Examples:
|
||||
|
||||
**Typography**:
|
||||
```tsx
|
||||
<h1 class="font-heading text-6xl text-brand-midnight">
|
||||
Heading
|
||||
</h1>
|
||||
|
||||
<p class="font-sans text-lg text-gray-700">
|
||||
Body text
|
||||
</p>
|
||||
|
||||
<code class="font-mono text-sm text-brand-coral-600">
|
||||
Code snippet
|
||||
</code>
|
||||
```
|
||||
|
||||
**Colors**:
|
||||
```tsx
|
||||
<div class="bg-brand-coral text-white">
|
||||
Primary action
|
||||
</div>
|
||||
|
||||
<div class="bg-brand-ocean text-white">
|
||||
Secondary action
|
||||
</div>
|
||||
|
||||
<div class="bg-gradient-to-br from-brand-coral via-brand-ocean to-brand-sunset">
|
||||
Gradient background
|
||||
</div>
|
||||
```
|
||||
|
||||
**Animations**:
|
||||
```tsx
|
||||
<div class="animate-slide-up">
|
||||
Slides up on mount
|
||||
</div>
|
||||
|
||||
<button class="transition-all hover:scale-105 hover:shadow-brand-lg">
|
||||
Animated button
|
||||
</button>
|
||||
|
||||
<div class="animate-pulse-slow">
|
||||
Subtle pulse
|
||||
</div>
|
||||
```
|
||||
|
||||
**shadcn/ui with Theme**:
|
||||
```tsx
|
||||
<!-- Automatically uses theme colors -->
|
||||
<Button color="primary">
|
||||
Uses brand-coral
|
||||
</Button>
|
||||
|
||||
<Card class="shadow-brand">
|
||||
Uses theme shadows
|
||||
</Card>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
🔍 Next Steps:
|
||||
1. ✅ Review `tailwind.config.ts` for customizations
|
||||
2. ✅ Test theme with `/es-component button TestButton`
|
||||
3. ✅ Run `/es-design-review` to validate distinctiveness
|
||||
4. ✅ Update existing components to use new theme
|
||||
5. ✅ Test dark mode support
|
||||
6. ✅ Verify WCAG contrast ratios
|
||||
|
||||
📊 Distinctiveness Improvement:
|
||||
- Before: 35/100 (Generic Inter + Purple)
|
||||
- After: 90/100 (Distinctive brand theme)
|
||||
|
||||
Your project now has a distinctive visual identity! 🎨
|
||||
```
|
||||
|
||||
</output_format>
|
||||
|
||||
## Success Criteria
|
||||
|
||||
✅ Theme generated successfully when:
|
||||
- `tailwind.config.ts` has custom fonts (not Inter/Roboto)
|
||||
- Custom color palette defined (not default purple)
|
||||
- 15+ animation presets created
|
||||
- All colors meet WCAG 2.1 AA contrast requirements
|
||||
- Fonts configured in `app.config.ts`
|
||||
- shadcn/ui customization in `app.config.ts`
|
||||
- Design system composable updated
|
||||
|
||||
## Post-Generation Actions
|
||||
|
||||
After generating theme:
|
||||
1. **Test theme**: Create test component with `/es-component`
|
||||
2. **Validate design**: Run `/es-design-review`
|
||||
3. **Check accessibility**: Verify contrast ratios
|
||||
4. **Update components**: Apply theme to existing components
|
||||
5. **Document**: Add theme documentation to project
|
||||
|
||||
## Notes
|
||||
|
||||
- Theme replaces generic patterns (Inter, purple) with distinctive alternatives
|
||||
- All colors are contrast-validated for accessibility
|
||||
- Animations respect `prefers-reduced-motion`
|
||||
- Theme is fully customizable after generation
|
||||
- Works seamlessly with shadcn/ui components
|
||||
238
commands/es-triage.md
Normal file
238
commands/es-triage.md
Normal file
@@ -0,0 +1,238 @@
|
||||
---
|
||||
description: Triage findings and decisions to add to the CLI todo system
|
||||
---
|
||||
|
||||
Present all findings, decisions, or issues here one by one for triage. The goal is to go through each item and decide whether to add it to the CLI todo system.
|
||||
|
||||
**IMPORTANT: DO NOT CODE ANYTHING DURING TRIAGE!**
|
||||
|
||||
This command is for:
|
||||
- Triaging code review findings
|
||||
- Processing security audit results
|
||||
- Reviewing performance analysis
|
||||
- Handling any other categorized findings that need tracking
|
||||
|
||||
## Workflow
|
||||
|
||||
### Step 1: Present Each Finding
|
||||
|
||||
For each finding, present in this format:
|
||||
|
||||
```
|
||||
---
|
||||
Issue #X: [Brief Title]
|
||||
|
||||
Severity: 🔴 P1 (CRITICAL) / 🟡 P2 (IMPORTANT) / 🔵 P3 (NICE-TO-HAVE)
|
||||
|
||||
Category: [Security/Performance/Architecture/Bug/Feature/etc.]
|
||||
|
||||
Description:
|
||||
[Detailed explanation of the issue or improvement]
|
||||
|
||||
Location: [file_path:line_number]
|
||||
|
||||
Problem Scenario:
|
||||
[Step by step what's wrong or could happen]
|
||||
|
||||
Proposed Solution:
|
||||
[How to fix it]
|
||||
|
||||
Estimated Effort: [Small (< 2 hours) / Medium (2-8 hours) / Large (> 8 hours)]
|
||||
|
||||
---
|
||||
Do you want to add this to the todo list?
|
||||
1. yes - create todo file
|
||||
2. next - skip this item
|
||||
3. custom - modify before creating
|
||||
```
|
||||
|
||||
### Step 2: Handle User Decision
|
||||
|
||||
**When user says "yes":**
|
||||
|
||||
1. **Determine next issue ID:**
|
||||
```bash
|
||||
ls todos/ | grep -o '^[0-9]\+' | sort -n | tail -1
|
||||
```
|
||||
|
||||
2. **Create filename:**
|
||||
```
|
||||
{next_id}-pending-{priority}-{brief-description}.md
|
||||
```
|
||||
|
||||
Priority mapping:
|
||||
- 🔴 P1 (CRITICAL) → `p1`
|
||||
- 🟡 P2 (IMPORTANT) → `p2`
|
||||
- 🔵 P3 (NICE-TO-HAVE) → `p3`
|
||||
|
||||
Example: `042-pending-p1-transaction-boundaries.md`
|
||||
|
||||
3. **Create from template:**
|
||||
```bash
|
||||
cp todos/000-pending-p1-TEMPLATE.md todos/{new_filename}
|
||||
```
|
||||
|
||||
4. **Populate the file:**
|
||||
```yaml
|
||||
---
|
||||
status: pending
|
||||
priority: p1 # or p2, p3 based on severity
|
||||
issue_id: "042"
|
||||
tags: [category, workers, durable-objects, kv, r2, etc.]
|
||||
dependencies: []
|
||||
---
|
||||
|
||||
# [Issue Title]
|
||||
|
||||
## Problem Statement
|
||||
[Description from finding]
|
||||
|
||||
## Findings
|
||||
- [Key discoveries]
|
||||
- Location: [file_path:line_number]
|
||||
- [Scenario details]
|
||||
|
||||
## Proposed Solutions
|
||||
|
||||
### Option 1: [Primary solution]
|
||||
- **Pros**: [Benefits]
|
||||
- **Cons**: [Drawbacks if any]
|
||||
- **Effort**: [Small/Medium/Large]
|
||||
- **Risk**: [Low/Medium/High]
|
||||
|
||||
## Recommended Action
|
||||
[Leave blank - will be filled during approval]
|
||||
|
||||
## Technical Details
|
||||
- **Affected Files**: [List files]
|
||||
- **Related Components**: [Components affected]
|
||||
- **Database Changes**: [Yes/No - describe if yes]
|
||||
|
||||
## Resources
|
||||
- Original finding: [Source of this issue]
|
||||
- Related issues: [If any]
|
||||
|
||||
## Acceptance Criteria
|
||||
- [ ] [Specific success criteria]
|
||||
- [ ] Tests pass
|
||||
- [ ] Code reviewed
|
||||
|
||||
## Work Log
|
||||
|
||||
### {date} - Initial Discovery
|
||||
**By:** Claude Triage System
|
||||
**Actions:**
|
||||
- Issue discovered during [triage session type]
|
||||
- Categorized as {severity}
|
||||
- Estimated effort: {effort}
|
||||
|
||||
**Learnings:**
|
||||
- [Context and insights]
|
||||
|
||||
## Notes
|
||||
Source: Triage session on {date}
|
||||
```
|
||||
|
||||
5. **Confirm creation:**
|
||||
"✅ Created: `{filename}` - Issue #{issue_id}"
|
||||
|
||||
**When user says "next":**
|
||||
- Skip to the next item
|
||||
- Track skipped items for summary
|
||||
|
||||
**When user says "custom":**
|
||||
- Ask what to modify (priority, description, details)
|
||||
- Update the information
|
||||
- Present revised version
|
||||
- Ask again: yes/next/custom
|
||||
|
||||
**Cloudflare-Specific Tags to Use:**
|
||||
- `workers-runtime` - V8 runtime issues, Node.js API usage
|
||||
- `bindings` - KV/R2/D1/DO binding configuration or usage
|
||||
- `security` - Workers security model, secrets, CORS
|
||||
- `performance` - Cold starts, bundle size, edge optimization
|
||||
- `durable-objects` - DO patterns, state persistence, WebSockets
|
||||
- `kv` - KV usage patterns, TTL, consistency
|
||||
- `r2` - R2 storage patterns, uploads, streaming
|
||||
- `d1` - D1 database patterns, migrations, queries
|
||||
- `edge-caching` - Cache API patterns, invalidation
|
||||
- `workers-ai` - AI integration, Vercel AI SDK, RAG
|
||||
|
||||
### Step 3: Continue Until All Processed
|
||||
|
||||
- Process all items one by one
|
||||
- Track using TodoWrite for visibility
|
||||
- Don't wait for approval between items - keep moving
|
||||
|
||||
### Step 4: Final Summary
|
||||
|
||||
After all items processed:
|
||||
|
||||
```markdown
|
||||
## Triage Complete
|
||||
|
||||
**Total Items:** [X]
|
||||
**Todos Created:** [Y]
|
||||
**Skipped:** [Z]
|
||||
|
||||
### Created Todos:
|
||||
- `042-pending-p1-transaction-boundaries.md` - Transaction boundary issue
|
||||
- `043-pending-p2-cache-optimization.md` - Cache performance improvement
|
||||
...
|
||||
|
||||
### Skipped Items:
|
||||
- Item #5: [reason]
|
||||
- Item #12: [reason]
|
||||
|
||||
### Next Steps:
|
||||
1. Review pending todos: `ls todos/*-pending-*.md`
|
||||
2. Approve for work: Move from pending → ready status
|
||||
3. Start work: Use `/resolve_todo_parallel` or pick individually
|
||||
```
|
||||
|
||||
## Example Response Format
|
||||
|
||||
```
|
||||
---
|
||||
Issue #5: Missing Transaction Boundaries for Multi-Step Operations
|
||||
|
||||
Severity: 🔴 P1 (CRITICAL)
|
||||
|
||||
Category: Data Integrity / Security
|
||||
|
||||
Description:
|
||||
The google_oauth2_connected callback in GoogleOauthCallbacks concern performs multiple database
|
||||
operations without transaction protection. If any step fails midway, the database is left in an
|
||||
inconsistent state.
|
||||
|
||||
Location: app/controllers/concerns/google_oauth_callbacks.rb:13-50
|
||||
|
||||
Problem Scenario:
|
||||
1. User.update succeeds (email changed)
|
||||
2. Account.save! fails (validation error)
|
||||
3. Result: User has changed email but no associated Account
|
||||
4. Next login attempt fails completely
|
||||
|
||||
Operations Without Transaction:
|
||||
- User confirmation (line 13)
|
||||
- Waitlist removal (line 14)
|
||||
- User profile update (line 21-23)
|
||||
- Account creation (line 28-37)
|
||||
- Avatar attachment (line 39-45)
|
||||
- Journey creation (line 47)
|
||||
|
||||
Proposed Solution:
|
||||
Wrap all operations in ApplicationRecord.transaction do ... end block
|
||||
|
||||
Estimated Effort: Small (30 minutes)
|
||||
|
||||
---
|
||||
Do you want to add this to the todo list?
|
||||
1. yes - create todo file
|
||||
2. next - skip this item
|
||||
3. custom - modify before creating
|
||||
```
|
||||
|
||||
Do not code, and if you say yes, make sure to mark the to‑do as ready to pick up or something. If you make any changes, update the file and then continue to read the next one. If next is selecrte make sure to remove the to‑do from the list since its not relevant.
|
||||
|
||||
Every time you present the to‑do as a header, can you say what the progress of the triage is, how many we have done and how many are left, and an estimated time for completion, looking at how quickly we go through them as well?
|
||||
252
commands/es-validate.md
Normal file
252
commands/es-validate.md
Normal file
@@ -0,0 +1,252 @@
|
||||
---
|
||||
description: Run Cloudflare Workers validation checks before committing code
|
||||
---
|
||||
|
||||
# Cloudflare Validation Command
|
||||
|
||||
Run comprehensive validation checks for Cloudflare Workers projects:
|
||||
|
||||
## Validation Checks
|
||||
|
||||
### Continuous SKILL-based Validation (Already Active During Development)
|
||||
|
||||
**Cloudflare Workers SKILLs**:
|
||||
- **workers-runtime-validator**: Runtime compatibility validation
|
||||
- **cloudflare-security-checker**: Security pattern validation
|
||||
- **workers-binding-validator**: Binding configuration validation
|
||||
- **edge-performance-optimizer**: Performance optimization guidance
|
||||
- **kv-optimization-advisor**: KV storage optimization
|
||||
- **durable-objects-pattern-checker**: DO best practices validation
|
||||
- **cors-configuration-validator**: CORS setup validation
|
||||
|
||||
**Frontend Design SKILLs** (if shadcn/ui components detected):
|
||||
- **shadcn-ui-design-validator**: Prevents generic aesthetics (Inter fonts, purple gradients, minimal animations)
|
||||
- **component-aesthetic-checker**: Validates shadcn/ui component customization depth and consistency
|
||||
- **animation-interaction-validator**: Ensures engaging animations, hover states, and loading feedback
|
||||
|
||||
### Explicit Command Validation (Run by /validate)
|
||||
1. **Documentation sync** - Validates all docs reflect current state
|
||||
2. **wrangler.toml syntax** - Validates configuration file
|
||||
3. **compatibility_date** - Ensures current runtime version
|
||||
4. **TypeScript checks** - Runs typecheck if available
|
||||
5. **Build verification** - Runs build command and checks for errors
|
||||
6. **Linting** - Runs linter if available
|
||||
7. **Bundle size analysis** - Checks deployment size limits
|
||||
8. **Remote bindings** - Validates binding configuration
|
||||
|
||||
## Usage
|
||||
|
||||
Run this command before committing code:
|
||||
|
||||
```
|
||||
/validate
|
||||
```
|
||||
|
||||
## When to Use
|
||||
|
||||
- Before `git commit`
|
||||
- After making configuration changes
|
||||
- Before deployment
|
||||
- When troubleshooting issues
|
||||
|
||||
## Validation Rules
|
||||
|
||||
### Strict Requirements
|
||||
- **0 errors** - All errors must be fixed before committing
|
||||
- **≤5 warnings** - More than 5 warnings must be addressed before committing
|
||||
|
||||
### Exit Codes
|
||||
- **0**: All checks passed ✅ (0 errors, ≤5 warnings)
|
||||
- **1**: Validation failed ❌ (fix issues before committing)
|
||||
|
||||
## Build Requirements
|
||||
|
||||
The validation will:
|
||||
- **SKILL Summary**: Report any P1/P2 issues found by active SKILLs during development
|
||||
- Run `pnpm build` if build script exists (fails on any build errors)
|
||||
- Run `pnpm typecheck` if typecheck script exists (fails on any TypeScript errors)
|
||||
- Run `pnpm lint` if lint script exists (counts warnings toward threshold)
|
||||
- Fail fast on first error to save time
|
||||
- Enforce code quality: no errors, max 5 warnings
|
||||
|
||||
**Integration Note**: SKILLs provide continuous validation during development, catching issues early. The /validate command provides explicit validation and summarizes any SKILL findings alongside traditional build/lint checks.
|
||||
|
||||
This helps catch issues early and ensures code quality before committing to repository.
|
||||
|
||||
## Documentation Validation (Step 1)
|
||||
|
||||
<thinking>
|
||||
Before running any code validation, verify that all documentation is up-to-date.
|
||||
This prevents committing code with outdated docs.
|
||||
</thinking>
|
||||
|
||||
### Required Documentation Files
|
||||
|
||||
The plugin must maintain these documentation files:
|
||||
- **README.md** - Overview, features, command list, agent list, SKILL list
|
||||
- **PREFERENCES.md** - Development standards, billing/auth preferences, design guidelines
|
||||
- **IMPLEMENTATION-COMPLETE.md** or **IMPLEMENTATION_COMPLETE.md** - Implementation status
|
||||
- **POST-MERGE-ACTIVITIES.md** - Post-deployment tasks and monitoring
|
||||
- **TESTING.md** - Test specifications and strategies
|
||||
- **docs/mcp-usage-examples.md** - MCP query patterns
|
||||
|
||||
### Documentation Validation Checks
|
||||
|
||||
**1. Count actual files**:
|
||||
|
||||
```bash
|
||||
# Count commands
|
||||
COMMAND_COUNT=$(find commands -name "es-*.md" | wc -l)
|
||||
NON_ES_COMMANDS=$(find commands -name "*.md" ! -name "es-*.md" | wc -l)
|
||||
TOTAL_COMMANDS=$((COMMAND_COUNT + NON_ES_COMMANDS))
|
||||
|
||||
# Count agents
|
||||
AGENT_COUNT=$(find agents -name "*.md" | wc -l)
|
||||
|
||||
# Count SKILLs
|
||||
SKILL_COUNT=$(find skills -name "SKILL.md" | wc -l)
|
||||
|
||||
echo "📊 Actual counts:"
|
||||
echo " Commands: $TOTAL_COMMANDS ($COMMAND_COUNT /es-* + $NON_ES_COMMANDS other)"
|
||||
echo " Agents: $AGENT_COUNT"
|
||||
echo " SKILLs: $SKILL_COUNT"
|
||||
```
|
||||
|
||||
**2. Check README.md accuracy**:
|
||||
|
||||
```bash
|
||||
# Extract counts from README
|
||||
README_COMMANDS=$(grep -oP '\d+(?= workflow commands)' README.md || echo "NOT_FOUND")
|
||||
README_AGENTS=$(grep -oP '\d+(?= specialized agents)' README.md || echo "NOT_FOUND")
|
||||
README_SKILLS=$(grep -oP '\d+(?= autonomous SKILLs)' README.md || echo "NOT_FOUND")
|
||||
|
||||
echo ""
|
||||
echo "📄 README.md claims:"
|
||||
echo " Commands: $README_COMMANDS"
|
||||
echo " Agents: $README_AGENTS"
|
||||
echo " SKILLs: $README_SKILLS"
|
||||
|
||||
# Compare
|
||||
DOCS_VALID=true
|
||||
|
||||
if [ "$README_COMMANDS" != "$TOTAL_COMMANDS" ]; then
|
||||
echo "❌ ERROR: README.md lists $README_COMMANDS commands, but found $TOTAL_COMMANDS"
|
||||
DOCS_VALID=false
|
||||
fi
|
||||
|
||||
if [ "$README_AGENTS" != "$AGENT_COUNT" ]; then
|
||||
echo "❌ ERROR: README.md lists $README_AGENTS agents, but found $AGENT_COUNT"
|
||||
DOCS_VALID=false
|
||||
fi
|
||||
|
||||
if [ "$README_SKILLS" != "$SKILL_COUNT" ]; then
|
||||
echo "❌ ERROR: README.md lists $README_SKILLS SKILLs, but found $SKILL_COUNT"
|
||||
DOCS_VALID=false
|
||||
fi
|
||||
|
||||
if [ "$DOCS_VALID" = false ]; then
|
||||
echo ""
|
||||
echo "❌ Documentation validation FAILED"
|
||||
echo " Fix: Update README.md with correct counts before committing"
|
||||
exit 1
|
||||
fi
|
||||
```
|
||||
|
||||
**3. Verify all commands are documented**:
|
||||
|
||||
```bash
|
||||
# List all commands
|
||||
COMMANDS_LIST=$(find commands -name "*.md" -exec basename {} .md \; | sort)
|
||||
|
||||
# Check if README mentions each command
|
||||
UNDOCUMENTED_COMMANDS=""
|
||||
for cmd in $COMMANDS_LIST; do
|
||||
if ! grep -q "/$cmd" README.md 2>/dev/null; then
|
||||
UNDOCUMENTED_COMMANDS="$UNDOCUMENTED_COMMANDS\n - /$cmd"
|
||||
fi
|
||||
done
|
||||
|
||||
if [ -n "$UNDOCUMENTED_COMMANDS" ]; then
|
||||
echo "⚠️ WARNING: Commands not mentioned in README.md:$UNDOCUMENTED_COMMANDS"
|
||||
echo " Consider adding documentation for these commands"
|
||||
fi
|
||||
```
|
||||
|
||||
**4. Check for outdated command references**:
|
||||
|
||||
```bash
|
||||
# Check for /cf- references (should be /es- now)
|
||||
CF_REFS=$(grep -r '/cf-' --include="*.md" 2>/dev/null | wc -l)
|
||||
|
||||
if [ "$CF_REFS" -gt 0 ]; then
|
||||
echo "❌ ERROR: Found $CF_REFS references to /cf-* commands (should be /es-*)"
|
||||
echo " Files with /cf- references:"
|
||||
grep -r '/cf-' --include="*.md" -l 2>/dev/null
|
||||
exit 1
|
||||
fi
|
||||
```
|
||||
|
||||
**5. Verify MCP server list**:
|
||||
|
||||
```bash
|
||||
# Count MCPs in .mcp.json
|
||||
if [ -f ".mcp.json" ]; then
|
||||
MCP_COUNT=$(jq '.mcpServers | keys | length' .mcp.json 2>/dev/null || echo "0")
|
||||
|
||||
# Check if README mentions correct MCP count
|
||||
if ! grep -q "$MCP_COUNT MCP" README.md 2>/dev/null && ! grep -q "${MCP_COUNT} MCP" README.md 2>/dev/null; then
|
||||
echo "⚠️ WARNING: README.md may not list all $MCP_COUNT MCP servers"
|
||||
fi
|
||||
fi
|
||||
```
|
||||
|
||||
**6. Check documentation freshness**:
|
||||
|
||||
```bash
|
||||
# Find recently modified code files
|
||||
RECENT_CODE=$(find agents commands skills -name "*.md" -mtime -1 | wc -l)
|
||||
|
||||
if [ "$RECENT_CODE" -gt 0 ]; then
|
||||
# Check if README was also updated
|
||||
README_MODIFIED=$(find README.md -mtime -1 | wc -l)
|
||||
|
||||
if [ "$README_MODIFIED" -eq 0 ]; then
|
||||
echo "⚠️ WARNING: $RECENT_CODE code files modified recently, but README.md not updated"
|
||||
echo " Consider updating README.md to reflect recent changes"
|
||||
fi
|
||||
fi
|
||||
```
|
||||
|
||||
### Documentation Auto-Update
|
||||
|
||||
If documentation validation fails, offer to auto-update:
|
||||
|
||||
```bash
|
||||
if [ "$DOCS_VALID" = false ]; then
|
||||
echo ""
|
||||
echo "Would you like to auto-update documentation? (y/n)"
|
||||
read -r UPDATE_DOCS
|
||||
|
||||
if [ "$UPDATE_DOCS" = "y" ]; then
|
||||
# Update README.md counts
|
||||
sed -i "s/\*\*[0-9]* specialized agents\*\*/\*\*$AGENT_COUNT specialized agents\*\*/g" README.md
|
||||
sed -i "s/\*\*[0-9]* autonomous SKILLs\*\*/\*\*$SKILL_COUNT autonomous SKILLs\*\*/g" README.md
|
||||
sed -i "s/\*\*[0-9]* workflow commands\*\*/\*\*$TOTAL_COMMANDS workflow commands\*\*/g" README.md
|
||||
|
||||
echo "✅ README.md updated with correct counts"
|
||||
echo " Please review changes and commit"
|
||||
fi
|
||||
fi
|
||||
```
|
||||
|
||||
### Documentation Validation Success
|
||||
|
||||
If all checks pass:
|
||||
|
||||
```bash
|
||||
echo ""
|
||||
echo "✅ Documentation validation PASSED"
|
||||
echo " - All counts accurate"
|
||||
echo " - No outdated command references"
|
||||
echo " - All commands documented"
|
||||
```
|
||||
179
commands/es-work.md
Normal file
179
commands/es-work.md
Normal file
@@ -0,0 +1,179 @@
|
||||
---
|
||||
description: Analyze work documents and systematically execute tasks until completion
|
||||
---
|
||||
|
||||
# Work Plan Execution Command
|
||||
|
||||
## Introduction
|
||||
|
||||
This command helps you analyze a work document (plan, Markdown file, specification, or any structured document), create a comprehensive todo list using the TodoWrite tool, and then systematically execute each task until the entire plan is completed. It combines deep analysis with practical execution to transform plans into reality.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- A work document to analyze (plan file, specification, or any structured document)
|
||||
- Clear understanding of project context and goals
|
||||
- Access to necessary tools and permissions for implementation
|
||||
- Ability to test and validate completed work
|
||||
- Git repository with main branch
|
||||
|
||||
## Main Tasks
|
||||
|
||||
### 1. Setup Development Environment
|
||||
|
||||
- Ensure main branch is up to date
|
||||
- Create feature branch with descriptive name
|
||||
- Setup worktree for isolated development
|
||||
- Configure development environment
|
||||
|
||||
### 2. Analyze Input Document
|
||||
|
||||
<input_document> #$ARGUMENTS </input_document>
|
||||
|
||||
## Execution Workflow
|
||||
|
||||
### Phase 1: Environment Setup
|
||||
|
||||
1. **Update Main Branch**
|
||||
|
||||
```bash
|
||||
git checkout main
|
||||
git pull origin main
|
||||
```
|
||||
|
||||
2. **Create Feature Branch and Worktree**
|
||||
|
||||
- Determine appropriate branch name from document
|
||||
- Get the root directory of the Git repository:
|
||||
|
||||
```bash
|
||||
git_root=$(git rev-parse --show-toplevel)
|
||||
```
|
||||
|
||||
- Create worktrees directory if it doesn't exist:
|
||||
|
||||
```bash
|
||||
mkdir -p "$git_root/.worktrees"
|
||||
```
|
||||
|
||||
- Add .worktrees to .gitignore if not already there:
|
||||
|
||||
```bash
|
||||
if ! grep -q "^\.worktrees$" "$git_root/.gitignore"; then
|
||||
echo ".worktrees" >> "$git_root/.gitignore"
|
||||
fi
|
||||
```
|
||||
|
||||
- Create the new worktree with feature branch:
|
||||
|
||||
```bash
|
||||
git worktree add -b feature-branch-name "$git_root/.worktrees/feature-branch-name" main
|
||||
```
|
||||
|
||||
- Change to the new worktree directory:
|
||||
|
||||
```bash
|
||||
cd "$git_root/.worktrees/feature-branch-name"
|
||||
```
|
||||
|
||||
3. **Verify Environment**
|
||||
- Confirm in correct worktree directory
|
||||
- Install dependencies if needed
|
||||
- Run initial tests to ensure clean state
|
||||
|
||||
### Phase 2: Document Analysis and Planning
|
||||
|
||||
1. **Read Input Document**
|
||||
|
||||
- Use Read tool to examine the work document
|
||||
- Identify all deliverables and requirements
|
||||
- Note any constraints or dependencies
|
||||
- Extract success criteria
|
||||
|
||||
2. **Create Task Breakdown**
|
||||
|
||||
- Convert requirements into specific tasks
|
||||
- Add implementation details for each task
|
||||
- Include testing and validation steps
|
||||
- Consider edge cases and error handling
|
||||
|
||||
3. **Build Todo List**
|
||||
- Use TodoWrite to create comprehensive list
|
||||
- Set priorities based on dependencies
|
||||
- Include all subtasks and checkpoints
|
||||
- Add documentation and review tasks
|
||||
|
||||
### Phase 3: Systematic Execution
|
||||
|
||||
1. **Task Execution Loop**
|
||||
|
||||
```
|
||||
while (tasks remain):
|
||||
- Select next task (priority + dependencies)
|
||||
- Mark as in_progress
|
||||
- Execute task completely
|
||||
- Validate with platform-specific agents
|
||||
- Mark as completed
|
||||
- Update progress
|
||||
```
|
||||
|
||||
2. **Platform-Specific Validation**
|
||||
|
||||
After implementing each task, validate with relevant agents:
|
||||
|
||||
- **Task workers-runtime-guardian** - Runtime compatibility check
|
||||
- Verify no Node.js APIs (fs, process, Buffer)
|
||||
- Ensure env parameter usage (not process.env)
|
||||
- Validate Web APIs only
|
||||
|
||||
- **Task platform-specific binding analyzer** - Binding validation
|
||||
- Verify bindings referenced in code exist in wrangler.toml
|
||||
- Check TypeScript Env interface matches usage
|
||||
- Validate binding names follow conventions
|
||||
|
||||
- **Task cloudflare-security-sentinel** - Security check
|
||||
- Verify secrets use wrangler secret (not hardcoded)
|
||||
- Check CORS configuration if API endpoints
|
||||
- Validate input sanitization
|
||||
|
||||
- **Task edge-performance-oracle** - Performance check
|
||||
- Verify bundle size stays under target
|
||||
- Check for cold start optimization
|
||||
- Validate caching strategies
|
||||
|
||||
3. **Quality Assurance**
|
||||
|
||||
- Run tests after each task (npm test / wrangler dev)
|
||||
- Execute lint and typecheck commands
|
||||
- Test locally with wrangler dev
|
||||
- Verify no regressions
|
||||
- Check against acceptance criteria
|
||||
- Document any issues found
|
||||
|
||||
3. **Progress Tracking**
|
||||
- Regularly update task status
|
||||
- Note any blockers or delays
|
||||
- Create new tasks for discoveries
|
||||
- Maintain work visibility
|
||||
|
||||
### Phase 4: Completion and Submission
|
||||
|
||||
1. **Final Validation**
|
||||
|
||||
- Verify all tasks completed
|
||||
- Run comprehensive test suite
|
||||
- Execute final lint and typecheck
|
||||
- Check all deliverables present
|
||||
- Ensure documentation updated
|
||||
|
||||
2. **Prepare for Submission**
|
||||
|
||||
- Stage and commit all changes
|
||||
- Write commit messages
|
||||
- Push feature branch to remote
|
||||
- Create detailed pull request
|
||||
|
||||
3. **Create Pull Request**
|
||||
```bash
|
||||
git push -u origin feature-branch-name
|
||||
gh pr create --title "Feature: [Description]" --body "[Detailed description]"
|
||||
```
|
||||
199
commands/es-worker.md
Normal file
199
commands/es-worker.md
Normal file
@@ -0,0 +1,199 @@
|
||||
---
|
||||
description: Generate Cloudflare Workers code with proper bindings and runtime compatibility
|
||||
---
|
||||
|
||||
You are a **Cloudflare Workers expert**. Your task is to generate production-ready Worker code that follows best practices and uses the Workers runtime correctly.
|
||||
|
||||
## Step 1: Analyze the Project Context
|
||||
|
||||
First, check if a `wrangler.toml` file exists in the workspace:
|
||||
|
||||
1. Use the Glob tool to find wrangler.toml:
|
||||
```
|
||||
pattern: "**/wrangler.toml"
|
||||
```
|
||||
|
||||
2. If found, read the file to extract:
|
||||
- KV namespace bindings (`[[kv_namespaces]]`)
|
||||
- R2 bucket bindings (`[[r2_buckets]]`)
|
||||
- Durable Object bindings (`[[durable_objects]]`)
|
||||
- D1 database bindings (`[[d1_databases]]`)
|
||||
- Service bindings (`[[services]]`)
|
||||
- Queue bindings (`[[queues]]`)
|
||||
- Vectorize bindings (`[[vectorize]]`)
|
||||
- AI bindings (`[ai]`)
|
||||
- Any environment variables (`[vars]`)
|
||||
|
||||
3. Parse the bindings and create a context summary like:
|
||||
```
|
||||
Available Bindings:
|
||||
- KV Namespaces: USER_DATA (binding name)
|
||||
- R2 Buckets: UPLOADS (binding name)
|
||||
- Durable Objects: Counter (binding name, class: Counter)
|
||||
- D1 Databases: DB (binding name)
|
||||
```
|
||||
|
||||
## Step 2: Generate Worker Code
|
||||
|
||||
Create a Worker that:
|
||||
- Accomplishes the user's stated goal: {{PROMPT}}
|
||||
- Uses the available bindings from the wrangler.toml (if any exist)
|
||||
- Follows Workers runtime best practices
|
||||
|
||||
### Code Structure Requirements
|
||||
|
||||
Your generated code MUST:
|
||||
|
||||
1. **Export Structure**: Use the proper Worker export format:
|
||||
```typescript
|
||||
export default {
|
||||
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
|
||||
// Handler code
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
2. **TypeScript Types**: Define the Env interface with all bindings:
|
||||
```typescript
|
||||
interface Env {
|
||||
// KV Namespaces
|
||||
USER_DATA: KVNamespace;
|
||||
|
||||
// R2 Buckets
|
||||
UPLOADS: R2Bucket;
|
||||
|
||||
// Durable Objects
|
||||
Counter: DurableObjectNamespace;
|
||||
|
||||
// D1 Databases
|
||||
DB: D1Database;
|
||||
|
||||
// Environment variables
|
||||
API_KEY: string;
|
||||
}
|
||||
```
|
||||
|
||||
3. **Runtime Compatibility**: Only use Workers-compatible APIs:
|
||||
- ✅ `fetch`, `Request`, `Response`, `Headers`, `URL`
|
||||
- ✅ `crypto`, `TextEncoder`, `TextDecoder`
|
||||
- ✅ Web Streams API
|
||||
- ❌ NO Node.js APIs (`fs`, `path`, `process`, `buffer`, etc.)
|
||||
- ❌ NO `require()` or CommonJS
|
||||
- ❌ NO synchronous I/O
|
||||
|
||||
4. **Error Handling**: Include proper error handling:
|
||||
```typescript
|
||||
try {
|
||||
// Operation
|
||||
} catch (error) {
|
||||
return new Response(`Error: ${error.message}`, { status: 500 });
|
||||
}
|
||||
```
|
||||
|
||||
5. **CORS Headers** (if building an API):
|
||||
```typescript
|
||||
const corsHeaders = {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
|
||||
'Access-Control-Allow-Headers': 'Content-Type',
|
||||
};
|
||||
```
|
||||
|
||||
### Binding Usage Examples
|
||||
|
||||
**KV Namespace:**
|
||||
```typescript
|
||||
await env.USER_DATA.get(key);
|
||||
await env.USER_DATA.put(key, value, { expirationTtl: 3600 });
|
||||
await env.USER_DATA.delete(key);
|
||||
await env.USER_DATA.list({ prefix: 'user:' });
|
||||
```
|
||||
|
||||
**R2 Bucket:**
|
||||
```typescript
|
||||
await env.UPLOADS.get(key);
|
||||
await env.UPLOADS.put(key, body, { httpMetadata: headers });
|
||||
await env.UPLOADS.delete(key);
|
||||
await env.UPLOADS.list({ prefix: 'images/' });
|
||||
```
|
||||
|
||||
**Durable Object:**
|
||||
```typescript
|
||||
const id = env.Counter.idFromName('my-counter');
|
||||
const stub = env.Counter.get(id);
|
||||
const response = await stub.fetch(request);
|
||||
```
|
||||
|
||||
**D1 Database:**
|
||||
```typescript
|
||||
const result = await env.DB.prepare('SELECT * FROM users WHERE id = ?')
|
||||
.bind(userId)
|
||||
.first();
|
||||
await env.DB.prepare('INSERT INTO users (name) VALUES (?)')
|
||||
.bind(name)
|
||||
.run();
|
||||
```
|
||||
|
||||
## Step 3: Provide Implementation Guidance
|
||||
|
||||
After generating the code:
|
||||
|
||||
1. **File Location**: Specify where to save the file (typically `src/index.ts` or `src/index.js`)
|
||||
|
||||
2. **Required Bindings**: If the wrangler.toml is missing bindings that your code needs, provide a note:
|
||||
```
|
||||
Note: This code expects the following bindings to be configured in wrangler.toml:
|
||||
|
||||
[[kv_namespaces]]
|
||||
binding = "USER_DATA"
|
||||
id = "<your-kv-namespace-id>"
|
||||
```
|
||||
|
||||
3. **Testing Instructions**: Suggest how to test:
|
||||
```bash
|
||||
# Local development
|
||||
npx wrangler dev
|
||||
|
||||
# Test the endpoint
|
||||
curl http://localhost:8787/api/test
|
||||
```
|
||||
|
||||
4. **Deployment Steps**: Brief deployment guidance:
|
||||
```bash
|
||||
# Deploy to production
|
||||
npx wrangler deploy
|
||||
```
|
||||
|
||||
## Critical Guardrails
|
||||
|
||||
**YOU MUST NOT:**
|
||||
- Suggest direct modifications to wrangler.toml (only show what's needed)
|
||||
- Use Node.js-specific APIs or packages
|
||||
- Create blocking/synchronous code
|
||||
- Use `require()` or CommonJS syntax
|
||||
- Access `process.env` directly (use `env` parameter)
|
||||
|
||||
**YOU MUST:**
|
||||
- Use only the bindings defined in wrangler.toml
|
||||
- Use Workers runtime APIs (fetch-based)
|
||||
- Follow TypeScript best practices
|
||||
- Include proper error handling
|
||||
- Make code edge-optimized (fast cold starts)
|
||||
- Use `env` parameter for all bindings and environment variables
|
||||
|
||||
## Response Format
|
||||
|
||||
Provide your response in the following structure:
|
||||
|
||||
1. **Project Context Summary**: Brief overview of detected bindings
|
||||
2. **Generated Code**: Complete, working Worker implementation
|
||||
3. **Type Definitions**: Full TypeScript interfaces
|
||||
4. **Setup Instructions**: Any configuration notes
|
||||
5. **Testing Guide**: How to test locally and in production
|
||||
6. **Next Steps**: Suggested improvements or additional features
|
||||
|
||||
---
|
||||
|
||||
**User's Request:**
|
||||
|
||||
{{PROMPT}}
|
||||
115
commands/generate_command.md
Normal file
115
commands/generate_command.md
Normal file
@@ -0,0 +1,115 @@
|
||||
---
|
||||
description: Create a custom Claude Code slash command in .claude/commands/
|
||||
---
|
||||
|
||||
# Create a Custom Claude Code Command
|
||||
|
||||
Create a new slash command in `.claude/commands/` for the requested task.
|
||||
|
||||
## Goal
|
||||
|
||||
#$ARGUMENTS
|
||||
|
||||
## Key Capabilities to Leverage
|
||||
|
||||
**File Operations:**
|
||||
- Read, Edit, Write - modify files precisely
|
||||
- Glob, Grep - search codebase
|
||||
- MultiEdit - atomic multi-part changes
|
||||
|
||||
**Development:**
|
||||
- Bash - run commands (git, tests, linters)
|
||||
- Task - launch specialized agents for complex tasks
|
||||
- TodoWrite - track progress with todo lists
|
||||
|
||||
**Web & APIs:**
|
||||
- WebFetch, WebSearch - research documentation
|
||||
- GitHub (gh cli) - PRs, issues, reviews
|
||||
- Puppeteer - browser automation, screenshots
|
||||
|
||||
**Integrations:**
|
||||
- Platform-specific MCPs for account context and docs
|
||||
- shadcn/ui MCP - component documentation
|
||||
- Stripe, Todoist, Featurebase (if relevant)
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Be specific and clear** - detailed instructions yield better results
|
||||
2. **Break down complex tasks** - use step-by-step plans
|
||||
3. **Use examples** - reference existing code patterns
|
||||
4. **Include success criteria** - tests pass, linting clean, etc.
|
||||
5. **Think first** - use "think hard" or "plan" keywords for complex problems
|
||||
6. **Iterate** - guide the process step by step
|
||||
|
||||
## Structure Your Command
|
||||
|
||||
```markdown
|
||||
# [Command Name]
|
||||
|
||||
[Brief description of what this command does]
|
||||
|
||||
## Steps
|
||||
|
||||
1. [First step with specific details]
|
||||
- Include file paths, patterns, or constraints
|
||||
- Reference existing code if applicable
|
||||
|
||||
2. [Second step]
|
||||
- Use parallel tool calls when possible
|
||||
- Check/verify results
|
||||
|
||||
3. [Final steps]
|
||||
- Run tests
|
||||
- Lint code
|
||||
- Commit changes (if appropriate)
|
||||
|
||||
## Success Criteria
|
||||
|
||||
- [ ] Tests pass
|
||||
- [ ] Code follows style guide
|
||||
- [ ] Documentation updated (if needed)
|
||||
```
|
||||
|
||||
## Tips for Effective Commands
|
||||
|
||||
- **Use $ARGUMENTS** placeholder for dynamic inputs
|
||||
- **Reference PREFERENCES.md** for framework-specific patterns and guidelines
|
||||
- **Include verification steps** - tests, linting, visual checks
|
||||
- **Be explicit about constraints** - don't modify X, use pattern Y
|
||||
- **Use XML tags** for structured prompts: `<task>`, `<requirements>`, `<constraints>`
|
||||
|
||||
## Example Pattern
|
||||
|
||||
```markdown
|
||||
Implement #$ARGUMENTS following these steps:
|
||||
|
||||
1. Research existing patterns
|
||||
- Search for similar code using Grep
|
||||
- Read relevant files to understand approach
|
||||
|
||||
2. Plan the implementation
|
||||
- Think through edge cases and requirements
|
||||
- Consider test cases needed
|
||||
|
||||
3. Implement
|
||||
- Follow existing code patterns (reference specific files)
|
||||
- Write tests first if doing TDD
|
||||
- Ensure code follows CLAUDE.md conventions
|
||||
|
||||
4. Verify
|
||||
- Run tests:
|
||||
- Local development: `npm test` or appropriate dev server
|
||||
- TypeScript: `npm run typecheck` or `tsc --noEmit`
|
||||
- Unit tests: `vitest` or `jest`
|
||||
- Run linter:
|
||||
- Rails: `bundle exec standardrb` or `bundle exec rubocop`
|
||||
- TypeScript: `npm run lint` or `eslint .`
|
||||
- Python: `ruff check .` or `flake8`
|
||||
- Check changes with git diff
|
||||
|
||||
5. Commit (optional)
|
||||
- Stage changes
|
||||
- Write clear commit message
|
||||
```
|
||||
|
||||
Now create the command file at `.claude/commands/[name].md` with the structure above.
|
||||
Reference in New Issue
Block a user