Skip to content

calebyhan/hacknc25

Repository files navigation

Good Studio

AI-powered microsite builder for small nonprofits and community organizations

Launch a professional website in under 2 minutes with AI-generated branding, copy, and accessibility checks. Built with Next.js 14, FastAPI, Google Gemini, and Supabase.


What is Good Studio?

Good Studio helps tiny nonprofits, mutual-aid pods, and community organizers create beautiful, accessible websites without hiring a developer. Just provide your mission statement and logo — our multi-agent AI system handles the rest, streaming real-time progress as it works.

Key Features

AI Generation & Streaming:

  • Multi-agent AI pipeline: 4 specialized agents (Brand, Copywriter, Accessibility, Developer) work together using Google Gemini
  • Real-time SSE streaming: Watch agents work in real-time (not fake delays) via Server-Sent Events
  • React component generation: Auto-generates custom React components with Tailwind CSS
  • Smart fallback system: Never crashes - uses deterministic fallbacks if AI fails

Site Management:

  • Visual site editing: Live content editor with drag-and-drop block system (text, images, flex layouts)
  • Brand customization: Edit colors, fonts, and brand voice with visual color picker
  • Inline text editing: Click any text to edit it directly on your site
  • Content regeneration: Re-generate copy with different tone/audience settings

Event Management:

  • Public events: Create events with title, date, location, capacity, and virtual options
  • RSVP system: Built-in RSVP forms with email validation and capacity limits
  • Rate limiting: IP-based rate limiting prevents spam RSVPs
  • Dashboard analytics: View RSVP counts and attendee lists

Developer Experience:

  • Type-safe API: Pydantic models with full validation
  • Comprehensive tests: 100+ pytest tests with 90%+ coverage
  • Row Level Security: Multi-tenant data isolation via Supabase RLS
  • React Query integration: No useEffect for data fetching - modern async patterns

Quick Start

Prerequisites

  • Node.js 18+ (for Next.js frontend)
  • Python 3.13+ (for FastAPI backend)
  • PostgreSQL 14+ (via Supabase - free tier works)
  • Google AI Studio account (for Gemini 2.5 Flash Lite API key - free tier: 15 RPM)

Installation

  1. Clone the repo

    git clone https://github.com/yourusername/good-studio.git
    cd good-studio
  2. Install dependencies

    npm install
    
    # Backend dependencies (create virtual environment first)
    cd api
    python -m venv venv
    source venv/bin/activate  # On Windows: venv\Scripts\activate
    pip install -r requirements.txt
    cd ..
  3. Set up Supabase 📚

    IMPORTANT: Follow the complete setup guide: SUPABASE_SETUP.md

    This includes:

    • Creating a Supabase project
    • Configuring authentication (magic links)
    • Setting up redirect URLs (critical for auth to work!)
    • Running database migrations
    • Enabling Row Level Security
    • Creating storage bucket for logos

    Quick version:

    • Site URL: http://localhost:3000
    • Redirect URLs: http://localhost:3000/** and http://localhost:3000/auth/callback
    • Run SQL schema from docs/examples/fixtures.sql
  4. Set up environment variables

    Frontend (.env.local):

    cp .env.local.example .env.local

    Fill in:

    • NEXT_PUBLIC_SUPABASE_URL — from Supabase Settings → API
    • NEXT_PUBLIC_SUPABASE_ANON_KEY — from Supabase Settings → API

    Backend (api/.env.api):

    cp api/.env.api.example api/.env.api

    Fill in:

    GEMINI_API_KEY=your-gemini-api-key-here
    SUPABASE_URL=https://yourproject.supabase.co
    SUPABASE_SERVICE_ROLE_KEY=your-service-role-key
    DATABASE_URL=postgresql://postgres:password@localhost:5432/good_studio
    ALLOWED_ORIGINS=http://localhost:3000,http://localhost:3001
  5. Start dev servers

    npm run dev

    This runs both servers concurrently:

    Or run them separately:

    # Terminal 1 - Frontend
    npm run dev:web
    
    # Terminal 2 - Backend
    npm run dev:api

Project Structure

