Production-ready Next.js AI SaaS template with Supabase auth, Stripe payments, email system, multi-model AI client, and customizable components for rapid AI...
# Whirlwind AI SaaS Template Skill
Version: 2.0.0
## Overview
Whirlwind is a production-ready Next.js template for building AI SaaS products. It provides complete infrastructure so developers can focus on their unique AI features.
**Included Infrastructure:**
- ✅ Supabase authentication (email, OAuth, magic links)
- ✅ Stripe payments (subscriptions, one-time, webhooks)
- ✅ Email system (Resend/Mailgun)
- ✅ Multi-model AI client (Claude, GPT-4, Gemini)
- ✅ Landing page components
- ✅ Dashboard shell
- ✅ Database with RLS
**ClawdBot's Role:**
Customize the template for each user's specific AI product by generating custom components, API routes, and database tables.
## File Structure
### ✅ Infrastructure (DON'T MODIFY)
These files are core infrastructure. Never modify:
```
lib/
supabaseClient.js - Database client setup
stripe.js - Stripe checkout/portal functions
api.js - Axios wrapper with auth
seo.js - SEO metadata helpers
ai-client.js - Multi-model AI client
components/
ButtonCheckout.js - Stripe checkout button
ButtonSignin.js - Authentication button
ButtonAccount.js - Account dropdown
CheckoutModal.js - Checkout modal
LayoutClient.js - Client-side layout wrapper
SubscribeForm.js - Email subscription
ai/ - Pre-built AI components
providers/ - Auth/context providers
app/api/
auth/ - Supabase auth routes
stripe/ - Stripe webhook handlers
webhook/ - Other webhooks
```
### 🎨 Customizable (UPDATE CONTENT)
Update these files with product-specific content:
```
components/
Hero.js - Update hero title/subtitle
Features.js - Update features list
Pricing.js - Update pricing copy
FAQ.js - Update FAQ items
CTA.js - Update call-to-action
Testimonials.js - Add testimonials
Header.js - Update navigation (partial)
Footer.js - Update footer links (partial)
config.js - App configuration (Stripe plans, etc.)
```
### 🤖 Create New (CLAWDBOT GENERATES)
Generate new files in these locations:
```
components/features/ - Custom AI feature components
app/api/custom/ - Custom API endpoints
lib/supabase/migrations/ - Custom tables (002+)
config/site.js - Product-specific configuration (NEW)
```
## AI Client Usage
Whirlwind provides `lib/ai-client.js` for all AI operations. Always use this instead of creating ad-hoc clients.
### Basic Usage
```javascript
import AIClient from "@/lib/ai-client";
// Choose model: 'claude', 'openai', or 'gemini'
const ai = new AIClient('claude');
// Simple chat
const response = await ai.chat([
{ role: "user", content: "Your prompt here" }
]);
// With options
const response = await ai.chat(messages, {
maxTokens: 2000
});
// Streaming
await ai.stream(messages, (chunk) => {
console.log(chunk); // Handle each chunk
});
```
### Available Models
- `claude` - claude-sonnet-4-20250514 (recommended)
- `openai` - gpt-4
- `gemini` - gemini-pro (if configured)
## Database Operations
Always use the Supabase client with proper error handling:
```javascript
import { supabase } from "@/lib/supabaseClient";
// Insert
const { data, error } = await supabase
.from('table_name')
.insert({ column: value });
// Select with auth
const { data, error } = await supabase
.from('table_name')
.select('*')
.eq('user_id', userId);
// Always check errors
if (error) {
console.error(error);
throw new Error(error.message);
}
```
## Creating an AI Product - Step by Step
When a user says: "Create [product name] - [description]"
### Step 1: Create config/site.js
This centralizes all product-specific content:
```javascript
/**
* 🎨 CLAWDBOT CUSTOMIZES
* Product-specific configuration
*/
const siteConfig = {
productName: "[Product Name]",
productDescription: "[Brief description]",
hero: {
title: "[Compelling title]",
subtitle: "[Subtitle explaining value]",
},
features: [
{
icon: "[emoji]",
name: "[Feature name]",
description: "[Feature description]"
},
// Add 3-6 features
]
};
export default siteConfig;
```
### Step 2: Create Feature Component
Location: `components/features/[ComponentName].jsx`
Use this template structure:
```javascript
/**
* 🤖 CLAWDBOT CREATED
* [Component description]
*/
"use client";
import { useState } from "react";
import apiClient from "@/lib/api";
export default function [ComponentName]() {
const [input, setInput] = useState("");
const [result, setResult] = useState("");
const [loading, setLoading] = useState(false);
const handleGenerate = async () => {
setLoading(true);
try {
const response = await apiClient.post("/custom/[endpoint]", {
input
});
setResult(response.result);
} catch (error) {
console.error("Error:", error);
}
setLoading(false);
};
return (
<div className="max-w-4xl mx-auto p-6">
<h2 className="font-bebas text-4xl uppercase tracking-wide mb-6">
[Component Title]
</h2>
{/* Input UI */}
<div className="space-y-4">
<input
type="text"
value={input}
onChange={(e) => setInput(e.target.value)}
className="w-full px-4 py-2 border border-gray-200 dark:border-white/10 rounded"
placeholder="[Placeholder]"
/>
<button
onClick={handleGenerate}
disabled={loading || !input}
className="px-6 py-3 bg-primary hover:bg-primary-focus text-black font-bebas text-lg uppercase tracking-wide transition-colors disabled:opacity-50"
>
{loading ? "Processing..." : "[Action Text]"}
</button>
</div>
{/* Output UI */}
{result && (
<div className="mt-6 p-4 bg-white dark:bg-white/5 border border-gray-200 dark:border-white/10 rounded">
<h3 className="font-bebas text-xl uppercase mb-2">Result:</h3>
<div className="font-ibm text-sm">{result}</div>
</div>
)}
</div>
);
}
```
### Step 3: Create API Route
Location: `app/api/custom/[endpoint]/route.js`
```javascript
/**
* 🤖 CLAWDBOT CREATED
* [Endpoint description]
*/
import { NextResponse } from "next/server";
import AIClient from "@/lib/ai-client";
import { supabase } from "@/lib/supabaseClient";
export async function POST(req) {
try {
// Parse input
const { input } = await req.json();
// Validate
if (!input) {
return NextResponse.json(
{ error: "Input is required" },
{ status: 400 }
);
}
// Create AI prompt
const prompt = `[Your specific prompt template]: ${input}`;
// Call AI
const ai = new AIClient('claude');
const result = await ai.chat([
{ role: "user", content: prompt }
]);
// Optional: Save to database
// const { data: session } = await supabase.auth.getSession();
// if (session?.user) {
// await supabase.from('your_table').insert({
// user_id: session.user.id,
// input,
// result
// });
// }
return NextResponse.json({
success: true,
result
});
} catch (error) {
console.error("API error:", error);
return NextResponse.json(
{ error: error.message || "Processing failed" },
{ status: 500 }
);
}
}
```
### Step 4: Create Database Migration
Location: `lib/supabase/migrations/00X_[table_name].sql`
```sql
-- 🤖 CLAWDBOT CREATED
-- [Table description]
create table if not exists [table_name] (
id uuid default uuid_generate_v4() primary key,
user_id uuid references auth.users on delete cascade not null,
[your_columns] text not null,
created_at timestamp with time zone default timezone('utc'::text, now()) not null
);
-- Indexes
create index [table_name]_user_id_idx on [table_name](user_id);
create index [table_name]_created_at_idx on [table_name](created_at desc);
-- Row Level Security
alter table [table_name] enable row level security;
-- Policies
create policy "Users can view own records"
on [table_name] for select
using (auth.uid() = user_id);
create policy "Users can insert own records"
on [table_name] for insert
with check (auth.uid() = user_id);
create policy "Users can delete own records"
on [table_name] for delete
using (auth.uid() = user_id);
```
### Step 5: Update Dashboard
Add component to `app/dashboard/page.js`:
```javascript
import [ComponentName] from "@/components/features/[ComponentName]";
export default function Dashboard() {
return (
<div>
<h1 className="font-bebas text-5xl">Dashboard</h1>
<[ComponentName] />
</div>
);
}
```
## Code Style Guidelines
### Typography
- Headers: `font-bebas text-4xl uppercase tracking-wide`
- Body: `font-ibm text-sm`
- Always include dark mode classes
### Colors
- Primary action: `bg-primary hover:bg-primary-focus`
- Text: `text-gray-900 dark:text-white`
- Borders: `border-gray-200 dark:border-white/10`
- Backgrounds: `bg-white dark:bg-white/5`
### Components
- Always use `"use client"` for interactive components
- Include loading states
- Handle errors gracefully
- Validate inputs
- Add disabled states for buttons
## Rules and Constraints
### NEVER:
- Modify infrastructure files (lib/supabaseClient.js, lib/stripe.js, etc.)
- Remove existing functionality
- Create duplicate AI clients (use AIClient)
- Forget Row Level Security in migrations
- Skip error handling
### ALWAYS:
- Add ClawdBot marker comments (`🤖 CLAWDBOT CREATED`)
- Use AIClient for AI operations
- Include proper error handling
- Validate user inputs
- Use Next.js 14 patterns
- Include TypeScript types if using TS
- Test database queries
- Use proper HTTP status codes
- Include loading/disabled states
## Common Patterns
### Content Generation
```javascript
const prompt = `Generate ${contentType} about: ${topic}
Tone: ${tone}
Length: ${length} words
Include: ${requirements}`;
const ai = new AIClient('claude');
const content = await ai.chat([
{ role: "user", content: prompt }
]);
```
### Image Analysis
```javascript
// For image analysis, include base64 image in prompt
const prompt = `Analyze this image and ${task}`;
// Note: Image handling requires additional setup
```
### Document Processing
```javascript
const prompt = `Extract ${dataPoints} from this document:
${documentText}
Return as JSON.`;
const ai = new AIClient('claude');
const result = await ai.chat([
{ role: "user", content: prompt }
]);
```
### Chat/Conversation
```javascript
// Maintain conversation history
const conversationHistory = [
{ role: "user", content: "Previous message" },
{ role: "assistant", content: "Previous response" },
{ role: "user", content: "Current message" }
];
const ai = new AIClient('claude');
const response = await ai.chat(conversationHistory);
```
## Example Workflows
See `/examples` folder for complete implementations:
- `content-generator.md` - WriteFlow content platform
- `image-analyzer.md` - VisionAI image analysis
- `chatbot.md` - TalkAI chatbot platform
- `document-processor.md` - DocuMind document intelligence
## Templates
See `/templates` folder for code templates to copy:
- `component.jsx` - Feature component template
- `api-route.js` - API endpoint template
- `migration.sql` - Database migration template
## Environment Variables
Remind users to add these to `.env`:
```bash
# Required
NEXT_PUBLIC_SUPABASE_URL=
NEXT_PUBLIC_SUPABASE_ANON_KEY=
SUPABASE_SERVICE_ROLE_KEY=
STRIPE_SECRET_KEY=
STRIPE_WEBHOOK_SECRET=
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=
# AI (at least one required)
ANTHROPIC_API_KEY=
OPENAI_API_KEY=
# Optional
RESEND_API_KEY=
GOOGLE_AI_API_KEY=
```
## Testing
After generating code, suggest testing:
1. Check component renders: `npm run dev`
2. Test API endpoint with curl or Postman
3. Run database migration in Supabase dashboard
4. Test full workflow end-to-end
## Support
For issues or questions:
- Documentation: [GitHub repo]
- Community: [Discord]
- Email: support@whirlwindai.xyz
don't have the plugin yet? install it then click "run inline in claude" again.