First off, thank you for considering contributing to Crypto Data Aggregator! 🎉
This document provides guidelines and steps for contributing. Following these guidelines helps communicate that you respect the time of the developers managing and developing this open source project.
- Code of Conduct
- Getting Started
- Development Workflow
- Code Style Guide
- Testing
- Reporting Bugs
- Suggesting Features
By participating in this project, you are expected to uphold our Code of Conduct:
- Be respectful and inclusive
- Be patient with newcomers
- Focus on what is best for the community
- Show empathy towards other community members
Before you begin, ensure you have the following installed:
-
Fork the repository by clicking the "Fork" button on GitHub
-
Clone your fork locally:
git clone https://github.com/YOUR_USERNAME/crypto-data-aggregator.git cd crypto-data-aggregator -
Add the upstream remote:
git remote add upstream https://github.com/nirholas/crypto-data-aggregator.git
-
Verify remotes:
git remote -v # origin https://github.com/YOUR_USERNAME/crypto-data-aggregator.git (fetch) # origin https://github.com/YOUR_USERNAME/crypto-data-aggregator.git (push) # upstream https://github.com/nirholas/crypto-data-aggregator.git (fetch) # upstream https://github.com/nirholas/crypto-data-aggregator.git (push)
Quick Setup (Recommended):
./scripts/setup.shManual Setup:
# Install dependencies
npm install
# Set up Husky hooks
npm run prepare
# Start development server
npm run devThe application will be available at http://localhost:3000.
Use descriptive branch names following this pattern:
<type>/<issue-number>-<short-description>
Types: | Type | Description | |------|-------------| | feature | New feature or enhancement |
| fix | Bug fix | | docs | Documentation only changes | | refactor | Code refactoring | |
test | Adding or updating tests | | chore | Maintenance tasks | | style | Code
style/formatting changes | | perf | Performance improvements |
Examples:
feature/123-add-portfolio-export
fix/456-chart-rendering-issue
docs/789-update-api-docs
refactor/101-simplify-price-utilsWe follow Conventional Commits specification.
Format:
<type>(<scope>): <subject>
[optional body]
[optional footer(s)]
Types: | Type | Description | |------|-------------| | feat | A new feature | | fix | A bug
fix | | docs | Documentation only changes | | style | Changes that don't affect code meaning
(formatting, etc.) | | refactor | Code change that neither fixes a bug nor adds a feature | |
perf | Performance improvement | | test | Adding missing tests or correcting existing tests | |
chore | Changes to build process or auxiliary tools | | ci | Changes to CI configuration files
and scripts | | revert | Reverts a previous commit |
Scopes (optional):
api- API routesui- UI componentscharts- Chart componentsportfolio- Portfolio featurewatchlist- Watchlist featuredefi- DeFi analyticsmarket- Market datadeps- Dependencies
Examples:
feat(portfolio): add CSV export functionality
fix(charts): resolve tooltip positioning on mobile
docs: update installation instructions
refactor(api): simplify market data fetching logic
test(portfolio): add unit tests for calculations
chore(deps): update next.js to v16.2.0Rules:
- Use lowercase for type and scope
- Use imperative mood in subject ("add" not "added" or "adds")
- Don't end the subject with a period
- Keep subject under 72 characters
- Use the body to explain what and why (not how)
-
Update your fork:
git fetch upstream git checkout main git merge upstream/main
-
Create a new branch:
git checkout -b feature/123-your-feature-name
-
Make your changes and commit following the commit message format
-
Run checks before pushing:
npm run check-all # Or individually: npm run lint npm run build npm run test:run -
Push to your fork:
git push origin feature/123-your-feature-name
-
Open a Pull Request:
- Go to the original repository on GitHub
- Click "New Pull Request"
- Select your branch
- Fill out the PR template completely
- Link any related issues
-
Address review feedback:
- Make requested changes
- Push additional commits
- Re-request review when ready
- Write clean, readable, and maintainable code
- Follow DRY (Don't Repeat Yourself) principles
- Keep functions small and focused
- Use meaningful variable and function names
- Use TypeScript for all new code
- Define proper types - avoid
anywhen possible - Use interfaces for object shapes
- Export types that might be reused
// ✅ Good
interface CoinData {
id: string;
name: string;
price: number;
change24h: number;
}
function formatPrice(price: number): string {
return new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD',
}).format(price);
}
// ❌ Avoid
function formatPrice(price: any) {
return '$' + price;
}- Use functional components with hooks
- Use named exports for components
- Keep components focused and composable
- Extract complex logic into custom hooks
// ✅ Good
export function PriceDisplay({ price, change }: PriceDisplayProps) {
const formattedPrice = useMemo(() => formatPrice(price), [price]);
return (
<div className="price-display">
<span>{formattedPrice}</span>
<PriceChange value={change} />
</div>
);
}
// ❌ Avoid
export default function(props) {
// Large component with mixed concerns
}- Use Tailwind CSS utility classes
- Extract repeated patterns into components
- Use semantic class names when custom CSS is needed
- Keep responsive design in mind
src/
├── app/ # Next.js app router pages
├── components/ # Reusable UI components
├── lib/ # Utility functions and services
└── types/ # TypeScript type definitions (if needed)
| Item | Convention | Example |
|---|---|---|
| Components | PascalCase | PriceChart.tsx |
| Utilities | camelCase | formatPrice.ts |
| Constants | SCREAMING_SNAKE_CASE | MAX_RETRY_COUNT |
| Types/Interfaces | PascalCase | CoinData |
| CSS classes | kebab-case | price-display |
We use Vitest for testing.
# Run all tests
npm run test:run
# Run tests in watch mode
npm run test:watch
# Run tests with UI
npm run test:ui
# Run tests with coverage
npm run test:coverage- Place test files next to the code they test:
component.tsx→component.test.tsx - Or use
__tests__directories for grouping - Write descriptive test names
- Test both happy paths and edge cases
import { describe, it, expect } from 'vitest';
import { formatPrice } from './formatPrice';
describe('formatPrice', () => {
it('formats positive prices correctly', () => {
expect(formatPrice(1234.56)).toBe('$1,234.56');
});
it('handles zero', () => {
expect(formatPrice(0)).toBe('$0.00');
});
it('handles very small numbers', () => {
expect(formatPrice(0.00001234)).toBe('$0.00001234');
});
});Found a bug? Please use the Bug Report template to report it.
Before submitting:
- Search existing issues to avoid duplicates
- Gather steps to reproduce
- Note your environment (browser, OS, etc.)
Have an idea? Please use the Feature Request template.
Before submitting:
- Search existing issues to avoid duplicates
- Consider if it fits the project scope
- Think about implementation details
Feel free to open a Question issue if you need help!
Thank you for contributing! 🚀