good-studio/
├── app/                           # Next.js 14 App Router
│   ├── page.tsx                  # Landing page
│   ├── login/                    # Login page
│   ├── signup/                   # Signup page
│   ├── auth/callback/            # Supabase auth callback
│   ├── dashboard/                # Protected dashboard
│   │   ├── page.tsx             # User dashboard with org list
│   │   └── org/[slug]/          # Org-specific dashboard
│   ├── new/                      # Onboarding flow
│   │   └── page.tsx             # 3-step wizard with SSE streaming
│   ├── orgs/                     # Public org pages
│   │   └── [slug]/page.tsx      # Live-editable org site
│   └── events/                   # Event pages
│       ├── page.tsx             # Event list
│       └── [id]/page.tsx        # Event detail with RSVP
│
├── components/                    # React components
│   ├── ui/                       # Shadcn-style base components
│   ├── dashboard/                # Dashboard-specific
│   │   ├── OrgSettings.tsx      # Brand & settings editor
│   │   ├── LiveContentEditor.tsx # Visual content block editor
│   │   ├── BrandEditor.tsx      # Color/font picker
│   │   ├── ContentEditor.tsx    # Text editing interface
│   │   ├── ContentBlocks.tsx    # Block type definitions
│   │   ├── EventManager.tsx     # Event CRUD
│   │   ├── CreateEventForm.tsx  # Event creation form
│   │   └── RSVPList.tsx         # RSVP viewer
│   ├── onboarding/
│   │   └── StepThreeSSE.tsx     # SSE streaming UI
│   └── navbar.tsx                # Main navigation
│
├── api/                           # FastAPI backend
│   ├── main.py                   # FastAPI app with all routes
│   ├── sse_generator.py          # SSE streaming endpoint
│   ├── multi_agent_system.py    # LangGraph agent orchestration
│   ├── ai_generator.py           # AI generation with fallback
│   ├── developer_agent.py        # React component generator
│   ├── visual_agent.py           # Image generation (deprecated)
│   ├── models.py                 # Pydantic models
│   ├── database.py               # Database connection utilities
│   ├── rate_limiter.py           # IP-based rate limiting
│   ├── agent_state.py            # Agent state TypedDict
│   ├── requirements.txt          # Python dependencies
│   └── tests/                    # Pytest suite (100+ tests)
│       ├── test_*.py            # Test files
│       └── conftest.py          # Pytest fixtures
│
├── lib/                           # Shared utilities
│   ├── supabase/                 # Supabase clients
│   │   ├── client.ts            # Browser client
│   │   └── server.ts            # Server client
│   └── queries/                  # React Query hooks
│       ├── orgs.ts              # Org CRUD operations
│       └── events.ts            # Event operations
│
├── hooks/                         # Custom React hooks
│   └── useSSEGeneration.ts       # SSE streaming hook
│
├── docs/                          # Documentation
│   ├── index.md                 # Project overview
│   ├── requirements.md          # User stories & database schema
│   ├── arch.md                  # Architecture deep dive
│   ├── build-order.md           # 24-hour timeline
│   └── prompts/                 # Implementation guides
│
└── scripts/                       # Utility scripts
    ├── test_rls.sh              # RLS validation
    └── test_rls_simple.sh       # Simple RLS test

Documentation


Tech Stack

Frontend:

  • Next.js 14 (App Router with Server Components)
  • React 18.3+ (TypeScript)
  • TailwindCSS 3.4
  • TanStack React Query 5 (no useEffect for data fetching)
  • React Hook Form + Zod (form validation)
  • Lucide React (icons)

Backend:

  • FastAPI 0.115+ (Python 3.13)
  • Google Gemini 2.5 Flash Lite (15 RPM free tier)
  • LangGraph (multi-agent orchestration)
  • Pydantic v2 (data validation)
  • SSE-Starlette (Server-Sent Events)
  • psycopg2 (PostgreSQL driver)

Database & Infrastructure:

  • Supabase Postgres 14+ (multi-tenant with RLS)
  • Supabase Auth (email magic links)
  • Supabase Storage (logo uploads)
  • Row Level Security for data isolation

Testing & Quality:

  • Pytest (100+ tests, 90%+ coverage)
  • FastAPI TestClient
  • Database fixtures for consistent testing

How It Works

1. Multi-Agent AI Pipeline with Real-Time Streaming

Four specialized AI agents work sequentially, streaming progress via SSE:

User Input (name, mission, logo, audience, tone)
    ↓
[SSE Stream Begins]
    ↓
