Thank you for your interest in contributing to our project! Together, we can build the best expense management solution.
Before contributing, ensure you have:
- π’ Node.js 18+ installed
- π¦ npm or yarn package manager
- ποΈ Supabase account for testing
- π― Git for version control
- π» Code editor (VS Code recommended)
-
π΄ Fork the Repository
# Click the "Fork" button on GitHub -
π₯ Clone Your Fork
git clone https://github.com/YOUR_USERNAME/expense-management-system.git cd expense-management-system -
π Add Upstream Remote
git remote add upstream https://github.com/ORIGINAL_OWNER/expense-management-system.git
-
π¦ Install Dependencies
npm run install-all
-
βοΈ Setup Environment
cp Backend/.env.example Backend/.env cp Frontend/.env.example Frontend/.env # Configure your Supabase credentials -
ποΈ Initialize Database
cd Backend && npm run init-db
-
π Start Development
cd .. && npm run dev
Before submitting a bug report:
- β Check existing issues to avoid duplicates
- π Search closed issues for previous solutions
- π Gather relevant information about your environment
Bug Report Template:
## π Bug Description
A clear description of what the bug is.
## π Steps to Reproduce
1. Go to '...'
2. Click on '...'
3. Scroll down to '...'
4. See error
## β
Expected Behavior
What you expected to happen.
## πΈ Screenshots
If applicable, add screenshots.
## π₯οΈ Environment
- OS: [e.g. Windows 11]
- Browser: [e.g. Chrome 91]
- Node.js: [e.g. 18.0.0]
- npm: [e.g. 8.0.0]Feature Request Template:
## π Feature Description
A clear description of the feature you'd like to see.
## π― Problem Solved
What problem does this feature solve?
## π Proposed Solution
How would you like this feature to work?
## π Alternative Solutions
Any alternative solutions you've considered.
## β Additional Context
Any other context or screenshots.# Feature branches
feature/expense-category-filtering
feature/receipt-ocr-enhancement
# Bug fix branches
bugfix/login-redirect-issue
bugfix/currency-conversion-error
# Documentation updates
docs/api-documentation-update
docs/setup-guide-improvementFollow the Conventional Commits specification:
# Feature commits
feat(auth): add OAuth2 integration
feat(expenses): implement bulk expense upload
# Bug fixes
fix(api): resolve currency conversion error
fix(ui): correct responsive layout issues
# Documentation
docs(readme): update installation instructions
docs(api): add endpoint documentation
# Refactoring
refactor(utils): optimize date formatting functions
refactor(components): simplify expense form logic
# Performance improvements
perf(db): optimize expense query performance
perf(ui): reduce bundle size with code splitting
# Tests
test(auth): add unit tests for login flow
test(expenses): add integration tests for CRUD operations-
π Sync with Upstream
git fetch upstream git checkout main git merge upstream/main
-
πΏ Create Feature Branch
git checkout -b feature/your-feature-name
-
π» Make Your Changes
- Follow coding standards
- Add tests for new features
- Update documentation
- Ensure all tests pass
-
β Test Your Changes
# Run frontend tests cd Frontend && npm test # Run backend tests cd Backend && npm test # Run full application npm run dev
-
π€ Submit Pull Request
- Use descriptive title and description
- Reference related issues
- Include screenshots for UI changes
- Mark as draft if work in progress
Pull Request Template:
## π Description
Brief description of changes made.
## π Related Issues
Fixes #(issue number)
## π§ͺ Testing
- [ ] Unit tests pass
- [ ] Integration tests pass
- [ ] Manual testing completed
- [ ] Cross-browser testing done
## πΈ Screenshots
[Include screenshots for UI changes]
## β
Checklist
- [ ] Code follows project standards
- [ ] Self-review completed
- [ ] Documentation updated
- [ ] Tests added/updated
- [ ] No breaking changes// β
Good: Use descriptive names
interface UserExpenseData {
amount: number;
currency: string;
category: ExpenseCategory;
submittedAt: Date;
}
// β Bad: Vague naming
interface Data {
amt: number;
cur: string;
cat: any;
date: any;
}// β
Good: Functional component with proper typing
interface ExpenseFormProps {
onSubmit: (expense: Expense) => Promise<void>;
initialData?: Partial<Expense>;
isLoading?: boolean;
}
const ExpenseForm: React.FC<ExpenseFormProps> = ({
onSubmit,
initialData,
isLoading = false
}) => {
// Component logic here
};
export default ExpenseForm;// β
Good: Consistent error handling
export async function createExpense(req, res) {
try {
const { amount, currency, category } = req.body;
// Validation
if (!amount || !currency || !category) {
return res.status(400).json({
error: 'Missing required fields',
details: { amount, currency, category }
});
}
const expense = await expenseService.create({
...req.body,
userId: req.user.id
});
res.status(201).json({ success: true, data: expense });
} catch (error) {
console.error('Create expense error:', error);
res.status(500).json({
error: 'Internal server error',
message: error.message
});
}
}/* β
Good: Use Tailwind utility classes */
<div className="flex items-center justify-between p-4 bg-white rounded-lg shadow-md">
<h2 className="text-xl font-semibold text-gray-800">Expense Details</h2>
<button className="px-4 py-2 text-white bg-blue-600 rounded hover:bg-blue-700">
Submit
</button>
</div>
/* β
Good: Custom CSS when needed */
.expense-chart {
@apply w-full h-64 p-4 bg-gray-50 rounded-lg;
}
.expense-chart canvas {
@apply max-w-full max-h-full;
}// Unit test example
import { render, screen, fireEvent } from '@testing-library/react';
import { ExpenseForm } from './ExpenseForm';
describe('ExpenseForm', () => {
it('should submit form with valid data', async () => {
const mockOnSubmit = jest.fn();
render(<ExpenseForm onSubmit={mockOnSubmit} />);
fireEvent.change(screen.getByLabelText(/amount/i), {
target: { value: '100.50' }
});
fireEvent.click(screen.getByRole('button', { name: /submit/i }));
await waitFor(() => {
expect(mockOnSubmit).toHaveBeenCalledWith({
amount: 100.50,
// ... other expected data
});
});
});
});// API test example
import request from 'supertest';
import app from '../src/server';
describe('POST /api/expenses', () => {
it('should create expense with valid data', async () => {
const expenseData = {
amount: 100.50,
currency: 'USD',
category: 'meals',
description: 'Team lunch'
};
const response = await request(app)
.post('/api/expenses')
.set('Authorization', `Bearer ${validToken}`)
.send(expenseData)
.expect(201);
expect(response.body.success).toBe(true);
expect(response.body.data.amount).toBe(100.50);
});
});/**
* Calculates the total expense amount in the company's base currency
*
* @param expenses - Array of expense records
* @param baseCurrency - Company's base currency code (e.g., 'USD')
* @param exchangeRates - Current exchange rates object
* @returns Promise resolving to total amount in base currency
*
* @example
* ```typescript
* const total = await calculateTotalInBaseCurrency(
* expenses,
* 'USD',
* { EUR: 1.1, GBP: 1.3 }
* );
* ```
*/
export async function calculateTotalInBaseCurrency(
expenses: Expense[],
baseCurrency: string,
exchangeRates: ExchangeRates
): Promise<number> {
// Implementation here
}## POST /api/expenses
Creates a new expense record.
### Request Body
```json
{
"amount": 100.50,
"currency": "USD",
"category": "meals",
"description": "Team lunch",
"expenseDate": "2023-12-01"
}Success (201)
{
"success": true,
"data": {
"id": "uuid",
"amount": 100.50,
"status": "pending",
"createdAt": "2023-12-01T10:00:00Z"
}
}Error (400)
{
"error": "Validation failed",
"details": {
"amount": "Amount is required"
}
}
---
## π **Code Review Guidelines**
### β
**What to Look For**
- **π Security**: No sensitive data exposed
- **π― Performance**: Efficient algorithms and queries
- **π± Accessibility**: Proper ARIA labels and keyboard navigation
- **π§ͺ Tests**: Adequate test coverage
- **π Documentation**: Clear comments and documentation
- **π¨ UI/UX**: Consistent design and user experience
### π¬ **Review Etiquette**
- **π― Be Specific**: Point to exact lines and suggest improvements
- **π‘ Be Constructive**: Offer solutions, not just problems
- **π Be Respectful**: Remember there's a person behind the code
- **π Educate**: Share knowledge and best practices
- **β‘ Be Timely**: Review promptly to maintain momentum
---
## π **Recognition**
### π **Contributor Levels**
| Level | Contributions | Benefits |
|:---:|:---|:---|
| π₯ **Bronze** | 1-5 PRs merged | Listed in contributors |
| π₯ **Silver** | 6-15 PRs merged | Special badge + early access |
| π₯ **Gold** | 16+ PRs merged | Maintainer consideration |
### π **Hall of Fame**
We recognize outstanding contributors in our:
- π **Monthly Contributors** - Most active contributors
- π **Bug Hunters** - Best bug reports and fixes
- π **Documentation Heroes** - Documentation improvements
- π **Feature Champions** - Best new features
---
## π **Getting Help**
### π¬ **Communication Channels**
- π **Issues**: For bugs and feature requests
- π¬ **Discussions**: For questions and general chat
- π§ **Email**: maintainers@expense-management.com
- π» **Discord**: [Join our server](https://discord.gg/expense-mgmt)
### π **Need Help?**
Don't hesitate to ask for help! We're here to support you:
- π€ **Stuck on setup?** Create a setup help issue
- π **Found a bug?** We'll help you debug it
- π‘ **Have an idea?** Let's discuss implementation
- π§ͺ **Testing issues?** We'll guide you through it
---
<div align="center">
### π **Ready to Contribute?**
*Every contribution, no matter how small, makes a difference!*
[](https://github.com/yourusername/expense-management-system/issues/good-first-issue)
---
**Thank you for making our project better! π**
</div>