TypeScript · Updated 2026
Repo Deleter
Bulk delete GitHub repositories instantly. Secure, fast, no data stored.
GitHub Repo Cleaner
A secure web application to bulk delete GitHub repositories. Sign in with GitHub, select repos, and delete them instantly.
Try it out here: https://repo-deleter.xyz
Features
- Bulk Selection: Search, filter, and select multiple repositories at once
- Fast Deletion: Delete up to 100 repositories in a single action with concurrent processing
- Secure: No database, no data storage. Your token is encrypted in an HTTP-only cookie
- User-Owned Only: Only shows repositories you own (excludes organization repos)
- Retry Failed: If any deletions fail, easily retry them
- Beautiful UI: Modern, responsive design with dark mode support
Tech Stack
- Framework: Next.js 16 (App Router)
- Language: TypeScript
- Styling: Tailwind CSS
- Auth: NextAuth.js with GitHub OAuth
- GitHub API: Octokit
- Validation: Zod
- Analytics: Vercel Analytics
- Hosting: Vercel
Prerequisites
- Node.js 20+
- A GitHub account
- A GitHub OAuth App
Environment Variables
| Variable | Description |
|----------|-------------|
| NEXTAUTH_URL | Your app's URL (e.g., http://localhost:3000 for dev) |
| NEXTAUTH_SECRET | A random string for session encryption |
| GITHUB_ID | Your GitHub OAuth App Client ID |
| GITHUB_SECRET | Your GitHub OAuth App Client Secret |
Setup
1. Create a GitHub OAuth App
- Go to GitHub Developer Settings
- Click New OAuth App
- Fill in the details:
- Application name: GitHub Repo Cleaner (or your choice)
- Homepage URL:
http://localhost:3000(for development) - Authorization callback URL:
http://localhost:3000/api/auth/callback/github
- Click Register application
- Copy the Client ID
- Click Generate a new client secret and copy it
2. Configure Environment
# Copy the example env file
cp .env.example .env.local
# Edit .env.local with your values
Your .env.local should look like:
NEXTAUTH_URL=http://localhost:3000
NEXTAUTH_SECRET=your-generated-secret
GITHUB_ID=your-github-client-id
GITHUB_SECRET=your-github-client-secret
Generate a secret:
openssl rand -base64 32
3. Install Dependencies
npm install
4. Run Development Server
npm run dev
Open http://localhost:3000 in your browser.
Security
What This App Does
- Uses GitHub OAuth for authentication (no passwords stored)
- Fetches your repository list from GitHub's API
- Deletes repositories using GitHub's API when you confirm
- Stores your access token in an encrypted HTTP-only session cookie
What This App Does NOT Do
- Store any data in a database
- Log repository names or sensitive information
- Share your data with third parties
- Access organization repositories
Session Security
- Session expires after 1 hour
- Cookies are HTTP-only (not accessible via JavaScript)
- Cookies use SameSite=Lax for CSRF protection
- Cookies are Secure in production (HTTPS only)
- Token is encrypted in the JWT
Revoking Access
You can revoke this app's access anytime:
- Go to GitHub Settings > Applications
- Find "GitHub Repo Cleaner"
- Click Revoke
Limitations
- User-owned repos only: Organization repositories are not shown
- 100 repos per action: Maximum bulk delete limit
- Rate limits: Subject to GitHub API rate limits (5,000 requests/hour for authenticated users)
- No recovery: Deleted repositories cannot be recovered
Project Structure
src/
├── app/
│ ├── api/
│ │ ├── auth/[...nextauth]/ # NextAuth API route
│ │ ├── repos/ # Repo listing API
│ │ └── delete/ # Repo deletion API
│ ├── dashboard/ # Protected dashboard page
│ ├── privacy/ # Privacy policy
│ ├── terms/ # Terms of service
│ ├── layout.tsx # Root layout with providers
│ ├── page.tsx # Landing page
│ ├── robots.ts # robots.txt
│ └── sitemap.ts # sitemap.xml
├── components/
│ ├── Button.tsx # Reusable button
│ ├── ConfirmModal.tsx # Deletion confirmation modal
│ ├── Header.tsx # App header
│ ├── Providers.tsx # Session provider wrapper
│ ├── RepoTable.tsx # Repository table
│ ├── ResultsSummary.tsx # Deletion results
│ ├── Toast.tsx # Toast notifications
│ └── Toolbar.tsx # Search/sort/delete toolbar
├── lib/
│ ├── auth.ts # NextAuth configuration
│ ├── github.ts # GitHub API functions
│ └── validation.ts # Zod schemas
└── types/
└── index.ts # TypeScript types
API Routes
GET /api/repos
Returns the authenticated user's repositories.
Response:
{
"repos": [
{
"id": 123,
"name": "my-repo",
"full_name": "username/my-repo",
"private": false,
"fork": false,
"is_template": false,
"updated_at": "2024-01-15T10:30:00Z",
"created_at": "2024-01-01T10:00:00Z",
"html_url": "https://github.com/username/my-repo",
"description": "My repository"
}
]
}
POST /api/delete
Deletes the specified repositories.
Request:
{
"full_names": ["username/repo1", "username/repo2"]
}
Response:
{
"results": [
{
"full_name": "username/repo1",
"ok": true,
"status": 204,
"message": "Deleted successfully"
},
{
"full_name": "username/repo2",
"ok": false,
"status": 403,
"message": "Rate limited or insufficient permissions"
}
]
}
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
MIT License - feel free to use this project for any purpose.
Disclaimer
This application is not affiliated with, endorsed by, or connected to GitHub, Inc. Use at your own risk. Always ensure you have backups of important repositories before deletion.