Skip to content

hamza7malik/pr-review-ai

Repository files navigation

PR Review AI

LLM-Powered GitHub Pull Request Review Assistant - A production-grade tool that analyzes GitHub pull requests using AI and provides structured, actionable code reviews.

๐ŸŽฌ Demo

demo.mp4

Note: If the video doesn't load above, you can watch it here or view it in the live application.

๐Ÿš€ Overview

This application allows users to:

  • Paste a public GitHub Pull Request URL
  • Fetch the PR diff using the GitHub API
  • Analyze the diff using an LLM (OpenAI GPT-4) acting as a senior code reviewer
  • Display a structured, readable review with risk categorization

Built as a portfolio project demonstrating clean architecture, modern TypeScript practices, and full-stack development skills.

๐Ÿ—๏ธ Architecture

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                         Frontend                            โ”‚
โ”‚  (Vite + React + TypeScript + shadcn/ui + TailwindCSS)    โ”‚
โ”‚                                                             โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚
โ”‚  โ”‚  UI Layer    โ”‚  โ”‚ React Query  โ”‚  โ”‚  Zustand Store  โ”‚  โ”‚
โ”‚  โ”‚ (Components) โ”‚  โ”‚  (API State) โ”‚  โ”‚  (Local State)  โ”‚  โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚
โ”‚            โ”‚               โ”‚                   โ”‚            โ”‚
โ”‚            โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜            โ”‚
โ”‚                            โ”‚                                โ”‚
โ”‚                      [Axios Client]                         โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                             โ”‚
                    HTTP POST /api/review
                             โ”‚
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚                         Backend                             โ”‚
โ”‚        (Node.js + Express + TypeScript + Octokit)          โ”‚
โ”‚                                                             โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚
โ”‚  โ”‚  Controller  โ”‚โ†’ โ”‚   Services   โ”‚โ†’ โ”‚   External APIs โ”‚  โ”‚
โ”‚  โ”‚  (Routing)   โ”‚  โ”‚  (Business   โ”‚  โ”‚  - GitHub API   โ”‚  โ”‚
โ”‚  โ”‚              โ”‚  โ”‚    Logic)    โ”‚  โ”‚  - OpenAI/Geminiโ”‚  โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚
โ”‚         โ”‚                  โ”‚                   โ”‚            โ”‚
โ”‚    [Validation]      [Processing]       [Integration]      โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Data Flow

  1. User Input: User submits GitHub PR URL via frontend form
  2. Validation: Zod schema validates URL format on both client and server
  3. PR Parsing: Backend extracts owner, repo, and PR number
  4. GitHub API: Fetch PR metadata and file diffs using Octokit
  5. Diff Processing: Normalize and chunk diff data for LLM consumption
  6. Provider Selection: Factory creates appropriate LLM provider (OpenAI or Gemini)
  7. LLM Analysis: Send diff to selected provider with structured prompt
  8. Response Parsing: Parse JSON response from LLM
  9. UI Rendering: Display categorized review results

๐Ÿ“ฆ Tech Stack

Frontend

  • Vite: Fast build tool and dev server
  • React 18: UI library with hooks
  • TypeScript: Type safety throughout
  • shadcn/ui: High-quality Radix + Tailwind components
  • TailwindCSS: Utility-first styling
  • Zustand: Lightweight state management
  • React Query (TanStack Query): Server state management
  • Axios: HTTP client
  • Zod: Runtime schema validation

Backend

  • Node.js + TypeScript: Runtime and language
  • Express: Web framework
  • Octokit: Official GitHub REST API client
  • LLM Providers:
    • OpenAI SDK: GPT-4 Turbo integration
    • Google Generative AI: Gemini 1.5 Pro integration
  • Factory Pattern: Extensible provider abstraction
  • Zod: Request validation
  • dotenv: Environment configuration
  • ESLint + Prettier: Code quality