🎨 Brand Agent (Google Gemini)
  → Analyzes mission and extracts brand personality
  → Generates 5-color palette (primary, secondary, accent, neutral, highlight)
  → Suggests font pairing (primary + accent fonts)
  → Defines brand voice (3-5 adjectives)
  [SSE Event: agent_complete with brand data]
    ↓
✍️ Copywriter Agent (Google Gemini)
  → Writes hero headline (5-8 words)
  → Crafts hero subheadline (1-2 sentences)
  → Drafts about section (2-3 paragraphs)
  → Creates primary & secondary CTAs
  [SSE Event: agent_complete with copy data]
    ↓
♿ Accessibility Agent
  → Generates descriptive logo alt-text
  → Validates WCAG AA contrast ratios
  → Checks reading level (target: 8th grade)
  → May trigger Brand Agent revision if contrast fails
  [SSE Event: agent_complete with a11y data]
    ↓
💻 Developer Agent
  → Generates custom React components with Tailwind
  → Creates layout structure (Hero, About, CTA sections)
  → Builds Tailwind config with brand colors
  [SSE Event: agent_complete with components]
    ↓
[SSE Event: workflow_complete with full site data]
    ↓
Frontend receives complete data → renders preview → saves to database

Key Innovation: Unlike fake progress bars, this uses actual Server-Sent Events to stream real-time updates as each agent completes its work. Total generation time: 5-15 seconds.

2. Onboarding Flow (3 Steps)

Step 1: Basic Info

  • Enter organization name
  • Write mission statement (2-3 sentences)
  • Select primary audience (volunteers, donors, community members, etc.)

Step 2: Branding

  • Upload logo (optional, 5MB max, stored in Supabase Storage)
  • Choose tone (warm, professional, energetic, friendly, etc.)

Step 3: Generation & Preview

  • Watch real-time SSE stream as 4 agents work (5-15 seconds total)
  • Preview generated site with brand colors, fonts, and copy
  • See generated React components and accessibility report
  • Publish to /orgs/[slug]

3. Visual Site Editor

After publishing, users can edit their site visually:

Content Block System:

  • Drag-and-drop blocks (text, images, flex containers)
  • Live preview while editing
  • Block types: markdown text, images with alt text, flex-row layouts
  • Nested blocks for complex layouts

Brand Customization:

  • Visual color picker for palette editing
  • Font selection (Google Fonts)
  • Real-time preview updates
  • Re-generate content with new tone/audience

4. Event Management System

Event Creation:

  • Title, description, date/time
  • Location (physical address or virtual link)
  • Capacity limits with automatic cutoff
  • Public/private visibility

RSVP System:

  • Public RSVP form with email validation
  • Duplicate email prevention
  • IP-based rate limiting (5 attempts per 15 minutes)
  • Real-time capacity tracking ("12/50 spots filled")

Dashboard Analytics:

  • List all events with RSVP counts
  • View attendee lists (name, email, timestamp)
  • Copy shareable event links
  • Filter upcoming/past events

Development

Run tests

# All tests
npm test

# Backend tests (recommended)
npm run test:backend              # All backend tests
npm run test:backend:unit         # Unit tests only
npm run test:backend:integration  # Integration tests only
npm run test:backend:rls          # Row Level Security validation

# Or directly with pytest
cd api
pytest -v --tb=short              # Verbose with short tracebacks
pytest test_ai_generator.py -v   # Specific test file
pytest -k "test_rsvp" -v          # Tests matching pattern

Test Coverage:

  • 100+ tests across all backend modules
  • 90%+ code coverage
  • AI generation (with fallback testing)
  • RSVP flow (capacity, duplicates, rate limiting)
  • Row Level Security (RLS) validation
  • Database constraints and triggers

Environment-Specific Testing

Test with AI fallback (no API key required):

cd api
export TEST_AI_FALLBACK=true
pytest test_ai_generator.py -v

Test with real Gemini API:

cd api
# Make sure GEMINI_API_KEY is in .env.api
pytest test_ai_generator.py -v

Lint & format

npm run lint             # ESLint for TypeScript/React
# Backend uses type hints and Pydantic for validation

Database migrations

# Via Supabase SQL Editor (recommended)
# Copy SQL from docs/requirements.md and run in Supabase dashboard

# Or via command line (if DATABASE_URL is set)
npm run db:migrate

Deployment

