Full-Stack AI Chat Service built with Go, React, and PostgreSQL in a monorepo architecture.
- 🤖 AI Chat API with multiple providers (OpenAI, Google, Anthropic, Mistral, DeepSeek)
- 🧠 66+ AI models including GPT-4, Claude, Gemini, Mistral, and DeepSeek
- 🔐 JWT Authentication
- 💳 Credit-based usage system
- 🔑 API Key management
- 📊 Chat history tracking
- ⚛️ Modern React with TypeScript
- 🎨 Tailwind CSS for styling
- ⚡ Vite for fast development
- 🔄 Hot module replacement
- 🐳 Docker containerization
- 🔄 Database migrations
- 🧪 Test coverage with CI/CD
- 📦 Monorepo structure with workspaces
# Install all dependencies
npm run install:all
# Start everything in development mode
npm run devThis will start:
- Backend API at
http://localhost:8080 - Frontend at
http://localhost:3000 - PostgreSQL database
# Development with hot reload
docker compose -f docker-compose.dev.yml up -d
# Production build
docker-compose upThe backend seeds a default user on startup (idempotent) so you can log in immediately during development.
-
Default user:
- Email:
admin@clearrouter.local - Name:
Admin - Password:
admin123 - EmailVerified: true
- Email:
-
Environment overrides (set in
docker-compose.dev.ymlunderbackend.environmentor your shell):SEED_DEFAULT_USER_EMAIL– defaultadmin@clearrouter.localSEED_DEFAULT_USER_NAME– defaultAdminSEED_DEFAULT_USER_PASSWORD– defaultadmin123SEED_ENABLE– set tofalseto disable seeding
-
Apply migrations (if needed):
- In dev (container):
docker compose -f docker-compose.dev.yml exec backend dbmate -d /app/db/migrations up - From host (psql/TablePlus): use Postgres URI
postgres://clearrouter:clearrouter_pass@localhost:5432/clearrouter?sslmode=disable
- In dev (container):
Notes:
- Seeding runs after the backend connects to the DB and only creates the user if it does not already exist.
- Do not use these defaults in production.
In development, simulate Razorpay's webhook to credit a user account.
- Webhook endpoint:
POST /credits/add - Header:
X-Razorpay-Signature(HMAC-SHA256 of raw body using your webhook secret) - Helper script:
scripts/gen_razorpay_signature.sh
- Create a payload file (example):
{
"event": "payment.captured",
"payload": {
"payment": { "entity": { "id": "rzp_test_xxx", "amount": 10000, "status": "captured", "order_id": "order_xxx" } },
"order": { "entity": { "id": "order_xxx", "amount": 10000, "notes": { "user_id": "<USER_UUID>" } } }
}
}- Generate signature and call webhook:
# Set your webhook secret (from Razorpay dashboard)
export RAZORPAY_WEBHOOK_SECRET="your_webhook_secret"
# Generate signature (prints hex)
SIG=$(scripts/gen_razorpay_signature.sh --payload payload.json)
# Send webhook (use --data-binary to preserve raw bytes)
curl -sS http://localhost:8080/credits/add \
-H "Content-Type: application/json" \
-H "X-Razorpay-Signature: $SIG" \
--data-binary @payload.json- Verify credits (JWT required):
# Login to get token (example)
curl -s http://localhost:8080/auth/login -H 'Content-Type: application/json' \
--data '{"email":"admin@clearrouter.local","password":"admin123"}'
# Then call credits endpoint with Authorization: Bearer <token>
curl -s http://localhost:8080/credits -H "Authorization: Bearer <JWT>"Notes:
- The signature must be computed on the exact raw bytes sent to the server.
- For another user, replace
<USER_UUID>in the payloadorder.entity.notes.user_idwith that user's UUID. - In production, Razorpay calls this endpoint directly; do not expose your webhook secret.
ClearRouter/
├── apps/
│ ├── backend/ # Go backend application
│ │ ├── cmd/server/ # Application entry point
│ │ ├── internal/ # Private application code
│ │ │ ├── handlers/ # HTTP handlers
│ │ │ ├── middleware/ # HTTP middleware
│ │ │ ├── models/ # Data models
│ │ │ ├── providers/ # AI provider implementations
│ │ │ ├── services/ # Business logic
│ │ │ └── utils/ # Utility functions
│ │ ├── Dockerfile # Development container
│ │ └── Dockerfile.prod # Production container
│ └── frontend/ # React frontend application
│ ├── src/ # Source code
│ ├── public/ # Static assets
│ ├── Dockerfile # Production container
│ ├── Dockerfile.dev # Development container
│ └── nginx.conf # Production nginx config
├── db/ # Database files
│ ├── schema.sql # Database schema
│ └── migrations/ # Database migrations
├── docker-compose.yml # Production compose
├── docker-compose.dev.yml # Development compose
├── package.json # Root workspace config
└── .env # Environment variables
# Install all dependencies
npm run install:all
# Development (both services)
npm run dev
# Development (individual services)
npm run dev:backend
npm run dev:frontend
# Docker development
npm run dev:docker
# Build
npm run build
npm run build:frontend
npm run build:backend
# Clean all build artifacts
npm run cleanPOST /auth/register- Register new userPOST /auth/login- Login user
POST /chat- Send chat messageGET /chat/history- Get chat history
GET /models- List available AI models
GET /credits- Get user creditsPOST /credits/add- Add credits (admin)
GET /apikeys- List user's API keysPOST /apikeys- Create new API keyDELETE /apikeys/:id- Delete API key
- Language: Go 1.23
- Framework: Gin (HTTP router)
- Database: PostgreSQL 15
- ORM: GORM
- Authentication: JWT
- Migration: dbmate
- Framework: React 18 with TypeScript
- Build Tool: Vite
- Styling: Tailwind CSS
- Development: Hot Module Replacement
- Containerization: Docker & Docker Compose
- CI/CD: GitHub Actions
- Development: Air (Go hot reload)
# Backend tests
cd apps/backend && go test ./...
# Frontend tests
cd apps/frontend && npm test
# Run with coverage
cd apps/backend && go test -cover ./...Copy .env.example to .env and configure the following variables:
# Database Configuration
DATABASE_URL=postgres://clearrouter:clearrouter_pass@localhost:5432/clearrouter?sslmode=disable
# Application Configuration
GIN_MODE=debug
GORM_DEBUG=true
JWT_SECRET=your-secret-key
# AI Provider API Keys
OPENAI_API_KEY=your-openai-key # Required for GPT models
GOOGLE_API_KEY=your-google-key # Required for Gemini models
ANTHROPIC_API_KEY=your-anthropic-key # Required for Claude models
DEEPSEEK_API_KEY=your-deepseek-key # Required for DeepSeek models
MISTRAL_API_KEY=your-mistral-key # Required for Mistral/Mixtral models
# Payment Configuration (Razorpay)
RAZORPAY_KEY_ID=your-razorpay-key
RAZORPAY_KEY_SECRET=your-razorpay-secret
RAZORPAY_WEBHOOK_SECRET=your-webhook-secret
# Email Configuration (SMTP)
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=your-email@gmail.com
SMTP_PASS=your-email-app-password
SMTP_FROM_EMAIL=your-email@gmail.com
SMTP_REPLY_TO_EMAIL=your-email@gmail.com
# Frontend
VITE_API_URL=http://localhost:8080- OpenAI: Get your API key from OpenAI Platform
- Google: Create a project in Google Cloud Console and enable Gemini API
- Anthropic: Get your API key from Anthropic Console
- DeepSeek: Sign up at DeepSeek Platform
- Mistral: Get your API key from Mistral AI Platform
# Start with hot reload
npm run dev
# Or with Docker
docker-compose -f docker-compose.dev.yml up# Build and start
docker-compose up -d
# Manual migrations (if needed)
docker-compose exec backend dbmate upGitHub Actions pipeline includes:
- Go testing and linting
- React build and testing
- Docker image building
- Security scanning
- 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
MIT License - see LICENSE file for details.