๐ŸŽฏ Prompt Design

The LLM prompt is carefully engineered for high-quality code reviews:

System Prompt

You are a senior software engineer performing a pull request review.

Rules:
- Only comment on what is visible in the diff.
- Do NOT assume missing context.
- If something is unclear, ask a question instead of guessing.
- Be strict, constructive, and practical.
- Focus on bugs, edge cases, performance, security, and maintainability.

Response Structure

The LLM returns structured JSON with six categories:

  • Summary: High-level overview of changes
  • High Risk Issues: Critical bugs, security vulnerabilities
  • Medium Risk Issues: Logic errors, potential bugs
  • Low Risk / Style Issues: Code style, minor improvements
  • Suggestions: Best practices, optimizations
  • Questions for Author: Clarifications needed

Why This Design?

  1. Strict Rules: Prevents hallucination by limiting analysis to visible code
  2. Risk Categorization: Helps prioritize reviewer attention
  3. JSON Format: Ensures structured, parseable output
  4. Constructive Tone: Balances strictness with helpfulness
  5. Question Section: Acknowledges uncertainty rather than guessing

๐Ÿ“‚ Project Structure

pr-review-ai/
โ”œโ”€โ”€ backend/
โ”‚   โ”œโ”€โ”€ src/
โ”‚   โ”‚   โ”œโ”€โ”€ app.ts                    # Express app setup
โ”‚   โ”‚   โ”œโ”€โ”€ server.ts                 # Server entry point
โ”‚   โ”‚   โ”œโ”€โ”€ config/
โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ env.ts                # Environment validation
โ”‚   โ”‚   โ”œโ”€โ”€ routes/
โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ review.route.ts       # API routes
โ”‚   โ”‚   โ”œโ”€โ”€ controllers/
โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ review.controller.ts  # Request handlers
โ”‚   โ”‚   โ”œโ”€โ”€ services/
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ llm/
โ”‚   โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ base.ts           # LLM provider interface
โ”‚   โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ openai.provider.ts # OpenAI implementation
โ”‚   โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ gemini.provider.ts # Gemini implementation
โ”‚   โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ factory.ts        # Provider factory
โ”‚   โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ index.ts          # Exports
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ github.service.ts     # GitHub API integration
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ llm.service.ts        # LLM service layer
โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ review.service.ts     # Core business logic
โ”‚   โ”‚   โ”œโ”€โ”€ utils/
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ parsePrUrl.ts         # URL parsing utility
โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ chunkDiff.ts          # Diff processing
โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ logger.ts             # Logging utility
โ”‚   โ”‚   โ”œโ”€โ”€ schemas/
โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ review.schema.ts      # Zod validation schemas
โ”‚   โ”‚   โ””โ”€โ”€ types/
โ”‚   โ”‚       โ””โ”€โ”€ review.ts             # TypeScript interfaces
โ”‚   โ”œโ”€โ”€ package.json
โ”‚   โ”œโ”€โ”€ tsconfig.json
โ”‚   โ””โ”€โ”€ .env.example
โ”‚
โ””โ”€โ”€ frontend/
    โ”œโ”€โ”€ src/
    โ”‚   โ”œโ”€โ”€ app/
    โ”‚   โ”‚   โ”œโ”€โ”€ App.tsx               # Main application
    โ”‚   โ”‚   โ””โ”€โ”€ providers/
    โ”‚   โ”‚       โ”œโ”€โ”€ query-client.tsx  # React Query setup
    โ”‚   โ”‚       โ””โ”€โ”€ index.tsx         # Provider composition
    โ”‚   โ”œโ”€โ”€ components/
    โ”‚   โ”‚   โ”œโ”€โ”€ review/
    โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ ReviewResult.tsx  # Main review display
    โ”‚   โ”‚   โ”‚   โ”œโ”€โ”€ ReviewSection.tsx # Section wrapper
    โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ IssueList.tsx     # Issue rendering
    โ”‚   โ”‚   โ””โ”€โ”€ ui/                   # shadcn components
    โ”‚   โ”œโ”€โ”€ features/
    โ”‚   โ”‚   โ””โ”€โ”€ review/
    โ”‚   โ”‚       โ”œโ”€โ”€ api.ts            # API client functions
    โ”‚   โ”‚       โ”œโ”€โ”€ schema.ts         # Client validation
    โ”‚   โ”‚       โ”œโ”€โ”€ store.ts          # Zustand store
    โ”‚   โ”‚       โ””โ”€โ”€ types.ts          # TypeScript types
    โ”‚   โ”œโ”€โ”€ lib/
    โ”‚   โ”‚   โ”œโ”€โ”€ axios.ts              # Axios configuration
    โ”‚   โ”‚   โ””โ”€โ”€ utils.ts              # Utility functions
    โ”‚   โ”œโ”€โ”€ styles/
    โ”‚   โ”‚   โ””โ”€โ”€ globals.css           # Global styles
    โ”‚   โ””โ”€โ”€ main.tsx                  # Application entry
    โ”œโ”€โ”€ package.json
    โ”œโ”€โ”€ vite.config.ts
    โ”œโ”€โ”€ tailwind.config.js
    โ””โ”€โ”€ .env.example

