๐ฏ Introduction
In this article, I'll walk you through the architecture and implementation of a complete, production-ready AI chatbot platform that I've built from scratch. This isn't just another chatbot tutorialโit's a comprehensive system featuring OAuth 2.0 authentication, real-time WebSocket communication, OpenAI integration, and a full-featured analytics dashboard.
What makes this project special?
- ๐๏ธ Microservices Architecture: Four independent services working together seamlessly
- ๐ Enterprise-Grade Security: OAuth 2.0 with JWT tokens and role-based access control
- ๐ฌ Real-Time Communication: WebSocket support for instant messaging
- ๐ Integrated Analytics: Live metrics and user activity tracking
- ๐ Production Ready: Docker deployment, comprehensive testing, and cross-platform support
- ๐จ Modern UI: Beautiful React interface with gradient themes and responsive design
Tech Stack:
- Frontend: React 18, React Router, WebSocket API
- Backend: FastAPI (Python 3.12+), SQLAlchemy, JWT
- AI: OpenAI GPT-4
- Database: SQLite (easily upgradeable to PostgreSQL)
- Deployment: Docker, Docker Compose
- Testing: Pytest, end-to-end test suite
๐๏ธ System Architecture
The platform consists of four microservices:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ React Frontend (Port 3000) โ
โ Chat Interface + Analytics Panel + Real-time Updates โ
โโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโ
โ Auth Service โ โ Chat Service โ โAnalytics Service โ
โ (Port 8001) โ โ (Port 8000) โ โ (Port 8002) โ
โ โ โ โ โ โ
โ โข User Mgmt โ โ โข Conversations โ โ โข Metrics โ
โ โข JWT Tokens โโโโค โข OpenAI API โโโบโ โข User Activity โ
โ โข RBAC โ โ โข WebSocket โ โ โข Token Tracking โ
โ โข Auto Admin โ โ โข Analytics MW โ โ โข Admin API โ
โโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโ
Why Microservices?
- Separation of Concerns: Each service has a single, well-defined responsibility
- Scalability: Scale services independently based on load
- Maintainability: Easier to understand, test, and modify individual components
- Technology Flexibility: Each service can use different technologies if needed
- Fault Isolation: If one service fails, others continue functioning
๐ Authentication & Authorization
OAuth 2.0 Implementation
The auth service implements OAuth 2.0 with JWT tokens:
# auth-service/auth_server/security/auth.py
from jose import JWTError, jwt
from datetime import datetime, timedelta, timezone
from passlib.context import CryptContext
SECRET_KEY = os.getenv("AUTH_SECRET_KEY")
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 43200 # 30 days
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
def create_access_token(data: dict):
to_encode = data.copy()
expire = datetime.now(timezone.utc) + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
to_encode.update({"exp": expire})
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
return encoded_jwt
def verify_password(plain_password: str, hashed_password: str) -> bool:
return pwd_context.verify(plain_password, hashed_password)
def get_password_hash(password: str) -> str:
return pwd_context.hash(password)
Key Features:
- BCrypt Password Hashing: Secure password storage with automatic salting
- JWT Tokens: Stateless authentication with 30-day expiration
- Role-Based Access Control: Admin, User, Manager roles
- Timezone-Aware: UTC timestamps for global compatibility
Automatic Admin Setup
One of my favorite featuresโthe system automatically creates an admin user on first startup:
# auth-service/auth_server/main.py
@app.on_event("startup")
async def startup_event():
"""Initialize database and create admin user if not exists"""
create_db_and_tables()
# Auto-create admin user
admin_username = os.getenv("ADMIN_USERNAME", "admin")
admin_password = os.getenv("ADMIN_PASSWORD", "admin123")
admin_email = os.getenv("ADMIN_EMAIL", "admin@example.com")
with Session(engine) as session:
admin_user = session.exec(
select(User).where(User.username == admin_username)
).first()
if not admin_user:
# Create admin with both admin and user roles
admin_user = User(
username=admin_username,
email=admin_email,
hashed_password=get_password_hash(admin_password)
)
session.add(admin_user)
session.commit()
session.refresh(admin_user)
# Assign roles
admin_role = session.exec(select(Role).where(Role.name == "admin")).first()
user_role = session.exec(select(Role).where(Role.name == "user")).first()
admin_user.roles.extend([admin_role, user_role])
session.commit()
print(f"โ
Admin user '{admin_username}' created successfully!")
No more manual SQL commands or bootstrap scripts! The admin user is ready to use immediately after deployment.
๐ฌ Real-Time Chat with WebSocket
WebSocket Connection Handler
The chat service uses WebSocket for real-time bidirectional communication:
# openai_web_service/websocket/chat_handler.py
@router.websocket("/ws/{conversation_id}")
async def websocket_endpoint(
websocket: WebSocket,
conversation_id: str,
token: str = Query(None),
db: Session = Depends(get_db)
):
await websocket.accept()
try:
# Authenticate user from JWT token
user_data = verify_access_token(token)
user_id = user_data.get("user_id")
# Verify conversation ownership
conversation = get_conversation_by_id(db, conversation_id, user_id)
if not conversation:
await websocket.send_json({
"type": "error",
"message": "Conversation not found or access denied"
})
await websocket.close()
return
# Handle messages
while True:
data = await websocket.receive_json()
if data.get("type") == "message":
# Save user message
user_message = create_message(
db, conversation_id, "user", data.get("content"), user_id
)
# Get AI response from OpenAI
ai_response = await get_openai_response(
db, conversation_id, user_message.content
)
# Save AI message
ai_message = create_message(
db, conversation_id, "assistant", ai_response, user_id
)
# Send to client
await websocket.send_json({
"type": "message",
"role": "assistant",
"content": ai_response,
"message_id": ai_message.id,
"timestamp": ai_message.timestamp.isoformat()
})
except WebSocketDisconnect:
print(f"Client disconnected from conversation {conversation_id}")
except Exception as e:
await websocket.send_json({
"type": "error",
"message": str(e)
})
await websocket.close()
Key Features:
- Token Authentication: Secure WebSocket connections with JWT
- Conversation Ownership: Users can only access their own conversations
- Auto-reconnection: Client automatically reconnects on disconnect (max 5 attempts)
- Error Handling: Graceful error messages and cleanup
OpenAI Integration
The service integrates with OpenAI's GPT-4 API:
# openai_web_service/services/openai_service.py
async def get_openai_response(db: Session, conversation_id: str, user_message: str) -> str:
"""Get response from OpenAI API with conversation context"""
# Get conversation history
messages = get_messages_by_conversation(db, conversation_id)
# Build context
conversation_history = [
{"role": msg.role, "content": msg.content}
for msg in messages[-10:] # Last 10 messages for context
]
# Add system message
conversation_history.insert(0, {
"role": "system",
"content": "You are a helpful AI assistant."
})
# Call OpenAI API
response = await openai.ChatCompletion.acreate(
model="gpt-4",
messages=conversation_history,
temperature=0.7,
max_tokens=500
)
return response.choices[0].message.content
Context Management: The system maintains conversation context by including the last 10 messages in each API call, ensuring coherent multi-turn conversations.
๐ Analytics Dashboard
Real-Time Metrics Tracking
The analytics service tracks comprehensive metrics:
# analytics-service/analytics/services/analytics_service.py
class AnalyticsService:
def get_summary_metrics(self, db: Session) -> dict:
"""Get overall platform statistics"""
now = datetime.now(timezone.utc)
today_start = now.replace(hour=0, minute=0, second=0, microsecond=0)
return {
"total_users": db.query(UserActivity).distinct(UserActivity.user_id).count(),
"active_users_today": db.query(UserActivity)
.filter(UserActivity.timestamp >= today_start)
.distinct(UserActivity.user_id)
.count(),
"total_conversations": db.query(ConversationMetrics).count(),
"total_messages": db.query(MessageMetrics).count(),
"total_tokens_used": db.query(func.sum(MessageMetrics.total_tokens)).scalar() or 0,
"avg_response_time": db.query(func.avg(ApiUsage.response_time))
.filter(ApiUsage.timestamp >= today_start)
.scalar() or 0,
"error_rate": self._calculate_error_rate(db, today_start)
}
Analytics Middleware
Automatic API usage tracking without cluttering application code:
# openai_web_service/middleware/analytics_middleware.py
@app.middleware("http")
async def analytics_tracking_middleware(request: Request, call_next):
"""Track all API requests for analytics"""
start_time = time.time()
# Process request
response = await call_next(request)
# Calculate response time
response_time = time.time() - start_time
# Extract user info from JWT token
user_id = None
if authorization := request.headers.get("authorization"):
try:
token = authorization.split("Bearer ")[1]
user_data = verify_access_token(token)
user_id = user_data.get("user_id")
except:
pass
# Send to analytics service (fire-and-forget)
asyncio.create_task(
send_analytics_event({
"event_type": "api_request",
"user_id": user_id,
"endpoint": str(request.url.path),
"method": request.method,
"status_code": response.status_code,
"response_time": response_time,
"timestamp": datetime.now(timezone.utc).isoformat()
})
)
return response
Fire-and-forget approach: Analytics tracking is non-blocking and doesn't impact API performance.
Frontend Analytics Panel
React component displaying live metrics:
// chat-frontend/src/components/AnalyticsPanel.js
function AnalyticsPanel({ isOpen, onClose }) {
const [metrics, setMetrics] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
const fetchMetrics = async () => {
try {
const data = await analyticsService.getSummary();
setMetrics(data);
} catch (error) {
console.error('Failed to fetch analytics:', error);
} finally {
setLoading(false);
}
};
fetchMetrics();
const interval = setInterval(fetchMetrics, 30000); // Refresh every 30s
return () => clearInterval(interval);
}, []);
return (
<div className={`analytics-panel ${isOpen ? 'open' : ''}`}>
<div className="analytics-header">
<h2>๐ Analytics Dashboard</h2>
<button onClick={onClose}>โ</button>
</div>
{loading ? (
<Spinner />
) : (
<div className="metrics-grid">
<MetricCard
icon="๐ฅ"
title="Total Users"
value={metrics.total_users}
color="#4a90e2"
/>
<MetricCard
icon="๐ฅ"
title="Active Today"
value={metrics.active_users_today}
color="#f5a623"
/>
<MetricCard
icon="๐ฌ"
title="Conversations"
value={metrics.total_conversations}
color="#7ed321"
/>
<MetricCard
icon="๐จ"
title="Messages"
value={metrics.total_messages}
color="#bd10e0"
/>
<MetricCard
icon="๐ฏ"
title="Tokens Used"
value={metrics.total_tokens_used.toLocaleString()}
color="#ff6b6b"
/>
<MetricCard
icon="โก"
title="Avg Response"
value={`${(metrics.avg_response_time * 1000).toFixed(0)}ms`}
color="#4ecdc4"
/>
</div>
)}
</div>
);
}
Auto-refresh: Metrics update every 30 seconds without user interaction.
๐ณ Docker Deployment
Docker Compose Configuration
Complete stack deployment with one command:
# docker-compose.yml
version: '3.8'
services:
auth-service:
build: ./auth-service
ports:
- "8001:8001"
environment:
- AUTH_SECRET_KEY=${AUTH_SECRET_KEY}
- ADMIN_USERNAME=admin
- ADMIN_PASSWORD=admin123
- ADMIN_EMAIL=admin@example.com
networks:
- chatbot-network
openai_web_service:
build: ./openai_web_service
ports:
- "8000:8000"
environment:
- OPENAI_API_KEY=${OPENAI_API_KEY}
- AUTH_SECRET_KEY=${AUTH_SECRET_KEY}
- AUTH_SERVICE_URL=http://auth-service:8001
- ANALYTICS_SERVICE_URL=http://analytics-service:8002
depends_on:
- auth-service
- analytics-service
networks:
- chatbot-network
analytics-service:
build: ./analytics-service
ports:
- "8002:8002"
environment:
- AUTH_SECRET_KEY=${AUTH_SECRET_KEY}
- AUTH_SERVICE_URL=http://auth-service:8001
depends_on:
- auth-service
networks:
- chatbot-network
chat-frontend:
build: ./chat-frontend
ports:
- "3000:3000"
environment:
- REACT_APP_AUTH_API_URL=http://localhost:8001
- REACT_APP_CHAT_API_URL=http://localhost:8000
- REACT_APP_ANALYTICS_API_URL=http://localhost:8002
- REACT_APP_WS_URL=ws://localhost:8000
depends_on:
- auth-service
- openai_web_service
- analytics-service
networks:
- chatbot-network
networks:
chatbot-network:
driver: bridge
Deploy with one command:
docker-compose up --build
๐ Cross-Platform Local Development
Platform-Specific Scripts
I created comprehensive script suites for Windows, macOS, and Linux:
Windows (scripts/windows/):
:: start-all-services.bat
@echo off
cd /d %~dp0..\..
:: Start auth service
start "Auth Service" cmd /k "cd auth-service && venv\Scripts\activate && uvicorn auth_server.main:app --reload --port 8001"
:: Start chat service
start "Chat Service" cmd /k "cd openai_web_service && venv\Scripts\activate && uvicorn main:app --reload --port 8000"
:: Start analytics service
start "Analytics Service" cmd /k "cd analytics-service && venv\Scripts\activate && uvicorn main:app --reload --port 8002"
:: Start frontend
start "Frontend" cmd /k "cd chat-frontend && npm start"
echo All services started!
Linux/Mac (scripts/linux-mac/):
#!/bin/bash
# start-all-services.sh
PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
# Detect terminal emulator
if [[ "$OSTYPE" == "darwin"* ]]; then
TERMINAL="Terminal"
else
TERMINAL="gnome-terminal"
fi
# Start auth service
$TERMINAL -- bash -c "cd $PROJECT_ROOT/auth-service && source venv/bin/activate && uvicorn auth_server.main:app --reload --port 8001; exec bash"
# Start chat service
$TERMINAL -- bash -c "cd $PROJECT_ROOT/openai_web_service && source venv/bin/activate && uvicorn main:app --reload --port 8000; exec bash"
# Start analytics service
$TERMINAL -- bash -c "cd $PROJECT_ROOT/analytics-service && source venv/bin/activate && uvicorn main:app --reload --port 8002; exec bash"
# Start frontend
$TERMINAL -- bash -c "cd $PROJECT_ROOT/chat-frontend && npm start; exec bash"
echo "All services started!"
One-command setup:
# Windows
scripts\windows\setup-venv.bat
scripts\windows\start-all-services.bat
# Linux/Mac
scripts/linux-mac/setup-venv.sh
scripts/linux-mac/start-all-services.sh
๐งช Comprehensive Testing
End-to-End Test Suite
Over 50 test cases covering all functionality:
# tests/test_4_end_to_end.py
import pytest
from datetime import datetime, timezone
class TestEndToEndFlow:
"""Complete user journey tests"""
def test_complete_user_journey_rest_api(self):
"""Test complete user flow using REST API"""
# 1. Register user
register_data = {
"username": f"user_{int(datetime.now(timezone.utc).timestamp())}",
"email": f"user_{int(datetime.now(timezone.utc).timestamp())}@test.com",
"password": "testpass123",
"full_name": "Test User"
}
register_response = requests.post(
f"{AUTH_BASE_URL}/users/",
json=register_data
)
assert register_response.status_code == 200
# 2. Login
login_data = {
"username": register_data["username"],
"password": register_data["password"]
}
token_response = requests.post(
f"{AUTH_BASE_URL}/auth/token",
data=login_data
)
assert token_response.status_code == 200
token = token_response.json()["access_token"]
headers = {"Authorization": f"Bearer {token}"}
# 3. Create conversation
conv_response = requests.post(
f"{CHAT_BASE_URL}/conversations/",
json={"title": "Test Conversation"},
headers=headers
)
assert conv_response.status_code == 200
conversation_id = conv_response.json()["id"]
# 4. Send message
message_response = requests.post(
f"{CHAT_BASE_URL}/conversations/{conversation_id}/messages",
json={
"conversation_id": conversation_id,
"role": "user",
"content": "Hello, AI!"
},
headers=headers
)
assert message_response.status_code == 200
# 5. Get message history
history_response = requests.get(
f"{CHAT_BASE_URL}/conversations/{conversation_id}/messages",
headers=headers
)
assert history_response.status_code == 200
assert len(history_response.json()) >= 2 # User + AI response
# 6. Delete conversation
delete_response = requests.delete(
f"{CHAT_BASE_URL}/conversations/{conversation_id}",
headers=headers
)
assert delete_response.status_code == 200
def test_websocket_real_time_messaging(self):
"""Test WebSocket real-time communication"""
# Register and login
token = self.get_test_token()
# Connect WebSocket
ws_url = f"{WS_BASE_URL}/ws/test-conversation?token={token}"
ws = websocket.create_connection(ws_url)
# Send message
ws.send(json.dumps({
"type": "message",
"content": "Test WebSocket message"
}))
# Receive AI response
response = json.loads(ws.recv())
assert response["type"] == "message"
assert response["role"] == "assistant"
assert len(response["content"]) > 0
ws.close()
Run tests:
pytest tests/ -v --cov=. --cov-report=html
๐จ UI/UX Highlights
Responsive Design
The frontend adapts seamlessly to all screen sizes:
/* chat-frontend/src/components/ChatPage.css */
.chat-page {
display: flex;
height: 100vh;
}
.sidebar {
width: 300px;
min-width: 300px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
.main-content {
flex: 1;
display: flex;
flex-direction: column;
}
/* Mobile responsive */
@media (max-width: 768px) {
.sidebar {
position: fixed;
left: -300px;
transition: left 0.3s ease;
z-index: 1000;
}
.sidebar.open {
left: 0;
}
.analytics-panel {
width: 100% !important;
}
}
Gradient Themes
Beautiful gradient color schemes throughout:
/* Conversation list gradients */
.conversation-item {
background: linear-gradient(135deg, rgba(255,255,255,0.1) 0%, rgba(255,255,255,0.05) 100%);
backdrop-filter: blur(10px);
border: 1px solid rgba(255,255,255,0.2);
}
/* Message bubbles */
.user-message {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
}
.ai-message {
background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
color: white;
}
/* Analytics metrics */
.metric-card {
background: linear-gradient(135deg, rgba(255,255,255,0.1) 0%, rgba(255,255,255,0.05) 100%);
backdrop-filter: blur(10px);
box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.37);
}
๐ง Configuration Management
3-Tier Environment System
Root .env (shared secrets):
AUTH_SECRET_KEY=your-super-secret-key-here
OPENAI_API_KEY=sk-your-openai-api-key
Service .env files (service-specific):
# auth-service/.env
PORT=8001
HOST=0.0.0.0
CORS_ORIGINS=http://localhost:3000
ADMIN_USERNAME=admin
ADMIN_PASSWORD=admin123
ADMIN_EMAIL=admin@example.com
# openai_web_service/.env
PORT=8000
HOST=0.0.0.0
AUTH_SERVICE_URL=http://localhost:8001
ANALYTICS_SERVICE_URL=http://localhost:8002
CORS_ORIGINS=http://localhost:3000
# analytics-service/.env
PORT=8002
HOST=0.0.0.0
AUTH_SERVICE_URL=http://localhost:8001
CORS_ORIGINS=http://localhost:3000
Frontend .env:
REACT_APP_AUTH_API_URL=http://localhost:8001
REACT_APP_CHAT_API_URL=http://localhost:8000
REACT_APP_ANALYTICS_API_URL=http://localhost:8002
REACT_APP_WS_URL=ws://localhost:8000
๐ Performance Optimizations
Database Optimization
Absolute Paths: Databases use absolute paths to prevent multiple database files:
# openai_web_service/engine/database.py
from pathlib import Path
# Get service directory
service_dir = Path(__file__).parent.parent
# Create data directory
data_dir = service_dir / "data"
data_dir.mkdir(parents=True, exist_ok=True)
# Database path
db_path = data_dir / "chatbot.db"
DATABASE_URL = f"sqlite:///{db_path}"
Caching Strategy
Static Asset Caching in Nginx configuration:
# chat-frontend/nginx.conf
server {
listen 3000;
location / {
root /usr/share/nginx/html;
index index.html;
try_files $uri $uri/ /index.html;
}
# Cache static assets
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
}
WebSocket Connection Pooling
Efficient connection management:
// chat-frontend/src/hooks/useChat.js
const [ws, setWs] = useState(null);
const reconnectAttemptsRef = useRef(0);
const maxReconnectAttempts = 5;
const connect = useCallback(() => {
if (ws?.readyState === WebSocket.OPEN) {
ws.close();
}
const token = localStorage.getItem('token');
const websocket = new WebSocket(
`${WS_URL}/ws/${conversationId}?token=${token}`
);
websocket.onopen = () => {
console.log('WebSocket connected');
reconnectAttemptsRef.current = 0;
};
websocket.onclose = () => {
if (reconnectAttemptsRef.current < maxReconnectAttempts) {
setTimeout(() => {
reconnectAttemptsRef.current++;
connect();
}, 2000 * reconnectAttemptsRef.current);
}
};
setWs(websocket);
}, [conversationId]);
๐ก๏ธ Security Best Practices
1. Password Security
- BCrypt hashing with automatic salting
- Minimum password complexity requirements
- Password updates require current password
2. JWT Token Security
- HS256 algorithm
- 30-day expiration (configurable)
- Token refresh mechanism
- Secure storage in localStorage (HTTPS only in production)
3. CORS Configuration
- Whitelist specific origins
- No wildcard (*) in production
- Credentials support enabled
4. SQL Injection Prevention
- SQLAlchemy ORM (parameterized queries)
- Input validation with Pydantic schemas
- No raw SQL queries
5. XSS Protection
- React's built-in XSS protection
- Content Security Policy headers
- Sanitized user inputs
6. Rate Limiting (Future Enhancement)
# Future implementation
from slowapi import Limiter
from slowapi.util import get_remote_address
limiter = Limiter(key_func=get_remote_address)
@app.get("/api/endpoint")
@limiter.limit("5/minute")
async def endpoint():
pass
๐ Monitoring & Observability
Health Check Endpoints
All services expose health checks:
@app.get("/health")
async def health_check():
return {
"status": "healthy",
"service": "auth-service",
"version": "1.1.0",
"timestamp": datetime.now(timezone.utc).isoformat()
}
Logging Configuration
Structured logging with levels:
import logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('app.log'),
logging.StreamHandler()
]
)
logger = logging.getLogger(__name__)
Metrics Collection
Analytics service tracks:
- API response times
- Error rates
- Token usage
- User activity
- Conversation metrics
๐ข Deployment Strategies
Docker Production Deployment
# Build images
docker-compose build
# Deploy in detached mode
docker-compose up -d
# View logs
docker-compose logs -f
# Scale services
docker-compose up -d --scale openai_web_service=3
Environment-Specific Configurations
# docker-compose.prod.yml
services:
openai_web_service:
environment:
- ENVIRONMENT=production
- DEBUG=false
- LOG_LEVEL=WARNING
deploy:
replicas: 3
resources:
limits:
cpus: '0.50'
memory: 512M
CI/CD Pipeline (Example)
# .github/workflows/deploy.yml
name: Deploy
on:
push:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Run tests
run: |
pip install -r requirements.txt
pytest tests/ -v
deploy:
needs: test
runs-on: ubuntu-latest
steps:
- name: Deploy to production
run: |
docker-compose -f docker-compose.prod.yml up -d --build
๐ Lessons Learned
1. Start with Microservices from Day One
Breaking the system into services early made scaling and maintenance much easier. Each service can be deployed, tested, and scaled independently.
2. Invest in Developer Experience
Creating platform-specific scripts saved countless hours. One-command setup and deployment significantly lowered the barrier to entry for new contributors.
3. Security is Not Optional
Implementing OAuth 2.0, RBAC, and proper password hashing from the beginning prevented major refactoring later. Security should be baked in, not bolted on.
4. Real-Time Features Require Careful Planning
WebSocket implementation required thinking about connection management, reconnection logic, and error handling upfront. The fire-and-forget analytics tracking pattern kept the main application performant.
5. Documentation is Code
Comprehensive READMEs and setup guides made onboarding new developers seamless. The time invested in documentation paid dividends in reduced support questions.
6. Test Everything
The end-to-end test suite caught numerous edge cases and integration issues. Having 50+ tests gave confidence to refactor and add features.
๐ฎ Future Enhancements
Short-Term (Next 3 Months)
- [ ] PostgreSQL migration for production
- [ ] Redis for session management and caching
- [ ] Rate limiting on API endpoints
- [ ] Conversation search functionality
- [ ] Message editing and deletion
- [ ] File upload support
- [ ] Voice input/output
Medium-Term (3-6 Months)
- [ ] Multi-model support (GPT-4, Claude, Gemini)
- [ ] Conversation sharing and collaboration
- [ ] Custom AI assistant personas
- [ ] API key management for users
- [ ] Advanced analytics (charts, graphs, exports)
- [ ] Mobile app (React Native)
- [ ] Email notifications
Long-Term (6-12 Months)
- [ ] Multi-tenancy support
- [ ] Plugin system for extensions
- [ ] Kubernetes deployment
- [ ] GraphQL API
- [ ] Real-time collaboration features
- [ ] Advanced AI features (RAG, function calling)
- [ ] Marketplace for custom assistants
๐ Key Takeaways
If you're building a similar system, here are my recommendations:
Architecture: Start with a clear separation of concerns. Microservices may seem overkill initially, but they pay off quickly.
Security: Don't compromise on security. OAuth 2.0, JWT, RBAC, and proper password hashing are table stakes.
Real-Time: WebSocket adds complexity but provides a superior user experience. Plan for connection management and error recovery.
Testing: Write tests as you go. End-to-end tests are especially valuable for catching integration issues.
Documentation: Document everything. Future you (and your team) will thank you.
Developer Experience: Invest in tooling and scripts. One-command setup and deployment are worth the effort.
Observability: Build in logging, metrics, and health checks from day one. You can't debug what you can't see.
๐ฆ Project Repository
GitHub: github.com/vcse59/ConvoAI
Quick Start
# Clone repository
git clone https://github.com/vcse59/ConvoAI.git
cd ConvoAI
# Create .env file
echo "AUTH_SECRET_KEY=your-secret-key" > .env
echo "OPENAI_API_KEY=sk-your-key" >> .env
# Docker deployment
docker-compose up --build
# Or local development (Windows)
scripts\windows\setup-venv.bat
scripts\windows\start-all-services.bat
# Or local development (Linux/Mac)
scripts/linux-mac/setup-venv.sh
scripts/linux-mac/start-all-services.sh
# Access at http://localhost:3000
Project Stats
- Lines of Code: ~15,000+
- Services: 4 (Frontend, Auth, Chat, Analytics)
- Test Coverage: 80%+
- Documentation: 6,000+ lines
- Scripts: 22 platform-specific automation scripts
๐ค Contributing
Contributions are welcome! Areas where help is needed:
- Additional language models integration
- Mobile app development
- Performance optimizations
- UI/UX improvements
- Documentation translations
- Additional test coverage
๐ License
MIT License - See LICENSE file for details.
๐ Acknowledgments
- FastAPI: Amazing Python web framework
- React: Excellent frontend library
- OpenAI: GPT-4 API for AI responses
- SQLAlchemy: Powerful ORM
- Docker: Simplified deployment
๐ Contact
- GitHub: @vcse59
- Email: v.cse59@gmail.com
- LinkedIn: Connect with me
Built with โค๏ธ using React, FastAPI, and OpenAI
If you found this article helpful, please give it a โค๏ธ and follow for more content on full-stack development, AI integration, and microservices architecture!
๐ก Questions?
Drop your questions in the comments below! I'm happy to discuss:
- Architecture decisions and tradeoffs
- Implementation details
- Deployment strategies
- Scaling considerations
- Security best practices
- Testing approaches
Let's build amazing things together! ๐
Top comments (0)