CommitPulse is built by the open-source community, for the open-source community. Whether you're a first-year developer from India shipping your first PR, or a senior engineer with 10 years of SVG experience — you belong here. The only requirement is that you care about quality.
- The Standard We Hold
- Local Setup
- What to Contribute
- Automated Issue Management & Claiming
- Branch & Commit Conventions
- Opening a Pull Request
- Code Style & Quality Gates
- Community Guidelines
CommitPulse is not a generic badge generator. It is a premium, high-fidelity data visualization tool with a distinct aesthetic identity.
Every contribution must uphold this standard. Before you open a PR, ask yourself:
"Does this look like something you'd find in a Dribbble showcase or a polished SaaS product — or does it look like a placeholder?"
If the answer is the latter, it's not ready yet. This is not gatekeeping — it's respect for the developers who embed CommitPulse in their public profiles.
- ✅ SVGs must use curated, harmonious color palettes — not arbitrary hex codes
- ✅ Animations must be smooth and purposeful — not distracting or janky
- ✅ Typography must match the
Syncopate/Space Groteskdesign system - ✅ New themes must feel cohesive — every
bg,accent, andtextvalue must work together - ❌ No raw, unstyled
<rect>or<text>elements without intentional styling - ❌ No flat, MS-Paint-level color combinations
- ❌ No breaking changes to the public API without a migration path
Get CommitPulse running on your machine in under 5 minutes.
- Node.js
v18+ - npm
v9+ - A GitHub Personal Access Token — generate one here with the
read:userscope
# Step 1 — Clone the repository
git clone https://github.com/JhaSourav07/commitpulse.git
cd commitpulse
# Step 2 — Install dependencies
npm install
# Step 3 — Set up your environment variables from the provided template
cp .env.local.example .env.localOpen .env.local and fill in your values. Every variable is documented inside the file. The key ones are:
Why is
GITHUB_TOKENrequired? The GitHub GraphQL API requires authentication. Without a validGITHUB_TOKEN, every request to/api/streakwill return a401 Unauthorizederror and the badge will not render.
Why is
MONGODB_URIoptional? The/api/track-userroute is designed to degrade gracefully. If the variable is missing, it logs a warning to the console and skips the DB write — your local dev experience is completely unaffected.
Generating a Personal Access Token (classic):
Go to GitHub → Settings → Developer settings → Personal access tokens → Tokens (classic) and click Generate new token (classic). Enable the read:user scope, set an expiry, and copy the generated token into your .env.local.
# Step 4 — Start the dev server
npm run devOpen your browser and test your changes:
http://localhost:3000/api/streak?user=YOUR_GITHUB_USERNAME
⚠️ Important: Never commit your.env.localfile or expose yourGITHUB_TOKEN. It is already in.gitignore.
We welcome contributions in three focused pillars. Staying within these areas ensures every PR adds clear, compounding value.
Themes live in lib/svg/themes.ts. A theme is three properties: bg, text, and accent — but the feeling a well-crafted theme creates is worth far more than the 3 lines of code.
What makes a great theme:
| Property | Guidance |
|---|---|
bg |
Should be dark (for the isometric glow to land) or intentionally light with high contrast. Avoid mid-range grays. |
accent |
This is the tower and glow color. It defines the entire personality of the card. Use saturated, vivid hues. |
text |
Must be readable against bg at small sizes. Test at 11px (the label size). |
Theme checklist before submitting:
- Tested against all 5 label/stat text sizes in the SVG
- Looks correct in both GitHub's Dark and Light browser modes
- Has a meaningful, memorable name (e.g.,
aurora,synthwave,obsidian) - Added to the theme table in
README.md
The isometric renderer lives in lib/svg/generator.ts. This is where the 3D tower geometry, glow filters, and animations are built.
Ideas we actively want:
- More sophisticated
<feGaussianBlur>filter chains for per-tower glow depth - A radar/sonar ring animation layered over the monolith grid
- Height scaling improvements — the current
Math.min(count * 5, 50)linear scale could be logarithmic for high contributors - Responsive viewBox adjustments for different aspect ratios
Rules for SVG changes:
- All SVG must be pure, self-contained — no external image dependencies
- Animations use native SVG
<animate>— do not introduce JavaScript-driven animations - Test the output SVG in SVG Viewer before submitting
- Do not increase the
width/heightattributes beyond600x420without a strong reason - All new visual data elements must include a descriptive
<title>tag — accessibility (a11y) is non-negotiable for an elite builder community
The accuracy engine lives in utils/time.ts and lib/calculate.ts.
Problems worth solving:
- User-configurable timezone offsets (e.g.,
?tz=Asia/Kolkata) so the "today" boundary reflects the user's local day, not UTC - Edge case: contributors who span the UTC midnight window and see their streak reset prematurely
- The grace period logic in
calculate.tscould be extended to be configurable (e.g.,?grace=2for 2-day grace)
Rules for logic changes:
- All logic changes must be backward-compatible (no breaking the default behavior)
- Include a code comment explaining why the logic works, not just what it does
- If you add a new URL parameter, document it in
README.md's parameter table
CommitPulse uses a custom, lightweight GitHub Actions automation system to manage issues fairly. This ensures that everyone (especially during events like GSSoC) gets a chance to contribute and prevents "issue hoarding".
Important
The Golden Rule: You can only be assigned to ONE open issue at a time. Finish it or unassign yourself before claiming another.
To maintain high quality in our codebase, we use structured Issue Templates when opening new issues:
- 🐛 Bug Report Template: For reporting visual glitches, API errors, or unexpected behavior.
- ✨ Feature Request Template: For suggesting new isometric monolith designs, themes, or time/accuracy improvements.
By using these templates, you provide maintainers with clear details and context. Since you authored the issue, you can immediately claim it for yourself by commenting /claim!
To help maintainers keep the repository organized and prevent multiple contributors from working on the same problem, we have an automated Semantic Duplicate Detector workflow in place:
- AI-Powered Matching: A custom GitHub Action uses the Google Gemini API (
gemini-embedding-001) to generate text embeddings for all open issues (analyzing the title and body). - Cosine Similarity Scan: The detector compares issues pairwise. If the semantic similarity between a new issue and an older issue exceeds 85%, it flags them.
- Automatic Flagging: The bot will post a friendly alert comment on the newer issue pointing to the older issue, and apply a
possible-duplicatelabel. - What this means for contributors: Before starting to work on an issue, check if the duplicate detection bot has flagged it. If it is indeed a duplicate of an existing open issue, we encourage you to collaborate on or contribute to the original issue instead of creating a duplicate.
Our automation runs entirely through issue comments. Here is how you interact with it:
| Command | Who Can Use It? | What It Does |
|---|---|---|
/claim |
Issue Author Only | Self-assigns the issue to you (only if you created it). |
/addlabel <label1> <label2> |
Anyone | Adds labels to the issue (e.g. /addlabel frontend bug). |
/unassign @username |
Maintainers Only | Removes the assignee from an issue. |
/assign @username |
Maintainers Only | Manually assigns someone to an issue. |
To keep the project moving, assignments are not permanent.
- The 3-Day Rule: If an issue has an assignee but sees no activity for 3 days, our automated background job will remove the assignment.
- What counts as activity? Posting a comment, opening a linked PR, or a maintainer adding a label.
- Why? It frees up stale issues so other active contributors can pick them up. If your issue expires, you can always
/claimit again if it's still available!
- Create a new issue describing the bug or feature request you want to work on using our Structured Issue Templates (or find an open issue you authored).
- Comment
/claimon the issue to lock it in. - Need labels? Comment
/addlabel good-first-issue(labels must already exist in the repo). - Work on your code and submit a PR within 3 days to avoid expiry.
- Once your PR is merged and the issue is closed, you can create and
/claimyour next one!
If the bot rejects your command, check these common scenarios:
- "Commands cannot be used on closed issues": You cannot claim, assign, or unassign on closed issues. Find an open one!
- "You already have an active assigned issue": You must finish your current task. If you're stuck, ask a maintainer to
/unassignyou from the old one. - "This issue is already assigned to @username": Be faster next time! Look for issues without assignees.
- "Only the author of this issue can claim it": You tried to
/claiman issue you did not create. You can only claim issues that you authored. - "The following label(s) do not exist": You can only add existing repo labels. The bot will reply with a list of valid labels you can use.
- "You don't have permission": You tried to use
/assignor/unassign. Please use/claiminstead.
Use the following format: type/short-description
| Branch Type | Example |
|---|---|
| New theme | feat/theme-aurora |
| SVG improvement | feat/tower-glow-filter |
| Bug fix | fix/streak-grace-period |
| Timezone work | fix/utc-midnight-edge-case |
| Documentation | docs/readme-update |
| Refactor | refactor/generator-cleanup |
Write atomic commits — one logical change per commit. Follow the Conventional Commits standard:
type(scope): short description in lowercase
# Examples:
feat(themes): add aurora preset with teal-pink palette
fix(calculate): handle grace period when today has zero contributions
docs(readme): add aurora theme to parameter table
refactor(generator): extract tower path builder into helper function
Types: feat, fix, docs, refactor, chore, test
One commit should do one thing. A PR with 15 commits that all say "update" will be asked to be squashed before merging.
- Fork and Star the repository and create your branch off
main - Make your changes following the pillar guidelines above
- Test locally — verify the SVG renders correctly at
localhost:3000/api/streak?user=YOUR_USERNAME - Open a PR with the following template filled out:
## Description
Fixes # (issue number)
## Pillar
- [ ] 🎨 Pillar 1 — New Theme Design
- [ ] 📐 Pillar 2 — Geometric SVG Improvement
- [ ] 🕐 Pillar 3 — Timezone Logic Optimization
- [ ] 🛠️ Other (Bug fix, refactoring, docs)
## Visual Preview
## Checklist before requesting a review:
- [ ] I have read the `CONTRIBUTING.md` file.
- [ ] I have tested these changes locally (`localhost:3000/api/streak?user=YOUR_USERNAME`).
- [ ] I have run `npm run format` and `npm run lint` locally and resolved all errors (CI will fail otherwise).
- [ ] My commits follow the Conventional Commits format (e.g., `feat(themes): ...`, `fix(calculate): ...`).
- [ ] I have updated `README.md` if I added a new theme or URL parameter.
- [ ] I have started the repo.
- [ ] I have made sure that i have only one commit to merge in this PR.
- [ ] The SVG output matches the CommitPulse "premium quality" aesthetic standard (no raw elements, smooth animations, correct fonts).
- [ ] (Recommended) I joined the CommitPulse Discord server for faster collaboration, mentorship, and PR support.PRs without a visual preview for any SVG-touching changes will be asked for one before review.
CommitPulse enforces code quality using ESLint (correctness & TypeScript rules), Prettier (consistent formatting), and Vitest (unit and integration testing). All of these run automatically in CI on every PR — there are no exceptions.
Run these three commands locally before you open a PR:
# 1. Auto-format all files to match the project's Prettier config
npm run format
# 2. Check for any remaining linting errors
npm run lint
# 3. Ensure all tests pass
npm run testFix every error before pushing. If you add new logic or features, you are expected to write tests for them.
We use Vitest alongside React Testing Library for our test suite.
- File Naming: Test files must be co-located with the code they test and end in
.test.tsor.test.tsx(e.g.,lib/calculate.test.ts). - Unit Tests: All core utility and calculation functions (like streak counting or timezone logic) must have exhaustive unit tests covering edge cases (zero contributions, grace periods, leap years).
- Component Tests: UI components must verify correct rendering, prop handling, and accessibility. We mock animation libraries (like
framer-motion) to keep DOM tests stable. - API Tests: API routes must be tested to ensure correct status codes, caching headers, and parameter validation. External network calls (like the GitHub GraphQL API) must be mocked using
vi.spyOn(global, 'fetch')so tests are fast, deterministic, and run offline. For routes that depend on optional environment variables (likeMONGODB_URIfor/api/track-user), write tests for both the bypass path (env var absent) and the live path (env var present with mocked DB). - Humanic Comments: Comments in test files should explain why a test exists or what specific edge-case it covers, rather than just repeating what the code does line-by-line.
🚨 GitHub Actions CI Gate Our CI pipeline runs
npm run lint,npm run format --check, andnpm run testautomatically on every pull request. If your code fails any check, the PR will be blocked from merging until the issues are resolved. There is no way to bypass this gate — so run the commands locally first and save yourself the round-trip.
Key style rules:
- All functions must have explicit TypeScript return types
- Use the
BadgeParams,StreakStats, andBadgeThemeinterfaces fromtypes/index.ts— never useany; create a typed interface for the data shape instead - SVG strings in
generator.tsshould remain readable — don't minify or compress them inline - Comments should explain intent, not repeat the code.
// Calculate streakis useless.// Grace period: a streak survives a missed day to handle timezonesis valuable.
CommitPulse is a project built by a first-year developer for the Web3 and open-source community. That means this is a space where learning is celebrated, not hidden.
- Ask questions freely. Open a GitHub Discussion or comment on an Issue.
- Teach, don't gatekeep. If you see a mistake in someone's PR, explain why it's wrong and how to fix it.
- Ship complete work. Half-done PRs stall. If you start something, try to bring it to a mergeable state.
- Credit others. If your implementation is inspired by another project, say so in your PR description or code comment.
Check the open issues tagged:
good first issue— Beginner-friendlytheme-request— Design contributionssvg-enhancement— Geometric improvements
Thank you for contributing. Every PR — no matter the size — makes CommitPulse better for every developer who uses it.
— Sourav Jha, Maintainer