๐Ÿ› ๏ธ Setup Instructions

Prerequisites

  • Node.js 18+ and yarn
  • LLM Provider API Key (choose one):
    • OpenAI API key (for GPT-4)
    • Google AI API key (for Gemini)
  • GitHub Personal Access Token (optional, increases rate limits)

Backend Setup

  1. Navigate to backend directory:
cd backend
  1. Install dependencies:
yarn install
  1. Create .env file:
cp .env.example .env
  1. Configure environment variables in .env:

Option A: Using OpenAI (GPT-4)

LLM_PROVIDER=openai
OPENAI_API_KEY=sk-your-openai-key-here
GITHUB_TOKEN=ghp_your-github-token-here  # Optional but recommended
PORT=4000
NODE_ENV=development

Option B: Using Google Gemini

LLM_PROVIDER=gemini
GEMINI_API_KEY=your-gemini-api-key-here
GITHUB_TOKEN=ghp_your-github-token-here  # Optional but recommended
PORT=4000
NODE_ENV=development

Note: The LLM_PROVIDER field determines which AI service to use. Set it to either openai or gemini, and provide the corresponding API key.

  1. Start development server:
yarn dev

Backend will run at http://localhost:4000

Frontend Setup

  1. Navigate to frontend directory:
cd frontend
  1. Install dependencies:
yarn install
  1. Create .env file:
cp .env.example .env
  1. Configure environment (defaults work for local development):
VITE_API_BASE_URL=http://localhost:4000
  1. Start development server:
yarn dev

Frontend will run at http://localhost:5173

Full Stack Development

Run both servers concurrently in separate terminals for full-stack development.

