How to Write a CONTRIBUTING.md That Actually Works: Lessons from Running a 5K-Star Open Source Repo
Your README gets all the love. But the CONTRIBUTING.md? That’s where the real work happens.
I’ve maintained a moderately popular open source project for three years — peaked at 5,200 stars, 150+ forks, and over 500 unique contributors. For the first year, our CONTRIBUTING.md was an afterthought. A few bullet points. A link to the code of conduct. We’d get maybe 2-3 PRs a month, mostly spam or one-line fixes.
Build a Custom AI PR Reviewer with Claude API and GitHub Webhooks — Here’s the Exact Code
Build a Custom AI PR Reviewer with Claude API and GitHub Webhooks — Here’s the Exact Code I’ve… ...
Then we rewrote it from scratch. PRs quadrupled. Time-to-merge dropped by 60%. Here’s exactly what we changed.
Why Most CONTRIBUTING.md Files Fail
Honestly, most are either too vague or too intimidating. They say “feel free to contribute” but give no concrete steps. Or they list 47 rules that scare off first-timers.
Why Outsourcing Software Development in Vietnam Is the Smartest Move for Your Startup (and Your Sanity)
TL;DR: Outsourcing software to Vietnam gives you engineering talent at 60% lower cost than the US, with 95%… ...
We fell into the first trap. Our original file:
markdown
## Contributing
Bug reports and pull requests are welcome. Please follow the code style.
That’s it. People didn’t know where to start. So they didn’t.
The fix? Treat your CONTRIBUTING.md like a developer onboarding document. Every line should answer: “What should I do next?”
The Four Sections That Actually Matter
After testing dozens of formats, we landed on this structure. It’s the one that drove our contributor growth.
1. The “First Timer” Welcome
Right at the top, we added:
markdown
# First time contributing to open source? Start here.
We have issues labeled `good first issue` for you. Read our [Code of Conduct](CODE_OF_CONDUCT.md) first.
If you're stuck, ask in our Discord — we're friendly, I promise.
Why this works? It removes anxiety. We explicitly tell newbies they’re welcome. We also link to issues that are intentionally small (e.g., documentation typos, test additions).
Rhetorical question: Have you ever stared at an open source repo and felt like you were interrupting a private party? That’s the feeling we killed.
2. How to Set Up the Development Environment
Don’t assume people know your stack. We wrote step-by-step commands:
bash
git clone https://github.com/yourorg/yourproject.git
cd yourproject
npm install # or pnpm install
cp .env.example .env
npm run dev
Then we added troubleshooting for common errors (Node version, port conflicts). Include a Docker setup if it’s complex. We saw a 40% reduction in “doesn’t work on my machine” issues after adding this.
3. The “How to Submit a PR” Walkthrough
This is the core. We broke it down into five steps:
- Fork and clone (with `git remote add upstream` commands)
- Create a branch – naming convention: `fix/issue-123` or `feat/description`
- Make your changes – and run `npm run lint` and `npm test`
- Commit messages – we follow Conventional Commits. Example: `fix: resolve timeout in cache layer`
- Open a PR – check that your target branch is `develop` or `main`
We also include a PR checklist in a comment template (via `.github/PULL_REQUEST_TEMPLATE.md`). That single change cut our review cycles in half.
4. Code Review Expectations
We state explicitly: “All PRs require at least one approval. Expect feedback within 48 hours. If you don’t hear back, ping us on Discord.”
Accountability goes both ways. Contributors need to know you’re not ignoring them.
Template: Copy and Adapt This
Here’s the skeleton we use now. It’s public and we’ve seen multiple forks adopt it.
markdown
# Contributing
We love pull requests! Here's how you can help.
## Code of Conduct
Read our [Code of Conduct](CODE_OF_CONDUCT.md). Be excellent to each other.
## Getting Started
1. Fork the repo.
2. Clone your fork: `git clone https://github.com/your-username/project.git`
3. Set up upstream: `git remote add upstream https://github.com/original/project.git`
4. Install dependencies: `npm install`
5. Run tests: `npm test`
6. Create a branch: `git checkout -b feat/your-feature`
## Making Changes
- Keep changes focused. One feature per PR.
- Add tests for new functionality.
- Run linter before committing: `npm run lint`
## Commit Messages
Use [Conventional Commits](https://www.conventionalcommits.org/):
- `feat:` new feature
- `fix:` bug fix
- `docs:` documentation only
- `refactor:` code change that neither fixes a bug nor adds a feature
- `test:` adding missing tests
## Submitting a PR
1. Push your branch: `git push origin feat/your-feature`
2. Open a PR against the `main` branch.
3. Fill out the PR template.
4. Wait for review (usually within 2 business days).
## Need Help?
Join our [Discord](https://discord.gg/example) or tag `@maintainers` in issues.
Important: Keep it under 200 lines. No one reads a novel when they’re trying to contribute.
The Hidden Factor: Localization
We maintain a team in Vietnam (Ho Chi Minh City and Can Tho). Many of our contributors are Vietnamese developers who found our project through conferences or local meetups. We started providing a Vietnamese translation of the CONTRIBUTING.md — just a separate file `CONTRIBUTING.vi.md`. That simple addition brought in dozens of quality PRs from devs who were previously intimidated by English-only docs.
If your project has an international audience, consider even a single translated version. It signals that you want their help.
Measuring What Matters
After the rewrite, we tracked:
| Metric | Before | After (6 months) |
|---|---|---|
| PRs per month | 8 | 34 |
| Average time to first response | 72h | 12h |
| First-time contributor PRs | 2/month | 15/month |
| PRs merged without rework | 30% | 75% |
The biggest surprise? Repeat contributors jumped from 10% to 40%. Because the onboarding felt easier, people came back.
Common Mistakes to Avoid
- Linking to a wiki instead of writing inline. Wiki docs rot. Keep everything in the repo.
- Being overly strict about style guides. Enforce with linters, not human review.
- Forgetting to update the file when the project changes. We broke our own CONTRIBUTING.md twice because we changed our branch strategy and didn’t update the doc. Embarrassing.
Final Thought
Your CONTRIBUTING.md is the front door to your project. Make it welcoming, clear, and actionable. The best open source communities don’t just happen — they’re designed.
We spend months writing code. Take an afternoon to write the guide that gets others to contribute it.
Frequently Asked Questions
Should I require a signed CLA in the CONTRIBUTING.md?
Only if your project needs one (e.g., corporate sponsorship). Otherwise, skip it — it adds friction. Use a simple DCO (Developer Certificate of Origin) instead; GitHub can enforce it automatically.
How do I handle contributions that don’t follow the template?
Close politely with a link to the CONTRIBUTING.md. Example: “Thanks for the PR! Could you please update the commit message to follow our convention? See here.”
Can I use a bot to automate parts of the contribution workflow?
Yes. We use a GitHub Action that automatically adds labels like `needs-triage` and comments with the contribution guide link when a new issue or PR is opened. It saves hours per week.
Do I need to include a code of conduct link in CONTRIBUTING.md?
Absolutely. It’s non-negotiable. Use the Contributor Covenant template. List a clear enforcement contact (e.g., maintainers@yourproject.org).
Related reading: Outsourcing Software Development: The Real Playbook for CTOs and Tech Leaders