Build an AI-Powered Code Assistant with Next.js, FastAPI & OpenAI | Full Stack 2026
๐ Build an AI-Powered Code Assistant
Complete guide to building a production-ready AI coding assistant with code generation, explanation, and bug detection features. Full stack with Next.js 14, FastAPI, and OpenAI GPT-4.
Next.js 14
FastAPI
OpenAI GPT-4
PostgreSQL
TypeScript
Tailwind CSS
๐ System Architecture
๐ Data Flow Diagram
Frontend (Next.js) → Backend (FastAPI) → AI Service (OpenAI) → Database (PostgreSQL)
↓ ↓ ↓ ↓
User Interface Authentication & Logic Code Generation Store Conversations
Frontend Features
- Code editor with syntax highlighting
- Real-time AI response streaming
- Session management & history
- Multiple programming language support
- Export code as PDF/ZIP
Backend Features
- JWT authentication
- Rate limiting & API key management
- Conversation persistence
- Code validation & security scanning
- WebSocket for real-time updates
๐ง Backend Implementation (FastAPI)
๐ Backend Directory Structure:
backend/
├── app/
│ ├── api/ # API endpoints
│ ├── core/ # Configuration
│ ├── models/ # Database models
│ ├── schemas/ # Pydantic schemas
│ ├── services/ # Business logic
│ └── main.py # FastAPI app
├── requirements.txt
└── Dockerfile
1. Main Application Setup
# app/main.py
from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from contextlib import asynccontextmanager
import logging
from app.api.routes import code, auth, conversations
from app.core.config import settings
from app.core.database import engine, Base
# Configure logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
@asynccontextmanager
async def lifespan(app: FastAPI):
# Startup
logger.info("Starting up...")
Base.metadata.create_all(bind=engine)
yield
# Shutdown
logger.info("Shutting down...")
app = FastAPI(
title="AI Code Assistant API",
version="1.0.0",
lifespan=lifespan
)
# CORS configuration
app.add_middleware(
CORSMiddleware,
allow_origins=settings.ALLOWED_ORIGINS,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Include routers
app.include_router(auth.router, prefix="/api/auth", tags=["authentication"])
app.include_router(code.router, prefix="/api/code", tags=["code"])
app.include_router(conversations.router, prefix="/api/conversations", tags=["conversations"])
@app.get("/")
async def root():
return {"message": "AI Code Assistant API", "status": "running"}
2. AI Service with OpenAI Integration
# app/services/ai_service.py
import openai
from typing import List, Dict, Any
import asyncio
from app.core.config import settings
from app.schemas.code import CodeRequest, CodeResponse
class AICodeAssistant:
def __init__(self):
openai.api_key = settings.OPENAI_API_KEY
self.system_prompt = """You are an expert coding assistant.
You help with code generation, explanation, debugging, and optimization.
Always provide clean, production-ready code with comments."""
async def generate_code(self, request: CodeRequest) -> CodeResponse:
"""Generate code based on user prompt"""
messages = [
{"role": "system", "content": self.system_prompt},
{"role": "user", "content": f"""
Language: {request.language}
Task: {request.prompt}
Requirements: {request.requirements}
"""}
]
try:
response = await openai.ChatCompletion.acreate(
model="gpt-4",
messages=messages,
temperature=0.7,
max_tokens=2000,
stream=True
)
# Stream response
full_response = ""
async for chunk in response:
if chunk.choices[0].delta.content:
content = chunk.choices[0].delta.content
full_response += content
yield content
return CodeResponse(
code=full_response,
language=request.language,
explanation=self._generate_explanation(full_response)
)
except Exception as e:
raise HTTPException(status_code=500, detail=f"AI service error: {str(e)}")
def _generate_explanation(self, code: str) -> str:
"""Generate explanation for the code"""
# Implementation for code explanation
pass
3. Database Models with SQLAlchemy
# app/models/conversation.py
from sqlalchemy import Column, Integer, String, DateTime, Text, ForeignKey
from sqlalchemy.orm import relationship
from datetime import datetime
from app.core.database import Base
class Conversation(Base):
__tablename__ = "conversations"
id = Column(Integer, primary_key=True, index=True)
user_id = Column(Integer, ForeignKey("users.id"))
title = Column(String(200))
language = Column(String(50))
created_at = Column(DateTime, default=datetime.utcnow)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
# Relationships
user = relationship("User", back_populates="conversations")
messages = relationship("Message", back_populates="conversation", cascade="all, delete-orphan")
class Message(Base):
__tablename__ = "messages"
id = Column(Integer, primary_key=True, index=True)
conversation_id = Column(Integer, ForeignKey("conversations.id"))
role = Column(String(20)) # 'user' or 'assistant'
content = Column(Text)
code_snippet = Column(Text, nullable=True)
tokens_used = Column(Integer, default=0)
created_at = Column(DateTime, default=datetime.utcnow)
conversation = relationship("Conversation", back_populates="messages")
๐จ Frontend Implementation (Next.js 14)
๐ Frontend Directory Structure:
frontend/
├── app/
│ ├── (dashboard)/ # Dashboard pages
│ ├── api/ # API routes
│ ├── components/ # React components
│ └── lib/ # Utilities
├── public/
└── package.json
1. Main Code Editor Component
// app/components/CodeEditor.tsx
'use client';
import { useState, useEffect } from 'react';
import Editor from '@monaco-editor/react';
import { useTheme } from 'next-themes';
import { sendCodeRequest, streamCodeResponse } from '@/lib/api';
import { LanguageSelector } from './LanguageSelector';
import { saveConversation } from '@/lib/db';
interface CodeEditorProps {
initialCode?: string;
language?: string;
conversationId?: string;
}
export default function CodeEditor({
initialCode = '',
language = 'javascript',
conversationId
}: CodeEditorProps) {
const [code, setCode] = useState(initialCode);
const [selectedLanguage, setSelectedLanguage] = useState(language);
const [isLoading, setIsLoading] = useState(false);
const [aiResponse, setAiResponse] = useState('');
const { theme } = useTheme();
const handleSubmit = async (prompt: string) => {
setIsLoading(true);
setAiResponse('');
try {
const response = await streamCodeResponse({
prompt,
language: selectedLanguage,
context: code
}, (chunk) => {
setAiResponse(prev => prev + chunk);
});
// Save to database
await saveConversation({
prompt,
response: aiResponse,
language: selectedLanguage,
code: response.code
});
} catch (error) {
console.error('Error:', error);
} finally {
setIsLoading(false);
}
};
return (
{code.length} characters
setCode(value || '')}
theme={theme === 'dark' ? 'vs-dark' : 'light'}
options={{
minimap: { enabled: true },
fontSize: 14,
wordWrap: 'on'
}}
/>
AI Assistant
{isLoading ? (
) : (
{aiResponse || '// AI response will appear here...'}
)}
);
}
2. Real-time Streaming API Route
// app/api/code/stream/route.ts
import { NextRequest, NextResponse } from 'next/server';
import { OpenAIStream, StreamingTextResponse } from 'ai';
export const runtime = 'edge';
export async function POST(req: NextRequest) {
try {
const { prompt, language, context } = await req.json();
const response = await fetch('https://api.openai.com/v1/chat/completions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${process.env.OPENAI_API_KEY}`
},
body: JSON.stringify({
model: 'gpt-4',
stream: true,
messages: [
{
role: 'system',
content: `You are a ${language} expert. Provide code with explanations.`
},
{
role: 'user',
content: `${prompt}\n\nContext:\n${context}`
}
],
max_tokens: 2000
})
});
if (!response.ok) {
throw new Error('OpenAI API error');
}
const stream = OpenAIStream(response);
return new StreamingTextResponse(stream);
} catch (error) {
console.error('Stream error:', error);
return NextResponse.json(
{ error: 'Failed to stream response' },
{ status: 500 }
);
}
}
๐ Deployment Guide
Backend (FastAPI) - Docker Deployment
# Dockerfile
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
RUN useradd -m -u 1000 user
USER user
EXPOSE 8000
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
# docker-compose.yml
version: '3.8'
services:
backend:
build: ./backend
ports:
- "8000:8000"
environment:
- DATABASE_URL=postgresql://user:pass@db:5432/aicode
- OPENAI_API_KEY=${OPENAI_API_KEY}
depends_on:
- db
db:
image: postgres:15
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: pass
POSTGRES_DB: aicode
volumes:
- postgres_data:/var/lib/postgresql/data
frontend:
build: ./frontend
ports:
- "3000:3000"
depends_on:
- backend
volumes:
postgres_data:
Frontend (Next.js) - Vercel Deployment
// vercel.json
{
"buildCommand": "npm run build",
"devCommand": "npm run dev",
"installCommand": "npm install",
"framework": "nextjs",
"outputDirectory": ".next",
"env": {
"NEXT_PUBLIC_API_URL": "https://your-api.vercel.app",
"NEXT_PUBLIC_OPENAI_KEY": "@openai_api_key"
},
"regions": ["iad1"],
"functions": {
"app/api/**/*.ts": {
"maxDuration": 60
}
}
}
Environment Variables
# .env.local NEXT_PUBLIC_API_URL=http://localhost:8000 OPENAI_API_KEY=your_key_here DATABASE_URL=postgresql://... JWT_SECRET=your_jwt_secret
✨ Advanced Features
๐ Code Analysis
- Complexity scoring (O-notation)
- Security vulnerability detection
- Performance optimization suggestions
- Code style & linting
๐ค AI Capabilities
- Multi-language code generation
- Code-to-code translation
- Documentation generation
- Test case creation
๐ Analytics
- Token usage tracking
- Popular language stats
- User engagement metrics
- Cost optimization
๐ Security
- JWT authentication
- Rate limiting
- Input validation & sanitization
- API key rotation
๐งช Testing Suite
# tests/test_ai_service.py
import pytest
from app.services.ai_service import AICodeAssistant
from app.schemas.code import CodeRequest
@pytest.mark.asyncio
async def test_code_generation():
"""Test AI code generation"""
assistant = AICodeAssistant()
request = CodeRequest(
prompt="Create a React component",
language="javascript",
requirements="Use TypeScript, hooks"
)
response = await assistant.generate_code(request)
assert response.code is not None
assert len(response.code) > 0
assert response.language == "javascript"
assert "React" in response.code or "TypeScript" in response.code
@pytest.mark.asyncio
async def test_error_handling():
"""Test error handling"""
assistant = AICodeAssistant()
with pytest.raises(HTTPException):
await assistant.generate_code(None)
๐ฏ Next Steps
This is a production-ready foundation. Here's what to add next:
Phase 2
- User authentication
- Payment integration
- Team collaboration
Phase 3
- Mobile app (React Native)
- VS Code extension
- CLI tool
Phase 4
- Custom AI models
- Enterprise features
- API marketplace
๐ Additional Resources
| Resource | Link | Purpose |
|---|---|---|
| GitHub Repository | github.com/yourusername/ai-code-assistant | Complete source code |
| Live Demo | demo.aicodeassistant.com | Try it yourself |
| API Documentation | api.aicodeassistant.com/docs | API reference |
Comments
Post a Comment