You are an expert AI assistant tasked with building a complete, functional Next.js MVP application. This application, 'Code Guardian', acts as a security layer for code repositories, specifically designed to detect and prevent unwanted content (ads, spam, malicious links, etc.) injected by AI code assistants like GitHub Copilot into Pull Requests (PRs). The goal is to protect the integrity and privacy of developers' codebases.
PROJECT OVERVIEW:
'Code Guardian' aims to solve the problem of AI code assistants inadvertently or intentionally inserting extraneous, harmful, or promotional content into developer's code and documentation within version control systems. The core value proposition is to provide developers and teams with a trusted layer that automatically scans PRs for such unwanted insertions, ensuring code quality, security, and maintaining a clean development environment. It prevents the 'platform death' scenario described by Cory Doctorow, where tools designed to help eventually abuse their users. This MVP will focus on integrating with GitHub, scanning PR descriptions and code changes for specific patterns indicative of unwanted content.
TECH STACK:
- Frontend: Next.js (App Router)
- Styling: Tailwind CSS
- State Management: Zustand or React Context API for global state, component-level state where appropriate.
- UI Components: shadcn/ui (for accessible, well-designed components)
- Backend: Next.js API Routes or a separate Node.js/Express server if complexity demands.
- Database: PostgreSQL with Drizzle ORM (for type-safe database interactions).
- Authentication: NextAuth.js (for secure GitHub OAuth and session management).
- API Interaction: React Query (TanStack Query) for efficient data fetching and caching.
- Form Handling: React Hook Form with Zod for validation.
- Utilities: Lodash, date-fns.
- CI/CD Integration: GitHub Actions for automated testing and deployment.
DATABASE SCHEMA (PostgreSQL with Drizzle ORM):
1. `users` table:
- `id`: UUID (Primary Key, default gen_random_uuid())
- `name`: TEXT
- `email`: TEXT UNIQUE
- `emailVerified`: TIMESTAMP WITH TIME ZONE
- `image`: TEXT
- `createdAt`: TIMESTAMP WITH TIME ZONE DEFAULT now()
- `updatedAt`: TIMESTAMP WITH TIME ZONE DEFAULT now()
2. `accounts` table (for NextAuth.js):
- `id`: BIGSERIAL PRIMARY KEY
- `userId`: UUID REFERENCES `users`(`id`) ON DELETE CASCADE
- `type`: TEXT
- `provider`: TEXT
- `providerAccountId`: TEXT
- `refresh_token`: TEXT
- `access_token`: TEXT
- `expires_at`: BIGINT
- `token_type`: TEXT
- `scope`: TEXT
- `id_token`: TEXT
- `createdAt`: TIMESTAMP WITH TIME ZONE DEFAULT now()
- `updatedAt`: TIMESTAMP WITH TIME ZONE DEFAULT now()
- UNIQUE (`provider`, `providerAccountId`)
3. `sessions` table (for NextAuth.js):
- `sessionToken`: TEXT PRIMARY KEY
- `userId`: UUID REFERENCES `users`(`id`) ON DELETE CASCADE
- `expires`: TIMESTAMP WITH TIME ZONE
- `createdAt`: TIMESTAMP WITH TIME ZONE DEFAULT now()
- `updatedAt`: TIMESTAMP WITH TIME ZONE DEFAULT now()
4. `verificationTokens` table (for NextAuth.js):
- `identifier`: TEXT
- `token`: TEXT PRIMARY KEY
- `expires`: TIMESTAMP WITH TIME ZONE
- `createdAt`: TIMESTAMP WITH TIME ZONE DEFAULT now()
- `updatedAt`: TIMESTAMP WITH TIME ZONE DEFAULT now()
5. `repositories` table:
- `id`: UUID (Primary Key, default gen_random_uuid())
- `userId`: UUID REFERENCES `users`(`id`) ON DELETE CASCADE
- `githubRepoId`: BIGINT UNIQUE NOT NULL // GitHub's internal repository ID
- `fullName`: TEXT NOT NULL // e.g., 'owner/repo_name'
- `name`: TEXT NOT NULL
- `owner`: TEXT NOT NULL
- `private`: BOOLEAN DEFAULT FALSE
- `hookId`: BIGINT // ID of the GitHub webhook for this repo
- `syncStatus`: TEXT DEFAULT 'pending' // 'pending', 'active', 'error', 'disabled'
- `createdAt`: TIMESTAMP WITH TIME ZONE DEFAULT now()
- `updatedAt`: TIMESTAMP WITH TIME ZONE DEFAULT now()
6. `scanRules` table:
- `id`: UUID (Primary Key, default gen_random_uuid())
- `userId`: UUID REFERENCES `users`(`id`) ON DELETE CASCADE
- `repositoryId`: UUID REFERENCES `repositories`(`id`) ON DELETE SET NULL
- `name`: TEXT NOT NULL // e.g., 'Ad Detection Rule', 'External Link Rule'
- `pattern`: TEXT NOT NULL // Regex pattern to detect unwanted content
- `type`: TEXT NOT NULL // 'description', 'code', 'commit_message'
- `severity`: TEXT DEFAULT 'warning' // 'info', 'warning', 'error'
- `enabled`: BOOLEAN DEFAULT TRUE
- `createdAt`: TIMESTAMP WITH TIME ZONE DEFAULT now()
- `updatedAt`: TIMESTAMP WITH TIME ZONE DEFAULT now()
7. `scanResults` table:
- `id`: UUID (Primary Key, default gen_random_uuid())
- `repositoryId`: UUID REFERENCES `repositories`(`id`) ON DELETE CASCADE
- `prId`: BIGINT NOT NULL // GitHub's internal PR ID
- `commitSha`: TEXT NOT NULL
- `filePath`: TEXT // Null for description scans
- `lineNumber`: INTEGER // Null for description scans
- `matchedContent`: TEXT NOT NULL
- `ruleId`: UUID REFERENCES `scanRules`(`id`) ON DELETE SET NULL
- `ruleName`: TEXT
- `detectedAt`: TIMESTAMP WITH TIME ZONE DEFAULT now()
- `status`: TEXT DEFAULT 'unresolved' // 'unresolved', 'resolved', 'ignored'
CORE FEATURES & USER FLOW:
1. Authentication:
- User signs up/logs in using GitHub OAuth via NextAuth.js.
- Upon successful login, the user is redirected to their dashboard.
2. Repository Integration:
- User navigates to 'Settings' > 'Repositories'.
- Clicks 'Add Repository'.
- A modal prompts the user to select repositories from their GitHub account.
- Upon selection, the application:
a. Fetches repository details from GitHub API.
b. Creates a new entry in the `repositories` table, linking it to the user.
c. Attempts to create a webhook on the GitHub repository for `pull_request` events (pointing to our Next.js API route).
d. Handles potential errors during webhook creation (e.g., permissions).
e. Updates the `syncStatus` in the `repositories` table.
- User can enable/disable webhook sync for each repository.
3. Rule Management:
- User navigates to 'Settings' > 'Scan Rules'.
- Sees a list of default rules (e.g., detect URLs, "buy now" phrases, AI tool names in descriptions).
- Can enable/disable rules.
- Can create new custom rules:
- Input: Rule Name, Regex Pattern, Target (Description, Code, Commit Message), Severity.
- Form validation ensures the regex is valid and other fields are present.
- New rule is saved in the `scanRules` table, linked to the user (or optionally a specific repository).
- Can edit/delete custom rules.
4. PR Scan Trigger & Execution:
- GitHub sends a `pull_request` webhook event to the designated Next.js API route (`/api/webhooks/github`).
- The API route:
a. Verifies the GitHub webhook signature for security.
b. Parses the event payload to identify the PR details (ID, repository, head commit SHA).
c. Checks if the repository is enabled for scanning and linked to the user.
d. Fetches the PR's diff content (and potentially description) using the GitHub API (requires appropriate permissions/token).
e. Retrieves the relevant `scanRules` for the user/repository.
f. Iterates through the rules and applies them to the PR's description and changed code files.
g. For code changes, it iterates through each added/modified line.
h. If a rule's pattern matches any content:
- Creates a record in the `scanResults` table.
- Optionally, uses the GitHub API to add a comment to the PR with the detected issue details and a link to Code Guardian.
- Optionally, can block the PR merge based on severity if configured.
i. Handles rate limits and errors gracefully.
5. Dashboard & Results View:
- User logs in and sees the main dashboard.
- Displays a summary: Number of repositories monitored, recent scans, number of unresolved issues.
- User can navigate to 'Scans' or 'Issues'.
- The 'Issues' page lists all `scanResults` with filters (Repository, PR, Status, Severity, Rule).
- Clicking an issue shows details: PR link, file path, line number, matched content, the rule triggered, and options to 'Resolve' or 'Ignore'.
- Resolved/Ignored status updates the `scanResults` table.
API & DATA FETCHING:
- `/api/auth/*`: NextAuth.js routes for authentication.
- `/api/webhooks/github`: POST endpoint to receive GitHub webhooks. Needs robust error handling and signature verification.
- `/api/repositories`: GET (list user's repos), POST (add repo, triggers webhook setup), DELETE (remove repo, triggers webhook deletion).
- `/api/scan-rules`: GET (list rules), POST (create rule), PUT (update rule), DELETE (delete rule).
- `/api/scans/results`: GET (list scan results with filtering/pagination).
- `/api/scans/results/[id]`: GET (single result), PUT (update status - resolve/ignore).
- Data fetching will primarily use React Query (`useQuery`, `useMutation`) on the client-side, interacting with these API routes.
- GitHub API interactions will happen server-side within the webhook handler and potentially in dedicated API routes if needed for proactive checks.
COMPONENT BREAKDOWN (Next.js App Router Structure):
- `app/layout.tsx`: Root layout (html, body, providers).
- `app/page.tsx`: Landing Page (Public).
- `app/dashboard/page.tsx`: Main dashboard after login. Shows summary stats. Uses `useQuery` for summary data.
- `app/settings/page.tsx`: Settings index page.
- `app/settings/repositories/page.tsx`: Manage connected GitHub repositories. Lists repos, Add button. Handles modal for repo selection. Uses `useQuery` for repo list, `useMutation` for add/delete.
- `app/settings/scan-rules/page.tsx`: Manage scan rules. Lists rules, Add/Edit buttons. Uses `useQuery` for rules, `useMutation` for CRUD operations. Includes a form component (`RuleForm.tsx`) for creating/editing rules.
- `app/issues/page.tsx`: List of detected issues. Implements filtering and pagination. Uses `useQuery` for fetching issues. Includes `IssueTable.tsx` component.
- `app/issues/[id]/page.tsx`: Detail view for a single issue. Shows context, allows resolving/ignoring. Uses `useQuery` for issue details, `useMutation` for status updates.
- `app/api/auth/[...nextauth]/route.ts`: NextAuth.js configuration.
- `app/api/webhooks/github/route.ts`: GitHub webhook handler.
- `components/ui/`: Re-exports from shadcn/ui (Button, Input, Card, Table, Dialog, Alert, etc.).
- `components/layout/`: `Navbar.tsx`, `Sidebar.tsx`, `Footer.tsx`.
- `components/auth/`: `SignInButton.tsx`, `SignOutButton.tsx`.
- `components/repositories/`: `RepositoryList.tsx`, `RepositoryItem.tsx`, `AddRepositoryModal.tsx`.
- `components/rules/`: `RuleList.tsx`, `RuleItem.tsx`, `RuleForm.tsx`.
- `components/issues/`: `IssueList.tsx`, `IssueItem.tsx`, `IssueDetailView.tsx`, `IssueFilter.tsx`.
- `components/common/`: `LoadingSpinner.tsx`, `AlertMessage.tsx`, `ErrorBoundary.tsx`.
- `lib/db.ts`: Drizzle ORM configuration and database connection.
- `lib/github.ts`: Utility functions for interacting with GitHub API.
- `lib/utils.ts`: General utility functions.
- `hooks/`: Custom hooks, e.g., `useRepositories.ts`, `useScanRules.ts`.
UI/UX DESIGN & VISUAL IDENTITY:
- Style: "Minimalist Clean" with subtle gradient accents.
- Color Palette:
- Primary: `#6366F1` (Indigo-500)
- Secondary: `#818CF8` (Indigo-400)
- Accent/Hover: `#A5B4FC` (Indigo-300)
- Background: `#FFFFFF` (White)
- Dark Background (for modals/cards): `#F9FAFB` (Gray-50)
- Text (Primary): `#1F2937` (Gray-900)
- Text (Secondary): `#6B7280` (Gray-500)
- Success: `#10B981` (Green-500)
- Warning: `#F59E0B` (Amber-500)
- Error: `#EF4444` (Red-500)
- Typography: Inter (or similar sans-serif like Inter, Manrope).
- Headings: Bold, varying weights.
- Body: Regular weight.
- Layout: Clean, card-based UI for dashboards and settings. Sidebar navigation for primary sections. Clear calls to action. Generous whitespace.
- Responsiveness: Mobile-first approach. Tailwind CSS's responsive utilities (`sm:`, `md:`, `lg:`) will be used extensively. Ensure layouts adapt gracefully to all screen sizes.
- Visual Elements: Subtle use of gradients in buttons or headers. Clean icons fromlucide-react or similar. Avoid clutter.
ANIMATIONS:
- Page Transitions: Subtle fade-in/out using Next.js's built-in features or a library like Framer Motion if needed.
- Button Hovers: Slight scale-up or background color change.
- Loading States: Skeleton loaders (`react-loading-skeleton` or shadcn/ui placeholders) or spinners (`LoadingSpinner.tsx`) when fetching data.
- Transitions: Smooth transitions for modal openings/closings and dropdowns (provided by shadcn/ui/Tailwind CSS).
EDGE CASES:
- Authentication:
- Unauthenticated user attempting to access protected routes redirects to login.
- GitHub OAuth errors are handled and displayed to the user.
- Session expiry and refresh.
- Authorization:
- Users can only access/modify their own repositories and rules.
- API Rate Limiting:
- Implement exponential backoff or caching strategies when interacting with the GitHub API to avoid hitting rate limits.
- Webhook Failures:
- If a webhook fails to deliver, provide guidance to the user on how to re-establish the connection or manually trigger a scan.
- Log webhook delivery failures server-side.
- Empty States:
- Repositories page: "No repositories connected. Add your first repository!"
- Rules page: "No custom rules created. Add a new rule or use defaults."
- Issues page: "No issues detected in recent scans!"
- Validation:
- All form inputs (rules, settings) use React Hook Form and Zod for robust client-side and server-side validation.
- Regex pattern validation for custom rules.
- GitHub API Errors:
- Gracefully handle errors (e.g., repo not found, insufficient permissions) when fetching data from GitHub.
- No Code Changes in PR:
- If a PR only updates the description, the scan logic should focus only on the description field.
SAMPLE DATA:
1. Repository (`repositories` table):
`{ "id": "uuid1", "userId": "user1", "githubRepoId": 123456789, "fullName": "devuser/cool-project", "name": "cool-project", "owner": "devuser", "private": false, "hookId": 98765, "syncStatus": "active" }`
2. Scan Rule (Default Ad Rule - `scanRules` table):
`{ "id": "rule1", "userId": "user1", "name": "Detect Advertisements", "pattern": "(?i)(buy now|copilot|raycast|special offer|limited time)", "type": "description", "severity": "warning", "enabled": true }`
3. Scan Rule (Default External Link Rule - `scanRules` table):
`{ "id": "rule2", "userId": "user1", "name": "Detect External Links", "pattern": "https?://(?!github\.com/|localhost:|127\.0\.0\.)", "type": "description", "severity": "info", "enabled": true }`
4. Scan Result (Ad detected in PR description - `scanResults` table):
`{ "id": "res1", "repositoryId": "uuid1", "prId": 55, "commitSha": "abc123def", "filePath": null, "lineNumber": null, "matchedContent": "...check out Copilot Pro for amazing features...", "ruleId": "rule1", "ruleName": "Detect Advertisements", "detectedAt": "2023-10-27T10:00:00Z", "status": "unresolved" }`
5. Scan Result (External link in code - `scanResults` table):
`{ "id": "res2", "repositoryId": "uuid1", "prId": 56, "commitSha": "ghi456jkl", "filePath": "src/utils/helpers.js", "lineNumber": 42, "matchedContent": "fetch('http://malicious-site.com/data')", "ruleId": "rule2", "ruleName": "Detect External Links", "detectedAt": "2023-10-27T11:30:00Z", "status": "unresolved" }`
6. User (`users` table):
`{ "id": "user1", "name": "Dev User", "email": "dev@example.com", "image": "https://github.com/images/modules/logos_page/GitHub-Mark.png" }`
7. Account (`accounts` table for GitHub OAuth):
`{ "id": 1, "userId": "user1", "type": "oauth", "provider": "github", "providerAccountId": "12345678", "access_token": "gho_xxxx...", "expires_at": 1700000000 }`
8. Repository Rule Linkage (Implicit via `userId` on `scanRules` or could be explicit via a join table if needed for repo-specific overrides).
9. Commit Info (as part of PR data):
`{ "sha": "abc123def", "commit": { "message": "Refactor login component\n\n---\\nCopilot suggested changes for typo correction.\n" } }` (Illustrates commit message scanning possibility)
10. PR Description Data:
`"PR Description: Fixed a bug in the user auth module. For more details, see the attached ticket. Also, check out Raycast's new AI features! Link: http://raycast.com/ai"` (Illustrates description scanning)