The internet's most brutal code review platform.
DevRoast is a web application where developers submit code snippets and receive honest, sometimes hilarious feedback from the community. Think of it as code review meets comedy — where bad code gets the roasting it deserves.
Every great developer has written bad code. DevRoast is here to celebrate that journey. 🔥
- What is DevRoast?
- Key Features
- How It Works
- Getting Started
- Production Deployment
- Development Setup
- Project Structure
- Tech Stack
- API & Features
- Database
- Contributing
- AI-Assisted Development
- Troubleshooting
Tired of polite code reviews? DevRoast changes the game by offering a judgment-free zone where code gets roasted with style. Whether you're writing the worst code imaginable or just curious about how others will critique it, DevRoast has you covered.
- Code Submission - Submit any code snippet in your favorite language
- AI-Powered Feedback - Get instant feedback using Google Gemini API
- Roast Mode - Toggle between standard feedback and full roast mode for maximum entertainment
- Real-time Updates - Get feedback as soon as it's generated (no page refresh needed)
- Shame Leaderboard - See which code made it to the internet's hall of shame with pagination
- Syntax Highlighting - Code is displayed with beautiful syntax highlighting via Shiki
- Dark Terminal Aesthetic - A sleek, terminal-inspired design inspired by developer culture
- Rate Limiting - Spam protection with per-IP and global cooldown limits
- Paginated Leaderboard - Browse submissions with 10 items per page and smart navigation controls
- Paste Your Code - Copy and paste any code snippet (1-50,000 characters) into the submission form
- Choose Mode - Select between standard feedback (professional) or roast mode (sarcastic)
- Get Feedback - Submit and receive AI-generated feedback in real-time
- View Results - See your shame score, issue breakdown, and detailed feedback
- Check the Leaderboard - See how your code ranks among the "worst" on the internet
- Visit the DevRoast website
- Paste your code in the submission form
- Choose your preferred feedback mode (standard or roast)
- Click "Start the Roast" and wait for your verdict
- Share your results or learn from the shame leaderboard
See the Development Setup section below.
🚀 Production URL: https://devroast-one.vercel.app
The application is fully deployed and running on Vercel with Supabase as the production database.
- Hosting: Vercel (iad1 region, Washington D.C.)
- Database: Supabase PostgreSQL with Connection Pooler
- Infrastructure: Uses Connection Pooler for serverless compatibility
Set in Vercel Dashboard > Settings > Environment Variables:
DATABASE_URL=[Supabase Connection Pooler string from dashboard]
NEXT_PUBLIC_SUPABASE_URL=[Supabase Project URL from Settings > API]
NEXT_PUBLIC_SUPABASE_ANON_KEY=[From Supabase Settings > API]
GEMINI_API_KEY=[your-gemini-api-key]Get connection strings from:
- Supabase Dashboard > Settings > Database > Connection String
- Switch to "Connection Pooler" mode for production
For detailed deployment information, see specs/DEPLOYMENT.md:
- Complete setup instructions
- Environment configuration
- Troubleshooting guide
- Database migration steps
- Network configuration
- Node.js 18+ with pnpm
- PostgreSQL 16+ (Docker Compose included)
- Google Gemini API Key (free tier available at https://ai.google.dev)
- Docker & Docker Compose (for local database)
-
Clone the repository
git clone <repository-url> cd devroast
-
Install dependencies
pnpm install
-
Set up environment variables
# Create .env.local file with required variables echo "DATABASE_URL=postgresql://devroast:devroast_dev_password@localhost:5432/devroast_db" > .env.local echo "GEMINI_API_KEY=your-gemini-api-key" >> .env.local
-
Start the database
# Start PostgreSQL with Docker Compose docker-compose up -d # Run migrations pnpm db:migrate
-
Start the development server
pnpm dev
-
Open your browser
http://localhost:3000
# Database
DATABASE_URL=postgresql://devroast:devroast_dev_password@localhost:5432/devroast_db
# AI/Gemini
GEMINI_API_KEY=your-gemini-api-key
# Node Environment
NODE_ENV=developmentSet via CI/CD secrets or environment management:
DATABASE_URL=postgresql://[user]:[password]@[host]:5432/[database]
GEMINI_API_KEY=[your-gemini-key]
NODE_ENV=productiondevroast/
├── src/
│ ├── app/ # Next.js app directory
│ │ ├── api/ # API routes
│ │ │ ├── feedback/[id]/ # Feedback polling endpoint
│ │ │ └── trpc/[trpc]/ # tRPC API handler
│ │ ├── leaderboard/ # Leaderboard page
│ │ ├── results/[id]/ # Submission results page
│ │ ├── examples/ # Example components page
│ │ ├── layout.tsx # Root layout with navbar
│ │ ├── page.tsx # Home page
│ │ └── globals.css # Global styles
│ │
│ ├── components/ # React components
│ │ ├── ui/ # Core UI components
│ │ │ ├── Button.tsx # Button component
│ │ │ ├── Card.tsx # Card component
│ │ │ ├── Toggle.tsx # Toggle component
│ │ │ ├── BadgeStatus.tsx # Status badge component
│ │ │ ├── CodeBlock.tsx # Code display component
│ │ │ ├── CodeEditor.tsx # Code editor component with language selector
│ │ │ ├── LeaderboardCodeBlock.tsx # Leaderboard code display
│ │ │ └── index.ts # Barrel export
│ │ ├── ScoreCardSkeleton.tsx # Skeleton loader for score card
│ │ ├── MetricsSkeleton.tsx # Skeleton loader for metrics
│ │ ├── LeaderboardContent.tsx # Paginated leaderboard client component
│ │ ├── LeaderboardTable.tsx # Leaderboard table display
│ │ ├── LeaderboardSkeleton.tsx # Skeleton loader for leaderboard
│ │ ├── CodeEditorSection.tsx # Code submission editor section
│ │ ├── HomeMetrics.tsx # Home page metrics display
│ │ ├── HomeMetricsSection.tsx # Metrics section wrapper
│ │ ├── HomeLeaderboardSection.tsx # Home page leaderboard preview
│ │ ├── HomeLeaderboardSkeleton.tsx # Skeleton for home leaderboard
│ │ └── index.ts # Main component export
│ │
│ ├── db/ # Database layer
│ │ ├── schema/ # Drizzle ORM schema definitions
│ │ │ ├── submissions.ts # Submissions table and enums
│ │ │ ├── feedback.ts # Feedback table
│ │ │ ├── roasts.ts # Roasts/leaderboard table
│ │ │ └── index.ts # Re-exports
│ │ ├── queries/ # Drizzle ORM queries
│ │ │ ├── submissions.ts # Submission queries
│ │ │ ├── feedback.ts # Feedback queries
│ │ │ ├── roasts.ts # Roast/leaderboard queries
│ │ │ └── index.ts # Re-exports
│ │ └── client.ts # Database connection
│ │
│ ├── server/ # Server-side logic
│ │ ├── trpc/ # tRPC setup
│ │ │ ├── init.ts # tRPC initialization
│ │ │ ├── router.ts # Main router
│ │ │ ├── server.tsx # Server-side tRPC caller
│ │ │ └── routes/ # Route handlers
│ │ │ ├── submissions.ts # Submission procedures
│ │ │ └── metrics.ts # Metrics and leaderboard procedures
│ │ ├── lib/ # Server utilities
│ │ │ ├── submissions.ts # Submission processing and feedback generation
│ │ │ ├── gemini.ts # Gemini API integration
│ │ │ └── rate-limiter.ts # Rate limiting
│ │ └── env.ts # Environment validation
│ │
│ ├── lib/ # Client/shared utilities
│ │ ├── severity.ts # Severity score calculation
│ │ └── trpc.ts # tRPC client setup
│ │
│ ├── utils/ # Utility functions
│ │ └── language.ts # Language utilities
│ │
│ ├── data/ # Mock/sample data
│ │ └── submissions.ts # Sample submission data
│ │
│ └── types/ # TypeScript types
│ └── css.d.ts # CSS module types
│
├── drizzle/ # Database migrations
│ └── migrations/ # Auto-generated migration files
│
├── scripts/ # Utility scripts
│ ├── seed.ts # Database seeding
│ └── init.sql # SQL initialization
│
├── specs/ # Project specifications
│ └── CODE_SUBMISSION_IMPLEMENTATION.md # Code submission system spec
│
├── docker-compose.yml # Docker compose for local dev
├── drizzle.config.ts # Drizzle ORM config
├── next.config.ts # Next.js config
├── tailwind.config.js # Tailwind CSS config
├── biome.json # Code linting/formatting
├── tsconfig.json # TypeScript config
├── package.json # Dependencies
├── AGENTS.md # Development guide for agents
├── DATABASE.md # Database setup guide
└── README.md # This file
- Next.js 16 - React 19 framework with SSR/SSG
- React 19 - Modern React with hooks and server components
- TypeScript 5 - Type-safe JavaScript development
- Tailwind CSS v4 - Utility-first CSS framework
- tailwind-variants - Type-safe variant composition
- JetBrains Mono - Monospace font for code and terminal aesthetic
- PostgreSQL 16 - Production database
- Drizzle ORM - TypeScript-first ORM
- Drizzle Kit - Schema management and migrations
- Google Gemini API - AI-powered code feedback generation
- Shiki - Server-side syntax highlighting
- Biome - Code formatting and linting
- pnpm - Fast, space-efficient package manager
- tRPC - Type-safe API layer with end-to-end type safety
- Zod - Runtime schema validation
- Docker & Docker Compose - Local development environment
Endpoint: POST /api/trpc/submissions.create
Submit code for analysis and feedback.
Request:
{
code: string // 1-50,000 characters
language: string // See supported languages below
roastMode: boolean // true for sarcastic, false for professional
}Response:
{
id: string // UUID of submission
code: string
language: string
roastMode: boolean
createdAt: Date
}Supported Languages:
- JavaScript/TypeScript
- Python
- Java
- C/C++
- Go
- Rust
- HTML/CSS
- JSON
- And more...
Endpoint: GET /api/feedback/[submissionId]
Poll for AI-generated feedback.
Response:
{
id: string
content: string // Feedback text
issuesFound: number
recommendationsCount: number
severityScore: number // 0-100 scale
}
// Returns null if feedback not yet generatedEndpoint: GET /api/trpc/metrics.getLeaderboard
Get paginated leaderboard submissions with filtering and sorting support.
Request:
{
page: number // Page number (1-indexed, default: 1)
pageSize: number // Items per page (1-100, default: 10)
}Response:
{
items: [
{
id: string
rank: number
score: string
code: string
language: string
createdAt: Date
},
...
],
pagination: {
page: number
pageSize: number
totalCount: number
totalPages: number
}
}Legacy Endpoint: GET /api/trpc/roasts.getTopRoasts
Get the top "worst" code submissions (non-paginated, for home preview).
Response:
[
{
id: string
code: string
language: string
severityScore: number
viewCount: number
createdAt: Date
feedback: {
content: string
severityScore: number
}
},
...
]Stores all code submissions.
| Column | Type | Description |
|---|---|---|
id |
UUID | Primary key |
code |
TEXT | Code snippet |
language |
ENUM | Programming language |
roast_mode |
BOOLEAN | Roast mode enabled |
severity_score |
INTEGER | 0-100 severity rating |
view_count |
INTEGER | Number of views |
created_at |
TIMESTAMP | Creation time |
updated_at |
TIMESTAMP | Last update time |
Stores AI-generated feedback.
| Column | Type | Description |
|---|---|---|
id |
UUID | Primary key |
submission_id |
UUID | Foreign key to submissions |
feedback_type |
ENUM | 'standard' or 'roast' |
content |
TEXT | Feedback text |
issues_found |
INTEGER | Number of issues |
recommendations_count |
INTEGER | Number of recommendations |
created_at |
TIMESTAMP | Creation time |
updated_at |
TIMESTAMP | Last update time |
Leaderboard and ranking data.
| Column | Type | Description |
|---|---|---|
id |
UUID | Primary key |
submission_id |
UUID | Foreign key to submissions |
rank_position |
INTEGER | Leaderboard position |
severity_rating |
INTEGER | 0-100 severity score |
critical_issues_count |
INTEGER | Critical issues |
badges |
TEXT[] | Earned badges |
last_ranked_at |
TIMESTAMP | Last ranking update |
created_at |
TIMESTAMP | Creation time |
updated_at |
TIMESTAMP | Last update time |
# Start PostgreSQL with Docker Compose
docker-compose up -d
# Stop Docker containers
docker-compose down
# View Docker logs
docker-compose logs -f postgres
# Run pending migrations
pnpm db:migrate
# Generate new migrations
pnpm db:generate
# Open Drizzle Studio (GUI)
pnpm db:studio
# Seed database with sample data
pnpm seed
# Reset everything (WARNING: deletes data)
docker-compose down -v && docker-compose up -dPostgreSQL Direct Connection:
- Host:
localhost - Port:
5432 - Username:
devroast - Password:
devroast_dev_password - Database:
devroast_db
PgAdmin (Web UI):
- URL: http://localhost:5050
- Email:
admin@devroast.local - Password:
admin_password
All components follow consistent patterns and use tailwind-variants for styling:
<Button variant="primary" size="md">Click me</Button>Variants: primary, secondary, link, danger, ghost Sizes: sm, md, lg
<Card>
<Card.Header>
<Card.Title>Title</Card.Title>
<Card.Badge>New</Card.Badge>
</Card.Header>
<Card.Description>Description text</Card.Description>
</Card><Toggle defaultChecked variant="primary">
Toggle label
</Toggle><BadgeStatus variant="critical">Critical Issue</BadgeStatus>Variants: critical, warning, good, needs_serious_help
<CodeBlock code={code} language="javascript" /><ScoreCardSkeleton />Shows animated placeholder while AI feedback is generating.
- ✅ Use
tailwind-variantsfor all styling - ✅ Use
forwardReffor native element refs - ✅ Use
HTMLAttributesto extend native elements - ✅ Named exports only (no default exports)
- ✅ Use
useId()for dynamic IDs (SSR-safe) - ✅ Pass className via
class:parameter totv() - ✅ Async server components for data fetching
- ❌ Never use
tailwind-merge - ❌ Never use hex colors (Tailwind classes only)
- ❌ Never use default exports
pnpm dev # Start Next.js dev server
pnpm build # Build for production
pnpm start # Start production serverpnpm lint # Run Biome linter
pnpm format # Format code with Biome
pnpm check # Run all Biome checkspnpm db:generate # Generate migrations
pnpm db:migrate # Run migrations
pnpm db:push # Push schema (unsafe)
pnpm db:studio # Open Drizzle Studio
pnpm seed # Seed databasedocker-compose up -d # Start containers
docker-compose down # Stop containers
docker-compose logs -f postgres # View logs
docker-compose down -v # Remove volumes (reset data)DevRoast embraces a dark, terminal-inspired aesthetic that appeals to developers:
- JetBrains Mono - Monospace font that feels native to code editors
- Dark Theme - Reduced eye strain with
bg-gray-950as primary background - Minimal Design - Clean, focused layout with no distractions
- Color-Coded Feedback:
- 🔴 Red for critical issues
- 🟡 Amber for warnings
- 🟢 Green for good code
- 🔵 Blue for informational
- Background:
bg-gray-950(primary),bg-gray-900(containers) - Text:
text-gray-100(headings),text-gray-300(body),text-gray-400(labels) - Borders:
border-gray-700 - Accent:
emerald-500(primary action/highlight) - Status: Various Tailwind status colors
- Create a feature branch:
git checkout -b feat/your-feature-name - Make your changes following the component patterns above
- Run linting and formatting:
pnpm check && pnpm format - Build to verify:
pnpm build - Commit with clear messages (no automatic commits - ask first!)
- Push and create a pull request
- Formatting: Use Biome (
pnpm format) - Linting: Pass all Biome checks (
pnpm check) - TypeScript: No
anytypes, strict mode enabled - Components: Follow the component pattern documented in
AGENTS.md - Naming: Use clear, descriptive names for variables and functions
- Documentation: Add comments for complex logic
- Always ask for confirmation before creating commits
- Use descriptive commit messages
- Do not force push to main without explicit permission
- Keep feature branches small and focused
- Component Creation: See
AGENTS.mdfor detailed patterns - Database Queries: See
DATABASE.mdfor schema and query examples - Code Submission System: See
specs/CODE_SUBMISSION_IMPLEMENTATION.md
This project was built with the assistance of Claude Haiku 4.5, a capable yet lightweight AI model. Despite its modest footprint, the development results were exceptional through a structured, iterative approach:
Speed-Focused Workflow:
- AI was used to rapidly prototype features, fix bugs, and implement best practices
- Development cycles were 3-4x faster than traditional manual development
- Complex features like tRPC integration, rate limiting, and async feedback generation were implemented in hours
- Critical bugs (missing leaderboard entries, pagination errors, async component issues) were diagnosed and fixed in minutes
Quality Improvement Process:
- Analysis Phase: Comprehensive codebase audits and documentation reviews
- Planning: Clear specifications and requirements before implementation
- Implementation: AI generated initial code with established patterns
- Review & Testing: Manual verification and continuous feedback
- Iteration: AI improved code based on specific feedback
- Validation: Full build verification and quality checks
- IDE: VSCode with Git integration
- AI Assistant: OpenCode CLI (powered by Claude Haiku 4.5)
- Version Control: Git with structured commits
The development process leveraged specialized MCP servers for enhanced capabilities:
1. Context7 MCP
- Real-time documentation and API reference lookups
- Library version-specific examples and code snippets
- Resolved library IDs and best practices for frameworks like Next.js, tRPC, and Tailwind
- Used for: Framework recommendations, API integration patterns, library-specific guidance
2. Pencil MCP
- Design system and UI component management
- Would have been used for: Design documentation, component specifications, design tokens (if design phase was needed)
- Provides structured design rules and component patterns
3. Playwright MCP
- End-to-end visual testing and regression detection
- Defined 14 comprehensive tests covering home page, leaderboard, results page, responsive design, and visual regressions
- Used for: Test configuration, test execution, visual baseline management
4. Skills System
context7-mcpskill: Activated for library/framework questions and code generation- Provides specialized instructions for working with libraries and frameworks
- Enhanced AI context with domain-specific knowledge
- ✅ 7 critical bugs fixed across components, tRPC, pagination, and async handling
- ✅ Production-ready codebase with proper error handling and type safety
- ✅ 100% test coverage on build — zero TypeScript errors
- ✅ Comprehensive documentation with accurate specs and guides
- ✅ Best practices implemented — proper component patterns, database design, rate limiting
- ✅ Security hardened — environment variables properly managed, production secrets excluded from git
Session 1: Bug Fixes & Documentation
- Fixed critical roast entry creation bug preventing submissions from appearing on leaderboard
- Fixed metrics query to count correct data source
- Fixed language dropdown to show all 17 supported languages
- Updated documentation to reflect actual codebase structure
- Fixed package version specs
Session 2: Pagination & tRPC
- Fixed HTTP 405 errors in pagination
- Implemented proper tRPC client with httpBatchLink
- Fixed GET vs POST method handling for queries
Session 3: Component Architecture
- Fixed async component errors in LeaderboardCodeBlock and LeaderboardTable
- Converted async server components to proper client components
- Implemented proper useEffect patterns for syntax highlighting
- Fixed tRPC method routing (queries use GET, mutations use POST)
Session 4: Security & Cleanup
- Added .env.production to gitignore
- Removed production secrets from git history
- Verified build integrity
Session 5: Production Timeout Fixes & Deployment (April 7, 2026)
- Problem: Intermittent "Feedback generation took too long" errors in production
- Solution: Implemented comprehensive timeout handling and automatic retry logic
- 30-second timeout on Gemini API calls with automatic retry (3 attempts)
- Exponential backoff between retries (1s, 2s, 4s)
- 45-second overall operation timeout to prevent serverless hangs
- Extended polling window from 120s to 180s for better UX
- Better error messages with attempt tracking and elapsed time logs
- Result: Build passed with zero errors, deployed to production with improved reliability
- Commits:
51415ce(timeout fixes),26051c7(merge), force pushed to GitHub
Even with a smaller model, exceptional results came from:
- Clear Communication: Detailed problem descriptions and desired outcomes
- Structured Feedback: Specific issues, exact error messages, and file references
- Iterative Dialogue: Back-and-forth refinement rather than one-shot requests
- Code Review: Manual inspection and validation of all changes
- Testing: Build verification before each commit
- Documentation: Clear specs and patterns for consistency
- AI quality depends on context — Providing full codebase understanding yields better solutions
- Structured feedback loops are critical — "This doesn't work" vs "Line 42 throws error X" have different impacts
- Documentation as guardrails — Well-documented patterns guide AI to consistent code
- Build verification is essential — Catching issues immediately prevents cascading problems
- Smaller models can be highly effective — With the right workflow, model size is less important than context and feedback
Port already in use:
# Kill the process on port 3000
lsof -i :3000
kill -9 <PID>
# Or use a different port
pnpm dev -- -p 3001Build errors:
# Clear Next.js cache
rm -rf .next
# Rebuild
pnpm buildDocker container won't start:
# Check logs
docker-compose logs -f postgres
# Reset (WARNING: deletes data)
docker-compose down -v && docker-compose up -dCannot connect to database:
# Verify containers are running
docker ps
# Check DATABASE_URL
cat .env.local
# Test connection
psql postgresql://devroast:devroast_dev_password@localhost:5432/devroast_dbMigration failed:
# Check applied migrations
psql -c "SELECT * FROM \"_drizzle_migrations\";" $DATABASE_URL
# Rollback manually if needed (see Drizzle docs)API key not working:
- Verify key is in
.env.local - Check key is valid at https://ai.google.dev
- Ensure you have API credits (free tier available)
- Check server logs for detailed error messages
Feedback not generating:
- Check
[Gemini]and[Submissions]logs in server output - Verify API response with:
curl -H "Authorization: Bearer YOUR_KEY" https://generativelanguage.googleapis.com/v1beta/models/gemini-flash-latest:generateContent - Check database that feedback row exists:
SELECT * FROM feedback WHERE submission_id = 'id';
Score card not updating:
- Open browser DevTools console
- Check for
[ResultsContent]logs - Verify
/api/feedback/[id]returns null initially, then feedback object - Check that feedback row is being created (may take 5-30 seconds)
Feedback generation timeout: The system now includes automatic retry logic and extended timeout windows:
- Each Gemini API call has a 30-second timeout with automatic retry (up to 3 attempts)
- Polling window is 180 seconds (90 polls × 2 seconds each)
- Exponential backoff is used between retries (1s, 2s, 4s)
- Most submissions complete within 5-15 seconds
If you still see "Feedback generation took too long" error:
- Check server logs for
[Gemini]or[generateAndSaveFeedback]messages - Verify Gemini API is accessible from your network
- Check Vercel logs in the dashboard for execution time
- Try submitting again - retries typically resolve temporary API issues
Current indexes cover common queries. Consider adding for large datasets:
CREATE INDEX idx_submissions_created_at ON submissions(created_at DESC);
CREATE INDEX idx_submissions_severity ON submissions(severity_score DESC);
CREATE INDEX idx_roasts_severity ON roasts(severity_rating DESC);Rate limits prevent abuse:
- Per-IP: 5 submissions per hour (configurable)
- Global: 30-second cooldown between all submissions
Adjust in src/server/lib/rate-limiter.ts as needed.
Consider adding Redis for:
- Leaderboard caching
- Feedback polling results
- User submission history
- ✅ Never commit
.env.local(in.gitignore) - ✅ Use prepared statements (Drizzle handles automatically)
- ✅ Validate user input (Zod schemas)
- ✅ Sanitize code submissions (blocked:
<script>,<style>, etc.) - ✅ Rate limiting to prevent spam
- ❌ Don't expose database credentials in client code
- ❌ Don't log sensitive data
- ❌ Don't commit
.envfiles
AGENTS.md- Development guide for agents and developersDATABASE.md- Database setup and configurationspecs/DEPLOYMENT.md- Production deployment guide ✅specs/CODE_SUBMISSION_IMPLEMENTATION.md- Implementation specificationsTESTING.md- Testing guide and examples
docker-compose.yml- Docker configurationtailwind.config.js- Tailwind configurationtsconfig.json- TypeScript configuration
- Check the Troubleshooting section
- Review relevant documentation (AGENTS.md, DATABASE.md)
- Check existing GitHub issues
- Open a new issue with:
- Clear description of the problem
- Steps to reproduce
- Expected vs actual behavior
- Environment info (Node version, OS, etc.)
Report issues at: https://github.com/anomalyco/opencode
Include:
- Error messages and stack traces
- Environment variables (sanitized)
- Database logs if applicable
- Browser console errors if frontend issue
See LICENSE file for details.
Last Updated: April 7, 2026
Made with ❤️ for developers who appreciate honest feedback.