Build Your GitHub Activity Streak — Securely & Ethically
A free, open-source GitHub App that helps developers maintain daily GitHub habits without Personal Access Tokens.
⚠️ Ethics Disclaimer: Automated commits do NOT represent real development work. This tool is designed for learning and habit-building purposes only. Always be transparent about your contributions.
- Features
- Tech Stack
- Quick Start (Users)
- Installation (Developers)
- Environment Variables
- Architecture
- Project Structure
- API Reference
- Security
- Deployment
- FAQ
- Contributing
- License
- Acknowledgments
| Feature | Description |
|---|---|
| 🔒 Secure Authentication | GitHub App OAuth — no PATs or passwords required |
| 🔐 Google OAuth Support | Alternative sign-in with Google account |
| 📝 Non-destructive Changes | Only modifies README formatting (whitespace) |
| ⏰ Smart Scheduling | Automatically skips days when you have real commits |
| 🎯 Daily Limits | Maximum 5 automated commits per day per repository |
| 🔄 Full Control | Pause, resume, or uninstall anytime |
| 📊 Activity Dashboard | Track automation history with beautiful UI |
| 📧 Email Notifications | Get notified about important events |
| 📈 Analytics | Discord webhook integration for visitor analytics |
| 🌱 Beginner-Friendly | Learn GitHub automation safely |
| Frontend | Backend | Database | Infrastructure |
|
|
|
|
Getting started with Commit Habit takes less than 2 minutes:
Go to commithabit.vercel.app
Click "Get Started" and authenticate with your GitHub or Google account.
Click "Add Repository" and install the Commit Habit app on your selected repositories.
Toggle automation ON for any connected repository. That's it! 🎉
- Node.js 18.0 or higher
- npm or yarn or pnpm
- PostgreSQL database (Supabase recommended)
- GitHub Account for creating a GitHub App
git clone https://github.com/HakkanShah/commit-habit.git
cd commit-habitnpm install
# or
yarn install
# or
pnpm install- Navigate to GitHub Settings → Developer settings → GitHub Apps
- Click "New GitHub App"
- Configure the following:
| Field | Value |
|---|---|
| App Name | commit-habit (must be unique) |
| Homepage URL | https://your-app.vercel.app |
| Callback URL | https://your-app.vercel.app/api/auth/callback |
| Setup URL | https://your-app.vercel.app/api/auth/callback |
| Webhook URL | https://your-app.vercel.app/api/github/webhook |
| Webhook Secret | Generate with openssl rand -hex 32 |
-
Set Permissions:
Permission Access Level Repository contents Read & Write Metadata Read -
Subscribe to Events:
- ✅ Installation
- ✅ Installation repositories
-
Click "Create GitHub App"
-
Generate and download a Private Key (
.pemfile) -
Note your App ID, Client ID, and Client Secret
cp .env.example .env.localFill in your values (see Environment Variables section).
# Initialize Prisma and run migrations
npx prisma migrate dev --name init
# Generate Prisma Client
npx prisma generatenpm run devOpen http://localhost:3000 in your browser.
Create a .env.local file in the root directory with the following variables:
| Variable | Description | Example |
|---|---|---|
DATABASE_URL |
PostgreSQL connection string | postgresql://user:pass@host:5432/db |
GITHUB_APP_ID |
Your GitHub App ID | 123456 |
GITHUB_APP_CLIENT_ID |
OAuth Client ID | Iv1.xxxxxxxxxx |
GITHUB_APP_CLIENT_SECRET |
OAuth Client Secret | xxxxxxxxxxxxxxxx |
GITHUB_WEBHOOK_SECRET |
Webhook signature secret | openssl rand -hex 32 |
GITHUB_APP_PRIVATE_KEY |
RSA Private Key content | -----BEGIN RSA... |
NEXT_PUBLIC_APP_URL |
Application base URL | http://localhost:3000 |
NEXT_PUBLIC_GITHUB_APP_NAME |
GitHub App name | commit-habit |
CRON_SECRET |
Secret for cron endpoint | openssl rand -hex 32 |
SESSION_SECRET |
Session encryption secret | openssl rand -hex 32 |
| Variable | Description | Example |
|---|---|---|
SMTP_HOST |
Email SMTP host | smtp.gmail.com |
SMTP_PORT |
Email SMTP port | 587 |
SMTP_USER |
Email username | your-email@gmail.com |
SMTP_PASS |
Email app password | Gmail App Password |
SMTP_FROM |
From email address | CommitHabit <noreply@example.com> |
DISCORD_WEBHOOK_URL |
Discord webhook for analytics | Webhook URL |
ADMIN_EMAIL |
Admin notification email | admin@example.com |
The private key must be converted to a single-line format:
# Linux/macOS
cat private-key.pem | tr '\n' '~' | sed 's/~/\\n/g'
# Or copy directly with newlines in the .env file (inside quotes)┌─────────────────────────────────────────────────────────────────────────┐
│ User's Browser │
│ ┌────────────────┐ ┌─────────────────┐ ┌────────────────────────┐ │
│ │ Landing Page │──▶│ OAuth Install │──▶│ Dashboard │ │
│ │ │ │ (GitHub/Google)│ │ (Manage Repos) │ │
│ └────────────────┘ └─────────────────┘ └────────────────────────┘ │
└────────────────────────────────┬────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────┐
│ Next.js Application (Vercel) │
│ ┌───────────────────────────────────────────────────────────────────┐ │
│ │ API Routes │ │
│ │ ┌───────────────┐ ┌──────────────────┐ ┌────────────────────┐ │ │
│ │ │ /api/auth/* │ │ /api/github/* │ │ /api/cron/daily │ │ │
│ │ │ OAuth Flows │ │ Webhook Handler │ │ Scheduled Jobs │ │ │
│ │ └───────────────┘ └──────────────────┘ └────────────────────┘ │ │
│ │ ┌───────────────┐ ┌──────────────────┐ ┌────────────────────┐ │ │
│ │ │ /api/install* │ │ /api/analytics │ │ /api/health │ │ │
│ │ │ Manage Repos │ │ Visitor Tracking │ │ Health Check │ │ │
│ │ └───────────────┘ └──────────────────┘ └────────────────────┘ │ │
│ └───────────────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────┬───────────────────────────────────┘
│
┌───────────────────┴───────────────────┐
▼ ▼
┌────────────────────────────────┐ ┌────────────────────────────────┐
│ Supabase PostgreSQL │ │ GitHub API │
│ ┌──────────────────────────┐ │ │ • Check user commits │
│ │ Users │ │ │ • Read README content │
│ │ Accounts (Multi-Provider)│ │ │ • Create automated commit │
│ │ Installations │ │ │ • Manage app installations │
│ │ ActivityLogs │ │ │ │
│ └──────────────────────────┘ │ └────────────────────────────────┘
└────────────────────────────────┘
commit-habit/
├── 📂 prisma/
│ └── schema.prisma # Database schema (User, Account, Installation, ActivityLog)
│
├── 📂 public/
│ ├── icon.png # App favicon
│ ├── logo.png # App logo
│ ├── manifest.json # PWA manifest
│ ├── robots.txt # SEO robots file
│ └── sitemap.xml # SEO sitemap
│
├── 📂 src/
│ ├── 📂 app/
│ │ ├── 📂 api/
│ │ │ ├── 📂 auth/
│ │ │ │ ├── callback/ # OAuth callback handler
│ │ │ │ ├── logout/ # Logout handler
│ │ │ │ ├── me/ # Current user endpoint
│ │ │ │ └── google/ # Google OAuth
│ │ │ ├── 📂 cron/
│ │ │ │ └── daily/ # Daily automation cron job
│ │ │ ├── 📂 github/
│ │ │ │ └── webhook/ # GitHub webhook handler
│ │ │ ├── 📂 installations/ # Repository management
│ │ │ ├── 📂 analytics/ # Visitor analytics
│ │ │ └── 📂 health/ # Health check endpoint
│ │ │
│ │ ├── 📂 dashboard/
│ │ │ ├── page.tsx # Dashboard page
│ │ │ ├── dashboard-client.tsx
│ │ │ └── installation-card.tsx
│ │ │
│ │ ├── favicon.ico
│ │ ├── globals.css # Global styles & Tailwind
│ │ ├── layout.tsx # Root layout with SEO
│ │ ├── page.tsx # Landing page
│ │ └── providers.tsx # React providers
│ │
│ ├── 📂 components/
│ │ ├── animated-terminal.tsx # Terminal animation
│ │ ├── contribution-demo.tsx # Contribution graph demo
│ │ ├── contribution-graph.tsx # GitHub contribution graph
│ │ ├── hero-comparison.tsx # Before/after comparison
│ │ ├── hero-sequence.tsx # Hero animation sequence
│ │ ├── skeleton.tsx # Loading skeletons
│ │ ├── toast.tsx # Toast notifications
│ │ ├── workflow-animation.tsx # Workflow demo
│ │ └── ... # Other UI components
│ │
│ └── 📂 lib/
│ ├── analytics.ts # Analytics & Discord webhook
│ ├── api-client.ts # Frontend API client
│ ├── auth.ts # Session management
│ ├── email.ts # Email service
│ ├── errors.ts # Error handling utilities
│ ├── github.ts # GitHub API utilities
│ ├── prisma.ts # Database client
│ ├── sounds.ts # Sound effects
│ └── utils.ts # Helper functions
│
├── .env.example # Environment variables template
├── next.config.ts # Next.js configuration
├── package.json # Dependencies
├── tailwind.config.ts # Tailwind configuration
├── tsconfig.json # TypeScript configuration
└── vercel.json # Vercel cron configuration
| Endpoint | Method | Description |
|---|---|---|
/api/auth/callback |
GET | GitHub OAuth callback handler |
/api/auth/google |
GET | Google OAuth initiation |
/api/auth/google/callback |
GET | Google OAuth callback |
/api/auth/logout |
POST | Logout and clear session |
/api/auth/me |
GET | Get current authenticated user |
| Endpoint | Method | Description |
|---|---|---|
/api/installations |
GET | List user's connected repositories |
/api/installations/[id] |
PATCH | Toggle automation for a repository |
/api/installations/[id] |
DELETE | Remove a repository |
| Endpoint | Method | Description |
|---|---|---|
/api/github/webhook |
POST | GitHub webhook receiver |
/api/cron/daily |
GET | Daily automation job (protected) |
/api/health |
GET | Health check endpoint |
/api/analytics |
POST | Visitor analytics |
Commit Habit implements enterprise-grade security practices:
| Aspect | Implementation |
|---|---|
| Authentication | GitHub App OAuth (no PAT exposure) |
| Token Storage | Access tokens are never stored — generated on-demand via JWT |
| Private Keys | Stored only as environment variables, never in code |
| Webhooks | HMAC-SHA256 signature verification |
| Sessions | HTTP-only secure cookies with encryption |
| Cron Protection | Secret header validation for scheduled jobs |
| Revocation | Users can uninstall anytime from GitHub settings |
| Data Privacy | Minimal data collection, GDPR-friendly |
- Push your repository to GitHub
- Import the project at vercel.com/new
- Add all environment variables from
.env.example - Deploy — Vercel handles the rest!
The vercel.json includes a cron job running daily at 6 AM UTC:
{
"crons": [
{
"path": "/api/cron/daily",
"schedule": "0 6 * * *"
}
]
}- Update GitHub App URLs to your Vercel domain
- Run database migrations:
npx prisma migrate deploy - Verify webhook delivery in GitHub App settings
- Test the OAuth flow end-to-end
Why use a GitHub App instead of Personal Access Tokens?
- More Secure: No long-lived tokens stored in the database
- User Control: Can be uninstalled anytime from GitHub settings
- Transparent: Clear permissions displayed during installation
- Learning Opportunity: Teaches real-world authentication patterns
What exactly does the automation do?
It toggles trailing whitespace in your README.md file. This creates a minimal, non-destructive commit that maintains your activity streak without modifying actual code.
How do I uninstall Commit Habit?
- Go to GitHub Settings → Applications
- Find "Commit Habit"
- Click "Configure" → "Uninstall"
Your data will be automatically cleaned up.
Can I self-host this?
Absolutely! Follow the Installation guide to deploy your own instance. You'll need to create your own GitHub App and database.
Contributions are welcome! Here's how you can help:
- Fork the repository
- Clone your fork:
git clone https://github.com/YOUR_USERNAME/commit-habit.git - Create a feature branch:
git checkout -b feature/amazing-feature - Commit your changes:
git commit -m 'Add amazing feature' - Push to the branch:
git push origin feature/amazing-feature - Open a Pull Request
- Follow the existing code style
- Write meaningful commit messages
- Add tests for new features
- Update documentation as needed
This project is licensed under the MIT License — see the LICENSE file for details.