๐ŸŽฎ Usage

  1. Open the frontend in your browser: http://localhost:5173
  2. Paste a public GitHub PR URL (e.g., https://github.com/facebook/react/pull/28000)
  3. Click "Review PR"
  4. Wait 10-30 seconds for analysis
  5. View structured review with categorized findings

Example PR to Test

https://github.com/vercel/next.js/pull/59000
https://github.com/microsoft/vscode/pull/200000
https://github.com/facebook/react/pull/28000

Note: PR must be from a public repository.

โš™๏ธ Environment Variables

Backend

Variable Description Required
OPENAI_API_KEY OpenAI API key for LLM access โœ… Yes
GITHUB_TOKEN GitHub personal access token โš ๏ธ Recommended
PORT Server port (default: 4000) โŒ No
NODE_ENV Environment mode โŒ No

Frontend

Variable Description Required
VITE_API_BASE_URL Backend API URL โœ… Yes

๐Ÿšง Error Handling

The application handles various error scenarios gracefully:

  • Invalid URL Format: Client-side Zod validation
  • Private Repositories: GitHub API returns 404
  • Rate Limiting: GitHub/OpenAI API rate limits
  • Network Errors: Axios interceptors with user-friendly messages
  • LLM Failures: Fallback error responses
  • Large Diffs: Automatic truncation at 8000 characters

All errors display user-friendly messages without exposing stack traces.

๐ŸŽจ Code Quality Features

  • Strict TypeScript: No any types, full type safety
  • Functional Architecture: Pure functions, clear separation of concerns
  • No Logic in JSX: Components only handle rendering
  • Validation Everywhere: Zod schemas on client and server
  • ESLint + Prettier: Consistent code formatting
  • Clear Naming: No abbreviations, self-documenting code
  • Small Functions: Most functions under 50 lines
  • Error Boundaries: Graceful error handling throughout

๐Ÿ”„ Tradeoffs & Limitations

Current Limitations

  1. Public PRs Only: Cannot access private repositories without OAuth
  2. Diff Size: Large PRs truncated at 8000 chars to manage token limits
  3. Single File Processing: All files analyzed together (not individually)
  4. No Persistence: Reviews not saved (stateless design)
  5. Rate Limits: Subject to GitHub (5000/hour) and OpenAI limits

Design Decisions

  • No Database: Keeps architecture simple, suitable for demo/portfolio
  • Synchronous Processing: Simpler than async job queues for MVP
  • Client-Side State: Zustand sufficient for single-page app
  • Monorepo Structure: Separate backend/frontend for clarity

๐Ÿš€ Future Improvements

Short Term

  • Add loading skeleton UI
  • Support PR comparison (base vs head)
  • Add "copy review" functionality
  • Dark mode toggle
  • Review history (local storage)

Medium Term

  • OAuth for private repositories
  • Batch file analysis for large PRs
  • Configurable LLM parameters (temperature, model)
  • Export review as Markdown/PDF
  • Multiple LLM provider support (Anthropic, etc.)

Long Term

  • User authentication and saved reviews
  • GitHub App integration (webhook-based)
  • Real-time streaming responses
  • Custom review templates
  • Team analytics dashboard

๐Ÿ“Š Example Output

{
  "summary": "This PR introduces a new authentication system using JWT tokens...",
  "high_risk_issues": [
    "Line 42: JWT secret is hardcoded. Use environment variables.",
    "Line 78: SQL query vulnerable to injection. Use parameterized queries."
  ],
  "medium_risk_issues": [
    "Line 120: Error handling missing for async operation."
  ],
  "low_risk_or_style_issues": ["Line 15: Consider using const instead of let."],
  "suggestions": ["Consider adding unit tests for the new auth middleware."],
  "questions_for_author": [
    "What is the expected behavior when the token expires?"
  ]
}

๐Ÿงช Testing

Manual Testing

  1. Test with various PR sizes (small, medium, large)
  2. Test with different programming languages
  3. Test error scenarios (invalid URL, private repo, rate limits)
  4. Test edge cases (empty PR, binary files, etc.)

Automated Testing (Future)

  • Unit tests for utils and services
  • Integration tests for API endpoints
  • E2E tests for critical user flows

๐Ÿ“ License

MIT License - feel free to use this project for learning or portfolio purposes.

๐Ÿค Contributing

This is a portfolio project, but feedback and suggestions are welcome! Open an issue or submit a PR.

๐Ÿ‘จโ€๐Ÿ’ป Author

Built as a demonstration of production-grade full-stack development skills.


Note: This project is designed for educational and portfolio purposes. For production use, consider adding authentication, database persistence, and more robust error handling.

About

LLM-powered PR review assistant with OpenAI/Gemini - Analyzes GitHub pull requests and provides structured, actionable code reviews

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors