Build an AI-Powered Code Assistant with Next.js, FastAPI & OpenAI | Full Stack 2026

Build AI Code Assistant | Full-Stack Tutorial

๐Ÿš€ 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

Popular posts from this blog

Graph Data Structure – Complete Beginner to Advanced Guide with BFS, DFS and Examples

Top Coding Mistakes Beginners Make (And How to Fix Them the Right Way)

Top 10 Free Coding Websites Every Beginner Should Use in 2026