Skip to content

Good First Tasks

Goal: Build confidence with low-risk, high-learning-value tasks

Characteristics of Good First Tasks

Small scope - Can complete in < 1 day ✅ Clear requirements - No ambiguity about what to do ✅ Low risk - Won't break production if wrong ✅ High visibility - PR will be reviewed, merged, deployed ✅ Learning value - Touches real code, teaches workflow ✅ Well-documented - Issue has clear description and acceptance criteria

Task Categories

1. Documentation Improvements

Why good: - Low risk (no production code changes) - Immediate value (helps next person) - Learn codebase while documenting - Easy to review

Examples: - Add missing API documentation - Fix typos in comments or docs - Add code examples to README - Document undocumented function - Update outdated getting-started guide

Label: good-first-issue, documentation

Template:

## Task: Add documentation for [Function/Class]

**File**: src/audio/buffer.cpp
**Function**: `allocateBuffer(size_t samples)`

**Current state**: No documentation
**Goal**: Add Doxygen comments explaining:
- What the function does
- Parameters
- Return value
- Example usage

**Acceptance criteria**:
- [ ] Doxygen comments added
- [ ] Example usage included
- [ ] Documentation builds without warnings

2. Code Cleanup

Why good: - Improves codebase quality - Learn coding standards - Touches real code - Low risk

Examples: - Fix linter warnings - Remove commented-out code - Rename poorly-named variables - Extract magic numbers to constants - Apply consistent formatting

Label: good-first-issue, cleanup

Template:

## Task: Extract magic numbers in [File]

**File**: src/audio/processor.cpp
**Lines**: 42, 67, 89

**Issue**: Magic numbers (44100, 512, etc.) hardcoded
**Goal**: Extract to named constants

**Example**:
Before:
```cpp
if (sampleRate > 44100) { ...

After:

constexpr int MAX_SAMPLE_RATE = 44100;
if (sampleRate > MAX_SAMPLE_RATE) { ...

Acceptance criteria: - [ ] All magic numbers extracted - [ ] Constants have descriptive names - [ ] Tests still pass

### 3. Small Bug Fixes

**Why good**:
- Real value (fixes actual bug)
- Learns debugging process
- Requires understanding code
- Clear success criteria (bug is fixed)

**Examples**:
- Fix typo in error message
- Correct off-by-one error
- Add missing null check
- Fix memory leak in small function
- Correct incorrect default value

**Label**: `good-first-issue`, `bug`

**Template**:
```markdown
## Bug: Error message has typo

**File**: src/audio/processor.cpp
**Line**: 123

**Current**: "Sampe rate invalid"
**Should be**: "Sample rate invalid"

**Steps to reproduce**:
1. Pass invalid sample rate to processor
2. See error message

**Acceptance criteria**:
- [ ] Typo fixed
- [ ] Error still triggered correctly
- [ ] Tests pass

4. Add Missing Tests

Why good: - Learn testing framework - Understand code by testing it - Valuable (increases coverage) - Clear scope (test one function)

Examples: - Add test for edge case - Test error handling path - Add missing unit test - Test cross-platform behavior - Add regression test for fixed bug

Label: good-first-issue, testing

Template:

## Task: Add tests for edge cases in [Function]

**File**: src/audio/util.cpp
**Function**: `clamp(value, min, max)`

**Current**: Basic test exists
**Missing**: Edge case tests

**Add tests for**:
- [ ] value < min (should return min)
- [ ] value > max (should return max)
- [ ] value == min (boundary)
- [ ] value == max (boundary)
- [ ] min > max (invalid input, should assert or error)

**Example test**:
```cpp
TEST_CASE("clamp returns min when value below range") {
    REQUIRE(clamp(-5, 0, 10) == 0);
}

Acceptance criteria: - [ ] All edge cases tested - [ ] Tests pass - [ ] Coverage increases

### 5. Simple Features

**Why good**:
- End-to-end feature (design → implement → test)
- Real value (ships to users)
- Confidence builder
- Team visibility

**Examples**:
- Add new parameter to existing processor
- Add simple validation check
- Add logging to key function
- Implement simple utility function
- Add configuration option

**Label**: `good-first-issue`, `feature`

**Template**:
```markdown
## Feature: Add dry/wet mix parameter

**Goal**: Add parameter to blend processed and unprocessed signal

**Implementation**:
1. Add `dryWetMix` parameter (range 0.0 - 1.0)
2. In `process()`:
   - 0.0 = 100% dry (bypass)
   - 1.0 = 100% wet (fully processed)
   - 0.5 = 50/50 blend
3. Formula: `output = dry * (1 - mix) + wet * mix`

**Files to modify**:
- `src/processor.hpp` (add parameter)
- `src/processor.cpp` (implement blending)
- `tests/processor_test.cpp` (add tests)

**Acceptance criteria**:
- [ ] Parameter added and wired up
- [ ] Blending implemented correctly
- [ ] Tests cover 0%, 50%, 100% cases
- [ ] Manual listening test sounds correct
- [ ] Documentation updated

**Estimated time**: 2-4 hours

Creating Good First Issues

Issue Template

---
title: "[GOOD FIRST ISSUE] Brief description"
labels: good-first-issue, [type]
---

## Description
[Clear explanation of what needs to be done]

## Why this matters
[Context on why this is valuable]

## How to approach
[Step-by-step guidance]
1. Step 1
2. Step 2
3. Step 3

## Files to modify
- [ ] File 1 (what to change)
- [ ] File 2 (what to add)
- [ ] File 3 (tests)

## Acceptance criteria
- [ ] Criterion 1
- [ ] Criterion 2
- [ ] Criterion 3

## Resources
- [Link to relevant doc]
- [Example PR doing similar thing]

## Questions?
Feel free to ask in #dev-help or tag @buddy-name

Maintaining a Backlog

Keep 5-10 good first issues ready: - Labeled good-first-issue - Well-documented - Not blocked by other work - Diverse (docs, code, tests)

Review quarterly: - Close stale issues - Create new ones - Update descriptions

What to Avoid

❌ Bad First Tasks

Too vague: - "Improve performance" (where? how?) - "Refactor audio module" (too broad)

Too complex: - "Rewrite DSP engine" (months of work) - "Implement new threading model" (requires deep knowledge)

Too risky: - "Change core audio algorithm" (high risk of breaking) - "Modify state management" (intricate, many dependencies)

Blocked: - "Add feature X" (waiting on architecture decision) - "Fix bug Y" (blocked by dependency update)

Unclear requirements: - "Make UI better" (subjective, no criteria) - "Optimize something" (what? by how much?)

Supporting New Contributors

When they pick a task

Respond quickly:

Great choice! This is a perfect first task. Let me know if you have any
questions as you work through it. Happy to pair program if helpful!

Offer guidance: - Point to relevant docs - Link to similar PRs - Suggest approach (but don't dictate)

When they submit PR

Timely review: - Review within 24 hours (sooner if possible) - First PRs get extra attention

Be encouraging:

Great first PR! Thanks for the contribution. I have a few minor suggestions,
but overall this looks good.

[Feedback]

Don't be discouraged by the feedback - it's how we all learn. Let me know if
anything is unclear!

Be thorough but kind: - Explain the "why" behind feedback - Provide examples - Distinguish blocking vs suggestions

When they merge

Celebrate:

🎉 Congrats on your first merged PR! Welcome to the team!

Want to grab another issue? Here are some good next steps:
- #456 (similar but slightly more complex)
- #789 (different area, good for learning)

Invite to continue: - Suggest next tasks - Invite to team discussions - Recognize contribution publicly

Metrics

Track: - Time to first PR merged (target: < 3 days) - Number of contributors (growth over time) - Good first issues backlog (keep 5-10 ready)

Success: - New contributor merges first PR - They continue contributing - They eventually maintain good first issues

Resources


Remember: Great first tasks make great first contributors!