Next.js (Vercel)

  1. Push to GitHub
  2. Import repo in Vercel
  3. Add environment variables
  4. Deploy

FastAPI (Render/Railway)

  1. Create new web service
  2. Set build command: pip install -r api/requirements.txt
  3. Set start command: uvicorn api.main:app --host 0.0.0.0 --port $PORT
  4. Add GEMINI_API_KEY environment variable
  5. Deploy

API Endpoints

Public Endpoints

  • GET / - API health check
  • GET /health - Detailed health status
  • GET /api/events?org={slug} - List public events for an organization
  • GET /api/events/{id} - Get single event details
  • POST /api/rsvp - Create RSVP for an event (rate limited)
  • POST /events/{id}/rsvps - RESTful RSVP endpoint

Protected Endpoints (require auth)

  • POST /generate-site - Generate site with AI (with fallback)
  • POST /generate-site-stream - SSE streaming endpoint for real-time progress
  • POST /generate-site-complete - Full multi-agent pipeline with components
  • PUT /api/orgs/{id} - Update org details (name, mission, logo)
  • PUT /api/orgs/{id}/brand - Update brand colors and fonts
  • PUT /api/orgs/{id}/content - Update content blocks (visual editor)
  • POST /api/orgs/{id}/regenerate - Regenerate content with new tone/audience

Rate Limiting

  • RSVP endpoints: 5 requests per 15 minutes per IP+event
  • Uses in-memory rate limiter with sliding window

Architecture Highlights

Multi-Tenant Security

  • Row Level Security (RLS) policies enforce data isolation
  • Each org has a single owner (no multi-user orgs yet)
  • Public pages readable by all; dashboard requires authentication
  • Service role key used for server-side operations only

AI Fallback System

  • Never crashes - if AI fails, uses deterministic fallback data
  • Environment variable TEST_AI_FALLBACK=true forces fallback mode
  • Fallback data is production-quality, not lorem ipsum
  • Useful for development without API key or rate limit testing

SSE Streaming Implementation

  • Uses sse-starlette for Server-Sent Events
  • Frontend connects via fetch() with ReadableStream
  • Events: agent_start, agent_complete, workflow_complete, error
  • Automatic reconnection and error handling
  • No polling required - real-time updates

Contributing

This was built as a hackathon project. Contributions welcome!

Current Status (✅ = Complete)

  • ✅ Multi-agent AI generation with SSE streaming
  • ✅ Real-time progress updates (not fake delays)
  • ✅ React component code generation
  • ✅ Visual content block editor
  • ✅ Brand customization (colors, fonts)
  • ✅ Event management with RSVP system
  • ✅ Rate limiting and spam prevention
  • ✅ Row Level Security (RLS)
  • ✅ 100+ tests with 90%+ coverage
  • ✅ AI fallback system

Roadmap

  • Multi-page sites (About, Contact, etc.)
  • Image generation (HuggingFace integration - currently deprecated)
  • Email notifications (Resend integration)
  • Private events with join codes
  • Team member roles (multi-user orgs)
  • Custom domains
  • Donation integration (Stripe)
  • Analytics dashboard (page views, RSVP trends)
  • A/B testing for copy variations
  • SEO optimization tools

See docs/build-order.md for detailed implementation timeline.


Troubleshooting

Backend Not Running

If you see "Failed to fetch" errors in the frontend:

# Check if backend is running
curl http://localhost:8000

# If not, start it
cd api
source venv/bin/activate
uvicorn main:app --reload --port 8000

Database Connection Issues

# Test database connection
psql $DATABASE_URL -c "SELECT 1"

# Check if tables exist
psql $DATABASE_URL -c "\dt"

AI Generation Fails

If AI generation times out or fails:

# Use fallback mode (no API key needed)
cd api
export TEST_AI_FALLBACK=true
uvicorn main:app --reload

Port Already in Use

# Find process using port 8000
lsof -i :8000

# Kill it
pkill -f uvicorn

# Or use a different port
uvicorn main:app --reload --port 8001

Rate Limit Exceeded (Gemini API)

Free tier: 15 requests per minute

  • Wait 1 minute between requests
  • Or use TEST_AI_FALLBACK=true for unlimited testing

License

MIT License - feel free to use this for your own projects!


Support & Resources


Acknowledgments

Built for HackNC 2025 using:

About

Submission for HackNC 2025

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •