A fully functional Google Meet clone with real-time video/audio calling, WebRTC peer-to-peer connections, chat messaging, and screen sharing capabilities.
βββββββββββββββββββ ββββββββββββββββββββ βββββββββββββββββββ
β β β β β β
β Next.js ββββββββββΊβ Go Backend ββββββββββΊβ PostgreSQL β
β Frontend β HTTP β (Fiber + WS) β GORM β Database β
β (TypeScript) β WebSocket β β β
β β β β β β
βββββββββββββββββββ ββββββββββββββββββββ βββββββββββββββββββ
β β
β β
βββββββββWebRTC P2Pβββββββββββ
(STUN/TURN)
- β User Authentication: JWT-based auth with bcrypt password hashing
- β Meeting Rooms: Create and join persistent meeting rooms with UUID identifiers
- β Real-time Video/Audio: WebRTC peer-to-peer connections (mesh topology for β€6 participants)
- β WebSocket Signaling: Reliable signaling server with rate limiting
- β Text Chat: Real-time chat with message persistence
- β
Screen Sharing: Browser-native screen sharing via
getDisplayMedia - β Participant Management: Real-time participant list with join/leave events
- β Media Controls: Mute/unmute audio, enable/disable video
- β Health & Metrics: Prometheus-compatible metrics endpoint
- β Docker Deployment: Full docker-compose setup for local development
- Docker and Docker Compose
- (Optional) Node.js 20+ and Go 1.21+ for local development
-
Clone the repository
git clone <repository-url> cd test-project
-
Set up environment variables
cp .env.example .env # Edit .env and set JWT_SECRET to a secure random string (min 32 characters) -
Start all services
docker-compose up --build
-
Access the application
- Frontend: http://localhost:3000
- Backend API: http://localhost:8080
- Health check: http://localhost:8080/healthz
- Metrics: http://localhost:8080/metrics
-
Create demo users (optional)
cd backend make seed # Creates user1@example.com and user2@example.com (password: password123)
/
βββ backend/ # Go backend
β βββ cmd/server/ # Main entry point
β βββ internal/
β β βββ api/ # REST API handlers
β β βββ auth/ # JWT & password hashing
β β βββ config/ # Configuration management
β β βββ db/ # GORM models & database
β β βββ signal/ # WebSocket signaling
β β βββ metrics/ # Prometheus metrics
β βββ migrations/ # SQL migrations
β βββ docs/ # OpenAPI specification
β βββ Dockerfile
β βββ Makefile
β βββ go.mod
βββ frontend/ # Next.js frontend
β βββ src/
β β βββ app/ # Next.js app router pages
β β βββ components/ # React components
β β βββ contexts/ # React contexts (Auth)
β β βββ hooks/ # Custom hooks (WebRTC)
β β βββ lib/ # API client
β βββ Dockerfile
β βββ package.json
βββ docker-compose.yml # Docker Compose configuration
βββ .gitlab-ci.yml # GitLab CI/CD pipeline
βββ README.md
cd backend
# Install dependencies
go mod download
# Set environment variables
export DATABASE_URL="postgres://postgres:postgres@localhost:5432/meet?sslmode=disable"
export JWT_SECRET="your-secret-key-min-32-characters"
export PORT=8080
# Run migrations (requires PostgreSQL running)
make migrate
# Start development server
make dev
# Run tests
make test
# Run linter
make lintcd frontend
# Install dependencies
npm install
# Create .env.local file
cat > .env.local << EOF
NEXT_PUBLIC_API_URL=http://localhost:8080
NEXT_PUBLIC_WS_URL=ws://localhost:8080/ws
NEXT_PUBLIC_STUN=stun:stun.l.google.com:19302
EOF
# Start development server
npm run dev
# Run linter
npm run lintcd backend
go test -v -cover ./...Tests include:
- JWT token generation and validation
- Password hashing with bcrypt
- Rate limiter functionality
- (More integration tests can be added)
cd frontend
# Unit tests (to be implemented)
npm test
# E2E tests with Playwright (to be implemented)
npm run test:e2eOpenAPI specification is available at /backend/docs/openapi.yaml.
Authentication
POST /api/v1/auth/register- Register new userPOST /api/v1/auth/login- Login and get JWT tokenGET /api/v1/user/me- Get current user profile (protected)
Rooms
POST /api/v1/rooms- Create a new room (protected)GET /api/v1/rooms/:id- Get room metadataGET /api/v1/rooms/:id/participants- List room participants
WebSocket
GET /ws?room={roomId}&token={jwt}- WebSocket endpoint for signaling
System
GET /healthz- Health checkGET /metrics- Prometheus metrics
- β JWT tokens with 15-minute expiration
- β bcrypt password hashing (cost 12)
- β CORS configured for frontend origin
- β Rate limiting on WebSocket messages (50 burst, 10/sec sustained)
- β HTML sanitization for chat messages (XSS prevention)
- β SQL injection protection via GORM parameterized queries
Warning
Do NOT use in production without these changes:
- HTTPS/TLS: Deploy behind a reverse proxy (nginx/Caddy) with TLS certificates
- JWT Secret: Use a cryptographically secure random string (min 64 characters)
- Secret Management: Store secrets in a secret manager (AWS Secrets Manager, HashiCorp Vault)
- TURN Server: Deploy coturn for reliable NAT traversal
- Database: Use managed PostgreSQL with backups and replication
- Rate Limiting: Add API rate limiting per IP address
- HSTS: Enable HTTP Strict Transport Security headers
- CSP: Configure Content Security Policy headers
- Monitoring: Set up logging aggregation and alerting
By default, uses Google's public STUN server: stun:stun.l.google.com:19302
For production deployments behind restrictive NATs/firewalls, deploy a TURN server:
# Using coturn with docker-compose (uncomment in docker-compose.yml)
docker-compose up coturn
# Configure environment variables
TURN_URL=turn:your-turn-server.com:3478
TURN_USER=username
TURN_PASS=passwordImportant
Current mesh topology supports β€6 participants
For larger meetings (>6 participants), use an SFU (Selective Forwarding Unit):
Problem: Video/audio not connecting between participants
Solutions:
- Check browser console for ICE connection errors
- Verify STUN server is reachable:
stun:stun.l.google.com:19302 - If behind corporate firewall, configure TURN server
- Ensure WebSocket connection is established (check Network tab)
- Grant browser permissions for camera/microphone
Problem: Backend fails to connect to PostgreSQL
Solutions:
- Verify PostgreSQL is running:
docker-compose ps - Check DATABASE_URL environment variable
- Ensure database migrations ran successfully
- Check logs:
docker-compose logs backend
Problem: Port 3000 or 8080 already in use
Solutions:
- Stop conflicting services
- Modify ports in
docker-compose.yml - Update frontend environment variables accordingly
Available at http://localhost:8080/metrics:
meet_active_rooms- Number of active meeting roomsmeet_total_connections- Total WebSocket connectionsmeet_messages_sent_total- Total messages sent
curl http://localhost:8080/healthz
# Response: {"status":"ok"}- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is for educational purposes.
- Inspired by Google Meet
- Built with Go Fiber, Next.js, and WebRTC
- Uses GORM for database operations
- Gorilla WebSocket for signaling
Made with β€οΈ for learning WebRTC and real-time communications