🎁 Get the FREE AI Skills Starter Guide β€” Subscribe β†’
BytesAgainBytesAgain
πŸ¦€ ClawHub

Whirlwind

by @rosebeatty

Production-ready Next.js AI SaaS template with Supabase auth, Stripe payments, email system, multi-model AI client, and customizable components for rapid AI...

TERMINAL
clawhub install whirlwind

πŸ“– About This Skill

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

    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:

    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:

    /**
     * 🎨 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:

    /**
     * πŸ€– 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 (

    [Component Title]

    {/* Input UI */}
    setInput(e.target.value)} className="w-full px-4 py-2 border border-gray-200 dark:border-white/10 rounded" placeholder="[Placeholder]" />
    {/* Output UI */} {result && (

    Result:

    {result}
    )}
    ); }

    Step 3: Create API Route

    Location: app/api/custom/[endpoint]/route.js

    /**
     * πŸ€– 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

    -- πŸ€– 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; create index [table_name]_created_at_idx on table_name;

    -- 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:

    import [ComponentName] from "@/components/features/[ComponentName]";

    export default function Dashboard() { return (

    Dashboard

    <[ComponentName] />
    ); }

    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

    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

    // For image analysis, include base64 image in prompt
    const prompt = Analyze this image and ${task};
    // Note: Image handling requires additional setup
    

    Document Processing

    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

    // 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:

    # 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