Generate production-quality websites in minutes using Claude Sonnet 4.5.
Thundercloud is an AI-powered website builder that creates professional, SEO-optimized, accessible websites using advanced AI. Unlike template-based builders, Thundercloud generates custom code tailored to your specific needs.
- β AI Website Generation - Claude Sonnet 4.5 creates custom HTML/CSS
- β Quality Validation - 50+ automated quality checks (SEO, accessibility, performance)
- β Real-time Preview - See your site on mobile, tablet, desktop
- β One-Click Deployment - Publish instantly with preview URL
- β Type-Safe API - End-to-end TypeScript with tRPC
- β Secure by Default - Row-level security (RLS) on all data
- Node.js 20+ and npm
- Supabase account (free tier works)
- Anthropic API key (Claude)
git clone <your-repo-url> thundercloud-app
cd thundercloud-app
npm installCreate .env.local:
# Supabase (get from https://supabase.com/dashboard)
NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
# Anthropic (get from https://console.anthropic.com/)
ANTHROPIC_API_KEY=sk-ant-...- Go to Supabase Dashboard β SQL Editor
- Copy contents of
supabase/schema.sql - Run the SQL script
- Verify tables created (21 tables total)
npm run dev- Sign up at
/signup - Go to Dashboard
- Click "Create Website"
- Fill in details, click "Generate"
- Wait 30-60 seconds
- Preview and save!
thundercloud-app/
βββ src/
β βββ app/ # Next.js 15 App Router
β β βββ (auth)/ # Auth pages (login, signup)
β β βββ (dashboard)/ # Dashboard pages
β β βββ api/trpc/ # tRPC API routes
β β βββ layout.tsx # Root layout
β β βββ page.tsx # Landing page
β βββ components/
β β βββ ui/ # shadcn/ui components
β β βββ auth/ # Auth components
β β βββ websites/ # Website components
β βββ lib/
β β βββ supabase/ # Supabase clients
β β βββ ai/ # AI generation & validation
β β βββ trpc/ # tRPC client setup
β β βββ utils.ts # Utilities
β βββ server/
β βββ trpc.ts # tRPC setup
β βββ routers/ # API routers
βββ public/ # Static files
βββ supabase/
β βββ schema.sql # Database schema
βββ package.json
| Variable | Required | Description |
|---|---|---|
NEXT_PUBLIC_SUPABASE_URL |
β | Your Supabase project URL |
NEXT_PUBLIC_SUPABASE_ANON_KEY |
β | Supabase anonymous key (public) |
ANTHROPIC_API_KEY |
β | Claude API key (secret) |
Security Notes:
- β
NEXT_PUBLIC_*vars are safe in browser (public) β οΈ ANTHROPIC_API_KEYis server-only (never exposed)- β All database access protected by RLS
| Layer | Technology | Why? |
|---|---|---|
| Frontend | Next.js 15 + React 19 | Server Components, App Router |
| Backend | tRPC + Next.js API | Type-safe APIs, no codegen |
| Database | Supabase (PostgreSQL) | Managed DB + Auth + RLS |
| AI | Anthropic Claude Sonnet 4.5 | Best-in-class code generation |
| Auth | Supabase Auth | JWT + RLS |
| Styling | Tailwind CSS | Utility-first CSS |
| UI | shadcn/ui | Accessible components |
| Deployment | Vercel | Zero-config, edge functions |
user_profiles - User accounts
- id (uuid, PK)
- email (text)
- full_name (text)
- role (text) - 'user' | 'admin'
- subscription_tier (text) - 'free' | 'pro' | 'agency'
- created_date (timestamp)websites - Generated websites
- id (uuid, PK)
- user_id (uuid, FK β user_profiles)
- title (text)
- description (text)
- slug (text, unique)
- html_content (text) - Full HTML output
- quality_score (integer) - 0-100
- seo_score (integer) - 0-100
- is_published (boolean)
- created_date (timestamp)See supabase/schema.sql for complete schema (21 tables).
- JWT tokens via Supabase Auth
- 30-day session expiry
- PKCE flow for OAuth (future)
- Row Level Security (RLS) on all tables
- Users can only access their own data
- Policy:
auth.uid() = user_id
- Zod schemas on all API inputs
- SQL injection prevention (parameterized queries)
- XSS prevention (DOMPurify on HTML output)
- 100 API requests/hour per user
- 10 website generations/hour per user
- Enforced at API gateway
npm run type-checknpm run lint- Start dev server:
npm run dev - Test generation:
- Go to
/dashboard/websites/new - Fill form, click "Generate"
- Check console for errors
- Verify website saved to dashboard
- Go to
- Push code to GitHub:
git add .
git commit -m "Initial commit"
git push origin main-
Import to Vercel:
- Go to vercel.com
- Click "Import Project"
- Select your repo
- Add environment variables
- Deploy!
-
Configure environment variables in Vercel:
- Go to Project Settings β Environment Variables
- Add all 3 env vars from
.env.local - Redeploy
Database is already deployed when you create Supabase project:
- β Production PostgreSQL
- β Automatic backups
- β SSL encryption
- β Global CDN
- Dashboard load: < 2 seconds
- Website generation: < 60 seconds
- Preview load: < 3 seconds
- API response: < 500ms (p95)
- Use React Query caching (already configured)
- Enable Next.js Image optimization for user uploads
- Add CDN caching for static assets
- Database indexes on
user_id,website_id(already added)
rm -rf node_modules package-lock.json
npm install- Check
NEXT_PUBLIC_SUPABASE_URLis correct - Verify anon key in
.env.local - Ensure RLS policies are created (run schema.sql)
- Check
ANTHROPIC_API_KEYis valid - Verify API key has credits
- Check Anthropic API status: https://status.anthropic.com/
- Clear browser cookies
- Check Supabase Auth settings
- Verify RLS policies allow user access
// List websites (paginated)
trpc.websites.list.useQuery({
page: 1,
pageSize: 10,
sortBy: 'created_date',
sortOrder: 'desc'
})
// Get single website
trpc.websites.getById.useQuery({ id: 'uuid' })
// Create website
trpc.websites.create.useMutation({
title: 'My Site',
slug: 'my-site',
html_content: '<html>...',
// ... other fields
})
// Update website
trpc.websites.update.useMutation({
id: 'uuid',
data: { title: 'New Title' }
})
// Delete website
trpc.websites.delete.useMutation({ id: 'uuid' })
// Toggle publish status
trpc.websites.togglePublish.useMutation({ id: 'uuid' })// Generate new website
trpc.generation.generate.useMutation({
title: 'My Business',
description: 'Professional consulting...',
category: 'business',
theme: 'modern',
colorScheme: 'Professional Blue',
language: 'English'
})
// Regenerate existing
trpc.generation.regenerate.useMutation({
id: 'uuid',
prompt: { title: 'Updated Title' }
})
// Validate HTML
trpc.generation.validate.useMutation({
html: '<html>...'
})- Update prompt templates in
src/lib/ai/prompts.ts:
export const PRODUCTION_PROMPTS = {
templates: {
// Add new category
nonprofit: {
sections: [
'Mission statement',
'Impact metrics',
// ...
]
}
}
}- Update form in
src/app/(dashboard)/websites/new/page.tsx:
const categories = [
// Add to dropdown
{ value: 'nonprofit', label: 'Non-Profit' },
]Edit src/lib/ai/quality-validator.ts:
private validateSEO(doc: Document, html: string): ValidationCheck {
// Add custom checks
if (!html.includes('custom-tag')) {
issues.push('Missing custom tag');
score -= 5;
}
}- Next.js Docs: https://nextjs.org/docs
- tRPC Docs: https://trpc.io/docs
- Supabase Docs: https://supabase.com/docs
- Anthropic Docs: https://docs.anthropic.com/
- Tailwind CSS: https://tailwindcss.com/docs
- shadcn/ui: https://ui.shadcn.com/
This is an MVP. Contributions welcome after initial launch.
[Your License Here]
- π§ Email: support@thundercloud.com
- π¬ Discord: discord.gg/thundercloud
- π Docs: docs.thundercloud.com
Built with β€οΈ using Claude Sonnet 4.5