Development Guidelines Overview
This section provides comprehensive guidelines for developing Asset360 v3, covering coding standards, testing practices, database management, and workflow procedures.
Why Guidelines Matter
Consistent development practices ensure:
- Code Quality: Maintainable, readable, and reliable code
- Team Productivity: Less time debugging, more time building
- Onboarding: New developers quickly understand conventions
- Technical Debt: Prevent accumulation of problematic code
- Best Practices: Leverage industry standards and lessons learned
Guidelines Sections
Coding Standards
- Coding Standards - General coding principles and rules
- Clean Code Principles - Writing maintainable code
- TypeScript Best Practices - Type safety and TS patterns
- Accessibility Standards - Building accessible UI
- React Best Practices - React-specific guidelines
Project Structure
- Project Structure - How code is organized
- Domain Isolation - Enforcing domain boundaries
- Type Exports - Sharing types correctly
Database & Migrations
- Database Standards - Database conventions
- Cloudflare D1 Limitations - Working with D1
- Drizzle ORM - Using Drizzle effectively
Testing
- Testing Standards - Overall testing approach
- Test Structure - Organizing tests
- Test Helpers - Shared test utilities
- Test Isolation - Independent test execution
Framework Usage
- TRPC v11 - Using TRPC correctly
- Package Management - PNPM usage
- Financial Calculations - Money handling
Workflow & Integration
- Git Workflow - Version control practices
- API Integration - External API usage
Core Principles
1. Clean Code
Write code that is:
- Self-documenting: Clear names, obvious intent
- Simple: Solve problems in straightforward ways
- DRY: Don't repeat yourself
- SOLID: Follow SOLID principles
2. Type Safety
Use TypeScript effectively:
- No
any: Always specify types - Strict mode: Enable all strict checks
- Interfaces: Define clear contracts
- Type inference: Let TypeScript work for you
3. Domain-Driven Design
Respect domain boundaries:
- No cross-domain imports: Use dependency injection
- Clear responsibilities: Each domain has a specific purpose
- Ubiquitous language: Use domain terminology consistently
4. Test-Driven Development
Write tests that:
- Are independent: Don't rely on other tests
- Test behavior: Not implementation details
- Are maintainable: Easy to understand and update
- Provide confidence: Cover critical paths
5. Documentation
Document through:
- JSDoc comments: For all public APIs
- README files: For major components
- Type definitions: Self-documenting code
- This documentation: Architecture and patterns
Quick Reference
File Naming
service.ts # Service class
repository.ts # Repository class
domain.ts # Domain types and entities
index.ts # Public exports
service.test.ts # Service tests
Import Organization
// 1. External dependencies
import { eq } from "drizzle-orm";
import type { ProductionDBClient } from "../db/client";
// 2. Shared utilities
import { Money } from "@shared/money";
// 3. Local imports
import type { FundEntity } from "./domain";
import { FundRepository } from "./repository";
Constructor Pattern
export class ServiceName {
constructor(
private repository: RepositoryType,
private optionalService?: OptionalServiceType,
) {}
}
Method Documentation
/**
* Creates a new fund with validation
*
* @param data - Fund creation data
* @returns Promise resolving to the created fund
* @throws Error if fund code already exists or validation fails
*/
async createFund(data: CreateFundRequest): Promise<FundEntity> {
// Implementation
}
Common Mistakes to Avoid
❌ DON'T
// Don't use any
function process(data: any) {}
// Don't import across domains
import { FundService } from "../fund/service";
// Don't use var
var count = 0;
// Don't ignore errors
try {
await someOperation();
} catch (e) {
// Empty catch block
}
// Don't create transactions (D1 doesn't support them)
await db.transaction(async (tx) => {});
✅ DO
// Use specific types
function process(data: ProcessInput) { }
// Use dependency injection
constructor(private fundService?: FundService) { }
// Use const/let
const count = 0;
// Handle errors properly
try {
await someOperation();
} catch (error) {
console.error('Operation failed:', error);
throw new Error(`Failed to process: ${error.message}`);
}
// Use sequential operations
const result1 = await db.insert(...);
const result2 = await db.insert(...);
Tools & Configuration
Required Tools
- Node.js: v20 or higher
- PNPM: For package management
- TypeScript: v5.6+
- VSCode: Recommended IDE
- Vitest: For testing
Configuration Files
tsconfig.json- TypeScript configurationeslint.config.mjs- Linting rulesvitest.config.ts- Test configurationdrizzle.config.ts- Database configurationwrangler.jsonc- Cloudflare Workers config
VSCode Extensions
Recommended extensions:
- ESLint - Linting support
- Prettier - Code formatting
- TypeScript Vue Plugin - Enhanced TS support
- Vitest - Test runner integration
Getting Help
- Check this documentation - Most answers are here
- Read the code - Our code is well-documented
- Check tests - Tests show usage examples
- Ask the team - We're here to help
Contributing
When adding new features:
- Follow these guidelines
- Write tests for your code
- Document public APIs with JSDoc
- Update this documentation if needed
- Request code review before merging
Next Steps
- Read Coding Standards
- Understand Project Structure
- Review Testing Standards
- Explore Database Standards
- Check framework-specific guides as needed