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.mp4
Note: If the video doesn't load above, you can watch it here or view it in the live application.
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.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ 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] โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
- User Input: User submits GitHub PR URL via frontend form
- Validation: Zod schema validates URL format on both client and server
- PR Parsing: Backend extracts owner, repo, and PR number
- GitHub API: Fetch PR metadata and file diffs using Octokit
- Diff Processing: Normalize and chunk diff data for LLM consumption
- Provider Selection: Factory creates appropriate LLM provider (OpenAI or Gemini)
- LLM Analysis: Send diff to selected provider with structured prompt
- Response Parsing: Parse JSON response from LLM
- UI Rendering: Display categorized review results
- 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
- 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
The LLM prompt is carefully engineered for high-quality code reviews:
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.
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
- Strict Rules: Prevents hallucination by limiting analysis to visible code
- Risk Categorization: Helps prioritize reviewer attention
- JSON Format: Ensures structured, parseable output
- Constructive Tone: Balances strictness with helpfulness
- Question Section: Acknowledges uncertainty rather than guessing
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
- 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)
- Navigate to backend directory:
cd backend- Install dependencies:
yarn install- Create
.envfile:
cp .env.example .env- 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=developmentOption 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=developmentNote: The
LLM_PROVIDERfield determines which AI service to use. Set it to eitheropenaiorgemini, and provide the corresponding API key.
- Start development server:
yarn devBackend will run at http://localhost:4000
- Navigate to frontend directory:
cd frontend- Install dependencies:
yarn install- Create
.envfile:
cp .env.example .env- Configure environment (defaults work for local development):
VITE_API_BASE_URL=http://localhost:4000- Start development server:
yarn devFrontend will run at http://localhost:5173
Run both servers concurrently in separate terminals for full-stack development.
- Open the frontend in your browser:
http://localhost:5173 - Paste a public GitHub PR URL (e.g.,
https://github.com/facebook/react/pull/28000) - Click "Review PR"
- Wait 10-30 seconds for analysis
- View structured review with categorized findings
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.
| Variable | Description | Required |
|---|---|---|
OPENAI_API_KEY |
OpenAI API key for LLM access | โ Yes |
GITHUB_TOKEN |
GitHub personal access token | |
PORT |
Server port (default: 4000) | โ No |
NODE_ENV |
Environment mode | โ No |
| Variable | Description | Required |
|---|---|---|
VITE_API_BASE_URL |
Backend API URL | โ Yes |
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.
- Strict TypeScript: No
anytypes, 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
- Public PRs Only: Cannot access private repositories without OAuth
- Diff Size: Large PRs truncated at 8000 chars to manage token limits
- Single File Processing: All files analyzed together (not individually)
- No Persistence: Reviews not saved (stateless design)
- Rate Limits: Subject to GitHub (5000/hour) and OpenAI limits
- 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
- Add loading skeleton UI
- Support PR comparison (base vs head)
- Add "copy review" functionality
- Dark mode toggle
- Review history (local storage)
- 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.)
- User authentication and saved reviews
- GitHub App integration (webhook-based)
- Real-time streaming responses
- Custom review templates
- Team analytics dashboard
{
"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?"
]
}- Test with various PR sizes (small, medium, large)
- Test with different programming languages
- Test error scenarios (invalid URL, private repo, rate limits)
- Test edge cases (empty PR, binary files, etc.)
- Unit tests for utils and services
- Integration tests for API endpoints
- E2E tests for critical user flows
MIT License - feel free to use this project for learning or portfolio purposes.
This is a portfolio project, but feedback and suggestions are welcome! Open an issue or submit a PR.
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.