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

Top 10 Free Coding Websites Every Beginner Should Use in 2026

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

5 JavaScript Console Methods You're Not Using (But Should Be)