Contributing - DigitalHerencia/FleetFusion GitHub Wiki
- Code of Conduct
- Getting Started
- Development Workflow
- Coding Standards
- Testing Guidelines
- Documentation Standards
- Pull Request Process
- Architecture Guidelines
- Security Considerations
By participating in this project, you agree to abide by our Code of Conduct:
- Be respectful: Treat all community members with respect and kindness
- Be inclusive: Welcome newcomers and help them learn
- Be constructive: Provide helpful feedback and criticism
- Be professional: Maintain professional communication in all interactions
Before contributing, ensure you have:
- Node.js 18+ installed
- Git configured with your GitHub account
- Access to the development environment
- Understanding of the Architecture and Getting Started guides
-
Fork and Clone
git clone https://github.com/your-username/fleetfusion-architecture.git cd fleetfusion-architecture
-
Install Dependencies
npm install
-
Environment Setup
cp .env.example .env.local # Fill in your environment variables
-
Database Setup
npm run db:push npm run db:seed
-
Start Development Server
npm run dev
Use descriptive branch names following this pattern:
feature/description-of-feature
fix/description-of-bug-fix
docs/description-of-documentation-change
refactor/description-of-refactor
test/description-of-test-addition
Examples:
feature/driver-compliance-dashboard
fix/load-assignment-validation
docs/api-reference-updates
Follow Conventional Commits specification:
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
Types:
-
feat
: New feature -
fix
: Bug fix -
docs
: Documentation changes -
style
: Code style changes (formatting, etc.) -
refactor
: Code refactoring -
test
: Adding or updating tests -
chore
: Maintenance tasks
Examples:
feat(auth): add multi-factor authentication support
Add MFA support using Clerk's built-in MFA capabilities.
Includes SMS and TOTP authentication methods.
Closes #123
fix(dashboard): resolve metric calculation error
Fixed incorrect calculation of on-time delivery rate
that was caused by timezone handling issues.
Fixes #456
-
Strict Type Safety
// ✅ Good: Explicit types interface DashboardMetrics { activeVehicles: number; onTimeDeliveryRate: number; } // ❌ Avoid: Any types const data: any = fetchData();
-
Use Interfaces for Object Shapes
// ✅ Good: Interface for component props interface LoadCardProps { load: Load; onStatusChange: (id: string, status: LoadStatus) => void; }
-
Zod for Runtime Validation
// ✅ Good: Runtime validation with Zod const createLoadSchema = z.object({ origin: z.string().min(1), destination: z.string().min(1), weight: z.number().positive(), });
-
Server Components by Default
// ✅ Good: Server Component (default) export default async function DashboardPage() { const data = await fetchDashboardData(); return <Dashboard data={data} />; } // Only use 'use client' when necessary 'use client'; export function InteractiveChart() { const [data, setData] = useState([]); // Interactive logic here }
-
Component Organization
components/ ├── ui/ # Generic, reusable components ├── dashboard/ # Dashboard-specific components ├── auth/ # Authentication components └── shared/ # Shared business components
-
Props Interface Pattern
interface ComponentProps { // Required props first title: string; data: DataType[]; // Optional props after className?: string; onAction?: () => void; }
-
Tailwind CSS Conventions
// ✅ Good: Logical grouping and responsive design <div className=" flex items-center justify-between p-4 rounded-lg border hover:bg-gray-50 md:p-6 dark:border-gray-700 dark:hover:bg-gray-800 ">
-
CSS Custom Properties
/* Use design tokens */ .custom-component { background: hsl(var(--background)); color: hsl(var(--foreground)); border-radius: var(--radius); }
-
Component Variants
// Use class-variance-authority for component variants const buttonVariants = cva( "inline-flex items-center justify-center rounded-md", { variants: { variant: { default: "bg-primary text-primary-foreground", destructive: "bg-destructive text-destructive-foreground", }, size: { default: "h-10 px-4 py-2", sm: "h-9 rounded-md px-3", }, }, } );
-
Prisma Schema Conventions
model Organization { id String @id @default(cuid()) clerkId String @unique @map("clerk_id") name String createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") // Relations users User[] vehicles Vehicle[] @@map("organizations") }
-
Query Optimization
// ✅ Good: Include only necessary relations const load = await prisma.load.findUnique({ where: { id }, include: { driver: { select: { name: true, phone: true } }, vehicle: { select: { unitNumber: true } }, }, }); // ❌ Avoid: Over-fetching data const load = await prisma.load.findUnique({ where: { id }, include: { driver: true, // Fetches all driver fields vehicle: true, // Fetches all vehicle fields }, });
-
Test File Organization
__tests__/ ├── components/ # Component tests ├── lib/ # Utility function tests ├── app/ # Page and API route tests └── e2e/ # End-to-end tests
-
Unit Test Example
// components/__tests__/MetricCard.test.tsx import { render, screen } from '@testing-library/react'; import { MetricCard } from '../MetricCard'; describe('MetricCard', () => { it('displays metric value correctly', () => { render( <MetricCard title="Active Vehicles" value={42} change={{ value: 5, type: 'increase', timeframe: 'last month' }} /> ); expect(screen.getByText('Active Vehicles')).toBeInTheDocument(); expect(screen.getByText('42')).toBeInTheDocument(); }); });
-
Integration Test Example
// app/__tests__/dashboard.test.tsx import { GET } from '../api/dashboard/route'; import { NextRequest } from 'next/server'; describe('/api/dashboard', () => { it('returns dashboard metrics for authenticated user', async () => { const request = new NextRequest('http://localhost/api/dashboard'); const response = await GET(request); const data = await response.json(); expect(response.status).toBe(200); expect(data).toHaveProperty('activeVehicles'); }); });
- Minimum Coverage: 80% for new code
- Critical Paths: 100% coverage for authentication, authorization, and data mutations
- Integration Tests: All API endpoints must have integration tests
- E2E Tests: Core user flows must have end-to-end test coverage
-
TSDoc for Functions
/** * Calculates the on-time delivery rate for an organization * @param organizationId - The organization identifier * @param timeframe - Number of days to look back * @returns Promise resolving to percentage (0-100) * @throws {ValidationError} When organizationId is invalid */ export async function calculateOnTimeDeliveryRate( organizationId: string, timeframe: number = 30 ): Promise<number> { // Implementation }
-
Component Documentation
/** * Dashboard metric card component * * @example * ```tsx * <MetricCard * title="Active Vehicles" * value={42} * change={{ value: 5, type: 'increase', timeframe: 'last month' }} * /> * ``` */ export function MetricCard({ title, value, change }: MetricCardProps) { // Implementation }
When adding new features, update relevant documentation:
- Update API Reference for new endpoints
- Update Component Library for new components
- Update Architecture for architectural changes
-
Run Tests
npm run test npm run test:e2e
-
Check Linting
npm run lint npm run type-check
-
Test Database Changes
npm run db:reset npm run db:seed
Use this template for your pull requests:
## Description
Brief description of changes made.
## Type of Change
- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
- [ ] Documentation update
## Testing
- [ ] Unit tests pass
- [ ] Integration tests pass
- [ ] E2E tests pass
- [ ] Manual testing completed
## Checklist
- [ ] Code follows the style guidelines
- [ ] Self-review of code completed
- [ ] Code is commented, particularly in hard-to-understand areas
- [ ] Corresponding documentation updates made
- [ ] No new warnings or errors introduced
## Screenshots (if applicable)
Add screenshots for UI changes.
## Related Issues
Closes #(issue number)
- Automated Checks: All CI checks must pass
- Code Review: At least one approving review required
- Testing: Manual testing for UI changes
- Documentation: Documentation updates reviewed
-
Domain-Driven Design
features/ ├── dispatch/ │ ├── components/ # UI components │ ├── lib/ # Business logic │ ├── types/ # Type definitions │ └── tests/ # Feature tests
-
Server Actions Pattern
// lib/actions/dispatchActions.ts 'use server'; export async function createLoadAction( formData: FormData ): Promise<ActionResult<Load>> { // Validation, authorization, and business logic }
-
Data Fetching Pattern
// lib/fetchers/dispatchFetchers.ts export async function getActiveLoads( organizationId: string ): Promise<Load[]> { // Data fetching with proper caching }
-
Caching Strategy
import { unstable_cache } from 'next/cache'; export const getCachedData = unstable_cache( async (id: string) => { // Data fetching logic }, ['cache-key'], { revalidate: 300, tags: ['data-tag'], } );
-
Database Optimization
// Use select to limit fields const loads = await prisma.load.findMany({ where: { organizationId }, select: { id: true, loadNumber: true, status: true, // Only include needed fields }, });
-
Always Verify User Context
export async function updateLoad(loadId: string, data: UpdateLoadData) { const { user } = await getCurrentUser(); // Verify user has permission to update this load await verifyLoadAccess(user.organizationId, loadId); // Proceed with update }
-
Input Validation
// Always validate inputs with Zod const validatedData = updateLoadSchema.parse(data);
-
SQL Injection Prevention
// ✅ Good: Use Prisma ORM (prevents SQL injection) const loads = await prisma.load.findMany({ where: { organizationId }, }); // ❌ Never: Raw SQL with user input const loads = await prisma.$queryRaw` SELECT * FROM loads WHERE organization_id = ${organizationId} `;
-
Multi-tenant Isolation
// Always include organizationId in queries const vehicle = await prisma.vehicle.findUnique({ where: { id: vehicleId, organizationId: user.organizationId, // Tenant isolation }, });
-
Sensitive Data Handling
// Don't log sensitive information console.log('User action:', { action: 'update_profile', userId: user.id, // Don't log: password, SSN, etc. });
- Documentation: Check the wiki first
- GitHub Issues: Search existing issues before creating new ones
- GitHub Discussions: For questions and general discussion
- Code Review: Tag reviewers for specific expertise areas
Thank you for contributing to FleetFusion! 🚛