Skill flagged — suspicious patterns detected

ClawHub Security flagged this skill as suspicious. Review the scan results before using.

Whirlwind

v1.0.0

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

0· 40·0 current·0 all-time
byRose Beatty@rosebeatty

Install

OpenClaw Prompt Flow

Install with OpenClaw

Best for remote or guided setup. Copy the exact prompt, then paste it into OpenClaw for rosebeatty/whirlwind.

Previewing Install & Setup.
Prompt PreviewInstall & Setup
Install the skill "Whirlwind" (rosebeatty/whirlwind) from ClawHub.
Skill page: https://clawhub.ai/rosebeatty/whirlwind
Keep the work scoped to this skill only.
After install, inspect the skill metadata and help me finish setup.
Use only the metadata you can verify from ClawHub; do not invent missing requirements.
Ask before making any broader environment changes.

Command Line

CLI Commands

Use the direct CLI path if you want to install manually and keep every step visible.

OpenClaw CLI

Bare skill slug

openclaw skills install whirlwind

ClawHub CLI

Package manager switcher

npx clawhub@latest install whirlwind
Security Scan
Capability signals
CryptoCan make purchasesRequires OAuth tokenRequires sensitive credentials
These labels describe what authority the skill may exercise. They are separate from suspicious or malicious moderation verdicts.
VirusTotalVirusTotal
Suspicious
View report →
OpenClawOpenClaw
Suspicious
high confidence
Purpose & Capability
The declared purpose (Next.js AI SaaS template with Supabase, Stripe, AI providers) matches the templates and examples provided. However, the skill.json and registry metadata list no required environment variables or primary credential, while SKILL.md and README repeatedly instruct the agent to collect and use many secrets (Supabase anon and SERVICE_ROLE key, Stripe secret/webhook secret, Anthropic/OpenAI keys, Mailchimp key, etc.). That mismatch (no declared required env vs. explicit instructions to collect many secrets) is an incoherence that reduces trust.
!
Instruction Scope
SKILL.md and SETUP_WORKFLOW.md explicitly instruct ClawdBot to prompt the user for API keys and secrets and to 'Create your .env with all your API keys' and to paste values into the conversation (e.g., 'Give me these: NEXT_PUBLIC_SUPABASE_URL=...'). Collecting highly privileged secrets (notably SUPABASE_SERVICE_ROLE_KEY and Stripe secret keys) via chat is unnecessary and dangerous. The rest of the instruction scope (creating components, API routes, SQL migrations, and using the AI client) is within the template's purpose, but the instructions grant the agent broad discretion to request and persist sensitive data in chat and files.
Install Mechanism
This is an instruction-first skill with included templates and no install spec — lowest install risk. There are no downloads, remote install URLs, or archive extraction steps in the metadata. The included templates are consistent with the stated purpose.
!
Credentials
The set of environment variables requested in the docs (Supabase URL, anon key, SUPABASE_SERVICE_ROLE_KEY, STRIPE_SECRET_KEY, NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY, STRIPE_WEBHOOK_SECRET, ANTHROPIC_API_KEY, OPENAI_API_KEY, Mailchimp keys, etc.) are all relevant to running the template. However, the inclusion of SUPABASE_SERVICE_ROLE_KEY (a high-privilege service key) and the practice of asking the user to paste those keys into the chat are disproportionate and risky. Additionally, the manifest declares no required env variables or primary credential — inconsistent with the large number of secrets the workflow expects.
Persistence & Privilege
The skill does not request 'always: true' and does not claim additional platform privileges. It instructs the agent to write .env files and migrations to the project — normal for a template generator. Nevertheless, because the skill's runtime instructions encourage placing secrets into files and the chat, treat autonomous invocation with caution: if the agent can run this workflow automatically, it could collect and persist secrets without clear guardrails. On its own this is not a privilege escalation, but combined with the secret-collection behavior it raises risk.
What to consider before installing
This skill appears to be a legitimate template generator, but exercise caution before providing secrets. Do not paste high-privilege keys (especially SUPABASE_SERVICE_ROLE_KEY, Stripe secret keys, or any private AI provider keys) directly into chat. Prefer the following safer workflow: - Verify the skill's source (GitHub repo, package publisher) and review the templates locally before running any automated setup. The registry metadata lacks a verified homepage — confirm the repository URL is legitimate. - When setting up services, create and paste only low-privilege keys into client-side config (e.g., public anon keys or publishable Stripe keys). Never disclose service_role or secret API keys in a conversational interface. Use your hosting platform's secrets manager or environment configuration (Vercel, Supabase project settings, etc.). - Inspect the generated .env files and ensure server-only secrets are kept out of client builds. SUPABASE_SERVICE_ROLE_KEY must only be used server-side and not committed to version control or exposed to the browser. - If you want ClawdBot to help with setup, restrict it to providing commands and checklists rather than collecting secrets. If you must provide keys to the skill, do so via a secure channel (not chat) and consider creating limited-scope API keys for this purpose. - If you plan to run the setup automatically, review the code paths that persist secrets and run migrations locally or in an isolated environment first. Given the mismatch between the manifest and the instructions and the explicit instruction to collect secrets in chat, treat this skill as suspicious until you confirm its provenance and adjust how secrets are supplied.

Like a lobster shell, security has layers — review code before you run it.

latestvk977wd9rqq9767qxd6yt3n9v1n85jzfe
40downloads
0stars
1versions
Updated 1d ago
v1.0.0
MIT-0

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

/**
 * 🤖 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](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:

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

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:

Comments

Loading comments...