A production-ready, scalable AI-driven mock interview platform built with Next.js, Prisma, and Supabase.
- ✅ AI-Powered Mock Interviews - Practice with AI-generated questions and feedback
- ✅ Code Editor - Monaco editor with syntax highlighting and test execution
- ✅ Progress Tracking - Detailed analytics and performance metrics
- ✅ Question Bank - 1000+ curated DSA, coding, and HR questions
- ✅ Secure Authentication - JWT with refresh tokens, password hashing
- ✅ Rate Limiting - Per-IP and per-user rate limits
- ✅ Notification System - In-app and email notifications with preferences
- ✅ Media Storage - Supabase storage with signed URLs
- ✅ Error Handling - User-friendly error messages
- ✅ Loading States - Beautiful skeleton loaders
- ✅ Caching - React Query + server-side caching
- ✅ Performance - Debouncing, throttling, code splitting
- Frontend: Next.js 14 (App Router), React, TypeScript, TailwindCSS
- Backend: Next.js API Routes, Server Actions, Prisma ORM
- Database: PostgreSQL (via Prisma)
- Storage: Supabase Storage
- Email: Supabase Email (configurable to Resend/SendGrid)
- Auth: JWT with refresh tokens
- State Management: TanStack Query (React Query)
- Code Editor: Monaco Editor
- Charts: Recharts
- Node.js 18+
- PostgreSQL database
- Supabase account
- Clone the repository
git clone <your-repo-url>
cd Mocky- Install dependencies
npm install- Set up environment variables
cp .env.local.example .env.localFill in your environment variables:
DATABASE_URL=postgresql://user:password@host:port/database
JWT_SECRET=your-secret-key-change-in-production
JWT_REFRESH_SECRET=your-refresh-secret-key
NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
SUPABASE_SERVICE_ROLE_KEY=your-service-role-key
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
OPENROUTER_API_KEY=your-openrouter-key
LLM_MODEL=openai/gpt-4o-mini
NEXT_PUBLIC_APP_URL=http://localhost:3000- Set up database
# Generate Prisma Client
npx prisma generate
# Run migrations
npx prisma migrate dev
# (Optional) Seed database
npx prisma db seed- Set up Supabase Storage
- Create a bucket named
mediain Supabase Storage - Configure bucket settings (private, 10MB max file size)
- Run development server
npm run dev-- BORN on 13-01-2026
-- DIED ON 30-01-2026 🥹😥😑☠️
Mocky/
├── app/ # Next.js app directory
│ ├── actions/ # Server actions
│ ├── api/ # API routes
│ ├── dashboard/ # Dashboard pages
│ ├── mock/ # Mock interview pages
│ └── auth/ # Auth pages
├── components/ # React components
│ ├── ui/ # UI primitives
│ └── skeletons/ # Loading skeletons
├── hooks/ # React Query hooks
├── lib/ # Utilities
│ ├── auth.ts # Auth utilities
│ ├── errors.ts # Error handling
│ ├── rate-limit.ts # Rate limiting
│ └── supabase/ # Supabase helpers
├── services/ # API services
├── types/ # TypeScript types
└── prisma/ # Prisma schema
- JWT Authentication: Access tokens (15min) + Refresh tokens (7 days)
- Password Hashing: bcryptjs with 12 rounds
- Rate Limiting: Per-endpoint rate limits
- Input Validation: Zod schemas for all inputs
- SQL Injection Protection: Prisma ORM
- XSS Protection: React's built-in escaping
- CSRF Protection: SameSite cookies
See prisma/schema.prisma for the complete schema. Key models:
User- User accountsSession- Refresh token sessionsNotification- In-app notificationsNotificationPreference- User notification settingsMockSession- Interview sessionsMockResult- Submission resultsQuestion- Question bankMediaObject- Media file metadata
- Push code to GitHub
- Import project in Vercel
- Add environment variables
- Deploy!
Run migrations in production:
npx prisma migrate deployPOST /api/auth/signup- Sign upPOST /api/auth/signin- Sign inPOST /api/auth/signout- Sign outPOST /api/auth/refresh- Refresh access tokenGET /api/auth/me- Get current user
POST /api/mock/start- Start mock interviewPOST /api/mock/submit- Submit solutionGET /api/mock/[id]- Get session details
GET /api/notifications- Get notificationsPOST /api/notifications/[id]/read- Mark as readPOST /api/notifications/read-all- Mark all as readGET /api/notifications/preferences- Get preferencesPATCH /api/notifications/preferences- Update preferences
POST /api/media/upload-url- Get upload URL
# Run linter
npm run lint
# Type check
npx tsc --noEmitMIT
Contributions are welcome! Please read our contributing guidelines first.
For issues and questions, please open an issue on GitHub.