12 KiB
Contributing to Changemaker Lite
Thank you for your interest in contributing to Changemaker Lite! This guide will help you get started with contributing code, documentation, bug reports, and feature requests.
Welcome!
Changemaker Lite is an open-source political campaign platform built by volunteers for organizers. We welcome contributions from developers, designers, writers, and community organizers of all experience levels.
Our mission: Provide free, self-hosted tools for grassroots political campaigns to compete with well-funded opponents.
Ways to Contribute
1. Code Contributions
Help build new features or fix bugs in:
- Backend API (TypeScript + Express + Prisma)
- Admin Frontend (React + Vite + Ant Design)
- Media API (TypeScript + Fastify + Drizzle)
- Infrastructure (Docker, Nginx, PostgreSQL, Redis)
→ Development Setup Guide{ .md-button .md-button--primary }
2. Documentation
Improve guides, tutorials, and API documentation:
- User guides - Help organizers use the platform
- Developer docs - API reference, architecture guides
- Tutorials - Step-by-step walkthroughs
- Translations - Localize docs for other languages
→ Documentation Guide{ .md-button }
3. Bug Reports
Found a bug? Help us fix it:
- Search existing issues first
- Provide clear reproduction steps
- Include error messages and logs
- Test on latest version
→ Report a Bug{ .md-button }
4. Feature Requests
Suggest new features or enhancements:
- Check roadmap first
- Describe the use case
- Explain why it's valuable
- Consider implementation complexity
→ Request a Feature{ .md-button }
5. Testing
Help test new features and releases:
- Test beta releases on staging
- Verify bug fixes
- Test migration procedures
- Report edge cases
6. Community Support
Help other users:
- Answer questions in Discussions
- Share your setup experiences
- Write blog posts or tutorials
- Present at community calls
7. Design
Improve user experience:
- UI/UX design mockups
- User flow improvements
- Accessibility enhancements
- Mobile responsiveness
Code of Conduct
Changemaker Lite is committed to providing a welcoming and inclusive environment for all contributors.
Our values:
- Respect: Treat everyone with kindness and professionalism
- Inclusivity: Welcome contributors from all backgrounds
- Collaboration: Work together constructively
- Constructive feedback: Focus on improvement, not criticism
→ Full Code of Conduct{ .md-button }
Unacceptable behavior:
- Harassment, discrimination, or hate speech
- Personal attacks or trolling
- Publishing private information
- Spam or self-promotion
Enforcement: Violations will result in warnings, temporary bans, or permanent bans depending on severity.
Reporting: Email conduct@cmlite.org to report violations confidentially.
Getting Started
Prerequisites
Before contributing code, ensure you have:
- Node.js 20+ installed
- Docker Desktop (or Docker + Docker Compose)
- Git for version control
- Code editor (VSCode recommended)
- GitHub account for pull requests
Quick Start
- Fork the repository on GitHub
- Clone your fork locally
- Set up development environment (guide)
- Find an issue to work on
- Create a branch for your changes
- Make your changes with tests
- Submit a pull request (guide)
Finding Issues to Work On
Good first issues: Look for issues tagged good-first-issue in GitHub Issues.
Help wanted: Issues tagged help-wanted need contributors.
By skill level:
beginner- Simple fixes, documentationintermediate- Feature enhancements, refactoringadvanced- Architecture changes, performance optimization
By area:
backend- API, database, servicesfrontend- React components, UI/UXinfrastructure- Docker, Nginx, deploymentdocumentation- Guides, tutorials, API docs
→ Browse Issues{ .md-button }
Contribution Workflow
1. Claim an Issue
Before starting work:
- Comment on the issue: "I'd like to work on this"
- Wait for assignment: Maintainer will assign you
- Ask questions: Clarify requirements before coding
!!! tip "Avoid Duplicate Work" Always check if someone is already assigned before starting work.
2. Create a Branch
# Update main branch
git checkout main
git pull upstream main
# Create feature branch
git checkout -b feature/campaign-export
# Or for bug fixes
git checkout -b fix/geocoding-error
Branch naming:
feature/description- New featuresfix/description- Bug fixesdocs/description- Documentationrefactor/description- Code refactoringtest/description- Test additions
3. Make Changes
Follow our coding standards:
- TypeScript: Strict mode, type all functions
- ESLint: Run
npm run lintbefore committing - Prettier: Auto-format with
npm run format - Tests: Add tests for new features
- Comments: Document complex logic
// Good: Type-safe function with comments
/**
* Geocodes an address using the specified provider.
* Falls back to next provider if the first fails.
*
* @param address - Full address string
* @param provider - Geocoding provider (default: nominatim)
* @returns Promise resolving to { lat, lng, quality }
*/
async function geocodeAddress(
address: string,
provider: GeocodingProvider = 'nominatim'
): Promise<GeocodingResult> {
// Implementation
}
4. Test Your Changes
# Backend tests
cd api && npm test
# Frontend tests
cd admin && npm test
# Type checking
cd api && npx tsc --noEmit
cd admin && npx tsc --noEmit
# Linting
cd api && npm run lint
cd admin && npm run lint
# Integration tests
docker compose up -d
./scripts/test-integration.sh
5. Commit Your Changes
Commit message format (Conventional Commits):
type(scope): short description
Longer description (optional)
Fixes #123
Types:
feat- New featurefix- Bug fixdocs- Documentationstyle- Formatting, whitespacerefactor- Code restructuringtest- Test additionschore- Build, tooling
Examples:
feat(campaigns): add campaign export to CSV
Adds a new export button to the campaigns page that downloads
all campaigns as a CSV file.
Fixes #456
---
fix(geocoding): handle null responses from Nominatim
Prevents crash when Nominatim returns empty result for
invalid addresses.
Fixes #789
---
docs(api): document campaign endpoints
Adds comprehensive API documentation for all campaign endpoints
including request/response examples.
6. Push and Create Pull Request
# Push to your fork
git push origin feature/campaign-export
# Create pull request on GitHub
# Fill out the PR template
→ Pull Request Guidelines{ .md-button }
7. Code Review
After submitting your PR:
- Automated checks run (lint, tests, build)
- Maintainer review provides feedback
- Address feedback with new commits
- Request re-review after changes
- Merge after approval
Be patient: Reviews may take 1-3 business days. If no response after 5 days, politely ping the maintainer.
Development Guidelines
Code Style
TypeScript:
// Use interfaces for object shapes
interface Campaign {
id: string;
title: string;
slug: string;
active: boolean;
}
// Use types for unions/aliases
type SupportLevel = 'STRONG_SUPPORT' | 'SUPPORT' | 'UNDECIDED' | 'OPPOSED' | 'STRONG_OPPOSED';
// Prefer async/await over promises
async function getCampaigns(): Promise<Campaign[]> {
const campaigns = await prisma.campaign.findMany();
return campaigns;
}
React:
// Use functional components
const CampaignsPage: React.FC = () => {
const [campaigns, setCampaigns] = useState<Campaign[]>([]);
useEffect(() => {
fetchCampaigns();
}, []);
return <Table dataSource={campaigns} />;
};
// Extract reusable components
const CampaignCard: React.FC<{ campaign: Campaign }> = ({ campaign }) => {
return <Card title={campaign.title} />;
};
Prisma:
// Use type-safe queries
const campaigns = await prisma.campaign.findMany({
where: { active: true },
include: { createdBy: true },
orderBy: { createdAt: 'desc' }
});
// Use transactions for multi-step operations
await prisma.$transaction(async (tx) => {
await tx.campaign.update({ where: { id }, data: { active: false } });
await tx.campaignEmail.updateMany({ where: { campaignId: id }, data: { status: 'CANCELLED' } });
});
Testing Guidelines
Unit tests:
// api/src/modules/campaigns/campaigns.service.test.ts
describe('CampaignService', () => {
it('should create campaign with valid data', async () => {
const campaign = await campaignService.create({
title: 'Test Campaign',
slug: 'test-campaign',
createdByUserId: 'user-id'
});
expect(campaign).toHaveProperty('id');
expect(campaign.title).toBe('Test Campaign');
});
it('should throw error for duplicate slug', async () => {
await expect(
campaignService.create({ title: 'Test', slug: 'existing', createdByUserId: 'user-id' })
).rejects.toThrow('Slug already exists');
});
});
Integration tests:
// api/tests/campaigns.integration.test.ts
describe('Campaigns API', () => {
it('GET /api/influence/campaigns returns campaigns', async () => {
const response = await request(app)
.get('/api/influence/campaigns')
.set('Authorization', `Bearer ${adminToken}`);
expect(response.status).toBe(200);
expect(response.body.success).toBe(true);
expect(Array.isArray(response.body.data)).toBe(true);
});
});
Communication Channels
GitHub
- Issues: Bug reports, feature requests
- Discussions: General questions, ideas
- Pull Requests: Code contributions
- General: hello@cmlite.org
- Security: security@cmlite.org
- Code of Conduct: conduct@cmlite.org
Community Calls
- Monthly Contributors Call: First Tuesday of month, 7pm UTC
- Quarterly Community Call: Last Friday of quarter, 6pm UTC
→ Join Calls{ .md-button }
Recognition
We appreciate all contributors! Your name will be:
- Added to CONTRIBUTORS.md after first merged PR
- Listed in release notes for significant contributions
- Featured on website for major features
- Invited to community calls as a contributor
Hall of Fame
Top Contributors (all time):
- @contributor1 - 234 commits
- @contributor2 - 189 commits
- @contributor3 - 156 commits
License
By contributing to Changemaker Lite, you agree that your contributions will be licensed under the MIT License.
This means:
- Your code can be used by anyone
- Attribution is required (copyright notice)
- No warranty is provided
See LICENSE for full terms.
Questions?
- Need help getting started? Ask in Discussions
- Have a question about an issue? Comment on the issue
- Stuck on development setup? Check Development Setup Guide
- Want to chat? Join our monthly contributors call
Related Documentation
- Code of Conduct - Community standards
- Development Setup - Environment setup
- Pull Request Guidelines - PR process
- Roadmap - Future plans
Next Steps
Ready to contribute?
- Read the Code of Conduct - Understand community standards
- Set up your environment - Install dependencies
- Find an issue - Pick something to work on
- Submit your first PR - Make your contribution
Thank you for contributing to Changemaker Lite! Together, we're building tools for democratic change.