Development Guidelines - PCB Stackup Generator¶
Internal Use Only - This document provides development guidelines, code style requirements, and best practices for the internal development team. This is a proprietary project, not open source.
Table of Contents¶
- Getting Started
- Critical Development Rules
- Code Style Guidelines
- Documentation Requirements
- Testing Requirements
- Code Review Process
- Merge Request Checklist
- Project Structure
- Development Workflow
- Code Patterns to Follow
Getting Started¶
Prerequisites¶
- Node.js (v18 or later)
- Python 3.9+ (for backend)
- KiCad 10.0 (for full symbol generation)
- Git for version control
Setup¶
-
Clone the repository (internal access required):
-
Install dependencies:
-
Set up pre-commit hooks:
-
Configure environment variables:
- Copy
env.production.templateto.envin project root orconfig/.env -
Fill in required values (see ENV_VARIABLES_GUIDE.md)
-
Start development servers:
Critical Development Rules¶
- Database rule: Backend is the only source of truth. Edit only
backend/categorized_databases/. Do not runupdate_frontend_database.py(deprecated). Frontend uses the backend API; no sync step is needed. - KiCad Python: Use
C:\Program Files\KiCad\10.0\bin\python.exefor any script that importspcbneworeeschema. System Python does not have these modules. - Startup: Always use
.\start-all-servers-windowed.ps1. Do not start servers manually (e.g.node index.js); the script handles ports, env vars, and database preloading.
See CLAUDE.md for full details.
Code Style Guidelines¶
General Principles¶
- Keep files under 300 lines - Split into modules when approaching this limit
- Never create files longer than 500 lines - This is a hard limit
- Test early, test often - Write tests for all new functions
- Document as you go - Don't delay documentation
Python (Backend) Style¶
Naming Conventions¶
- Files:
snake_case.py(e.g.,email_service.py,validated_database_service.py) - Functions:
snake_case()(e.g.,get_components(),validate_input()) - Classes:
PascalCase(e.g.,ValidatedDatabaseService,ProjectCreate) - Variables:
snake_case(e.g.,user_id,component_list) - Constants:
UPPER_SNAKE_CASE(e.g.,SUPABASE_URL,API_KEYS) - Private functions: Prefix with
_(e.g.,_internal_helper())
Code Formatting¶
- Follow PEP 8 guidelines
- Use Ruff for linting and formatting:
- Unused imports are deleted at commit (ruff rule F401, issue 234). An import kept
only so OTHER files can import the name from here looks unused to ruff, so mark it
(
__all__, or# noqa: F401with the reason) or ruff will delete it. To find any it would delete:bash scripts/hook-tool.sh python backend/scripts/check_hidden_reexports.py. - Type hints required for all function parameters and return values:
Docstrings¶
Start docstrings with an Intent statement: 1-2 sentences describing what the function achieves from a business/domain perspective. This aids AI-assisted debugging.
Use Google-style docstrings for all functions:
def calculate_power_flow(
components: list[dict],
input_power: float
) -> dict[str, float]:
"""Calculate RF power flow through component chain.
Intent: Given a list of RF components and input power, compute power levels
at each stage for link budget analysis. Used by BOM validation and chain design.
Args:
components: List of RF components with gain/loss values.
input_power: Input power in dBm.
Returns:
Dictionary with power levels at each stage:
- 'stages': List of power levels
- 'output_power': Final output power in dBm
- 'total_gain': Total gain in dB
Raises:
ValueError: If input_power is negative or components list is empty.
"""
pass
Comments¶
- Comment non-obvious code with explanations of "why", not just "what"
- Add "# Reason:" comments for complex logic:
TypeScript/React (Frontend) Style¶
Naming Conventions¶
- Files:
camelCase.tsorcamelCase.tsx(e.g.,componentDatabaseService.ts,projectCard.tsx) - Components:
PascalCase(e.g.,ProjectCard,PhaseProvider) - Functions:
camelCase()(e.g.,saveProject(),loadComponent()) - Interfaces:
PascalCase(e.g.,ProjectCardProps,RfChainComponent) - Types:
PascalCase(e.g.,ProjectMetadata,PhaseState) - Hooks:
camelCasewith "use" prefix (e.g.,usePhaseContext(),useRfModuleState()) - Constants:
camelCaseorUPPER_SNAKE_CASE(e.g.,apiBaseURL,SUPABASE_URL) - Private functions: Prefix with
_(e.g.,_internalHelper())
Code Formatting¶
- Use Prettier for formatting (if configured)
- Follow ESLint rules
- Use TypeScript strict mode
- Prefer functional components with hooks
Function Documentation¶
/**
* Selects optimal VCO for given frequency requirements.
*
* @param frequency - Target frequency in Hz
* @param application - Application type (Consumer, Automotive, RF/Microwave)
* @param customWeights - Optional custom selection weights
* @returns Selected VCO component or null if none found
* @throws {Error} If frequency is out of valid range
*/
async function selectVCO(
frequency: number,
application: RfApplicationType,
customWeights?: VCOWeights
): Promise<RfChainComponent | null> {
// Implementation
}
File Organization¶
- Keep related code together - Group by feature, not by type
- Use barrel exports - Create
index.tsfiles for clean imports - Separate concerns - Business logic in services, UI in components
- Follow existing patterns - Match the structure of similar files
Documentation Requirements¶
Code Documentation¶
- All exported/public functions must have docstrings/comments:
- Python: Google-style docstrings
-
TypeScript: JSDoc comments
-
Complex logic must have inline comments:
-
Update README.md when:
- Adding new features
- Changing dependencies
- Modifying setup steps
- Adding new environment variables
Service Documentation¶
When adding new services:
- Update service README:
- See GitHub repository for component services
- See GitHub repository for RF chain services
-
See GitHub repository for backend services
-
Document in main README:
- Add to architecture overview
- Update service list
- Add usage examples if applicable
API Documentation¶
- FastAPI endpoints are auto-documented, but add clear descriptions:
Testing Requirements¶
Test Coverage¶
Every new function must have unit tests with at least:
- Expected use case - Normal operation
- Edge case - Boundary conditions
- Failure case - Error handling
Python Tests¶
- Use pytest for all tests
- Use pytest-asyncio for async functions
- Tests in
backend/tests/mirror main structure - Name tests:
test_[function_name]_[scenario].py
import pytest
from services.validated_database_service import validated_db_service
def test_get_components_by_category_success():
"""Test successful component retrieval."""
components = validated_db_service.get_components_by_category('vco')
assert len(components) > 0
assert all(c['category'] == 'vco' for c in components)
def test_get_components_by_category_invalid():
"""Test invalid category handling."""
with pytest.raises(ValueError):
validated_db_service.get_components_by_category('invalid')
TypeScript Tests¶
- Use Vitest for frontend tests
- Tests in
frontend/src/**/__tests__/ - Test components, hooks, and services
import { selectVCO } from './vcoSelectionService';
describe('selectVCO', () => {
it('should select VCO for valid frequency', async () => {
const vco = await selectVCO(2.4e9, 'Consumer');
expect(vco).toBeDefined();
expect(vco?.frequency_min).toBeLessThanOrEqual(2.4e9);
expect(vco?.frequency_max).toBeGreaterThanOrEqual(2.4e9);
});
it('should return null for invalid frequency', async () => {
const vco = await selectVCO(-1, 'Consumer');
expect(vco).toBeNull();
});
});
Running Tests¶
Code Review Process¶
Before Submitting for Review¶
- Check existing work - Avoid duplicates with current tasks
- Update documentation - README, service docs, API docs
- Write/update tests - Ensure all tests pass
- Run linters - Fix all linting errors
- Test locally - Verify functionality works
- Update CHANGELOG (if applicable)
Merge Request Title Format¶
Use clear, descriptive titles:
- feat: Add VCO selection optimization
- fix: Resolve power flow calculation error
- docs: Update component selection documentation
- refactor: Split large service into modules
Merge Request Description Template¶
## Description
Brief description of changes.
## Type of Change
- [ ] Bug fix
- [ ] New feature
- [ ] Documentation update
- [ ] Refactoring
- [ ] Performance improvement
## Testing
- [ ] Unit tests added/updated
- [ ] Integration tests pass
- [ ] Manual testing completed
## Documentation
- [ ] README updated
- [ ] Service documentation updated
- [ ] API documentation updated
- [ ] Code comments added
## Checklist
- [ ] Code follows style guidelines
- [ ] All tests pass
- [ ] No linting errors
- [ ] Documentation updated
Merge Request Checklist¶
Before submitting a merge request, ensure:
Code Quality¶
- Code follows naming conventions
- Files are under 300 lines (or split appropriately)
- Type hints added (Python) / Types defined (TypeScript)
- No hardcoded secrets or credentials
- Error handling implemented
- No console.log/debug statements left in code
Documentation¶
- All functions have docstrings/comments
- Complex logic has "# Reason:" comments
- README.md updated if needed
- Service documentation updated
- API documentation updated (if applicable)
Testing¶
- Unit tests written for new functions
- Edge cases tested
- Error cases tested
- All existing tests still pass
- Manual testing completed
Style & Linting¶
- Ruff/Python formatting applied (
ruff format .) - Ruff linting passes (
ruff check .) - TypeScript/ESLint passes
- Pre-commit hooks pass
Git¶
- Meaningful commit messages
- Logical commit history (use rebase if needed)
- Branch is up to date with main
- No merge conflicts
Functionality¶
- Feature works as expected
- No breaking changes (or documented if intentional)
- Backward compatibility maintained
- Performance acceptable
Project Structure¶
Key Directories¶
pcb_stackup_generator/
├── frontend/ # React/TypeScript frontend
│ └── src/
│ ├── services/ # Business logic services
│ ├── components/ # UI components
│ ├── hooks/ # React hooks
│ └── utils/ # Utility functions
├── backend/ # Python FastAPI backend
│ ├── services/ # Backend services
│ ├── routes/ # API routes
│ ├── agents/ # AI agent implementations
│ └── categorized_databases/ # Component databases
├── docs/ # Project documentation
└── scripts/ # Utility scripts
Important Files¶
README.md- Main project documentationDEVELOPMENT_GUIDELINES.md- This file.cursor/rules/general-rule.mdc- Project-specific rulesPLANNING.md- Architecture and planning docsTASK.md- Task tracking
Development Workflow¶
1. Create Feature Branch¶
2. Make Changes¶
- Write code following style guidelines
- Add tests as you go
- Update documentation
- Commit frequently with clear messages
3. Test Locally¶
# Run all tests
pytest backend/tests
npm test -- frontend
# Run linters
ruff check --fix .
ruff format .
# Start servers and test manually
.\start-all-servers-windowed.ps1
4. Update Documentation¶
- Update relevant README files
- Add/update service documentation
- Update API docs if needed
5. Submit for Review¶
- Push to your branch
- Create merge request with description
- Link related tasks/issues
- Request review from team
6. Address Feedback¶
- Respond to review comments
- Make requested changes
- Update merge request as needed
Code Patterns to Follow¶
Pattern 1: Service Layer Architecture¶
Purpose: Separate business logic from UI components
// CORRECT: Logic in service
// services/rfChain/powerCalculator.ts
export const calculateRfPower = (
inputPower: number,
gain: number,
loss: number
): number => {
return inputPower + gain - loss; // dBm calculation
};
// components/PowerDisplay.tsx
import { calculateRfPower } from '../../services/rfChain/powerCalculator';
const PowerDisplay = ({ inputPower, gain, loss }) => {
const outputPower = calculateRfPower(inputPower, gain, loss);
return <div>Output: {outputPower} dBm</div>;
};
Pattern 2: Context Splitting¶
Purpose: Reduce re-renders by separating data from actions
// CORRECT: Split contexts
// contexts/RfModuleDataContext.tsx
export const RfModuleDataContext = createContext<RfModuleData | null>(null);
// contexts/RfModuleActionsContext.tsx
export const RfModuleActionsContext = createContext<RfModuleActions | null>(null);
// Usage: data re-renders only on data changes; actions are stable reference
Pattern 3: Barrel Exports¶
Purpose: Cleaner imports and better organization
// CORRECT: services/index.ts
export * from './stackup/impedanceCalculator';
export * from './stackup/stackupService';
export * from './rfChain/powerCalculator';
// Usage
import { calculateImpedance, generateStackup, calculateRfPower } from '../services';
Pattern 4: Error Handling with Fallbacks¶
Purpose: Graceful degradation and user-friendly errors
# CORRECT: Fallback mechanism
try:
results = await nexar_api.search(request.query)
return results
except NexarAPIError as e:
logger.warning(f"Nexar failed: {e}, falling back to validated database")
return validated_db.search(request.query)
except Exception as e:
logger.error(f"Search failed: {e}")
raise HTTPException(status_code=500, detail="Component search unavailable")
Pattern 5: TypeScript Strict Typing¶
Purpose: Catch errors at compile time
// CORRECT: Strong typing
interface Component {
part_number: string;
frequency_min_ghz: number;
frequency_max_ghz: number;
gain_db?: number;
}
const filterByFrequency = (
components: Component[],
targetFreq: number
): Component[] => {
return components.filter(c =>
c.frequency_min_ghz <= targetFreq &&
c.frequency_max_ghz >= targetFreq
);
};
Environment Variables¶
Never commit .env files!
- Use
env.production.templateas reference - Document new variables in
ENV_VARIABLES_GUIDE.md - Use environment variables for all secrets/config
Security¶
- Never hardcode API keys or credentials
- Use environment variables for sensitive data
- Validate all user inputs
- Sanitize outputs to prevent injection
- Follow security best practices (see SECURITY_TESTING_GUIDE.md)
Upgrading Dependencies¶
- GitHub keeps two pip snapshots of this repo: one scanned from the repo root, which also reads
backend/requirements*.txt, and one scanned from/backend. - A PR that changes only
backend/requirements*.txtrefreshes only the/backendsnapshot, so the Dependabot alerts it fixes stay open. - When only backend requirements change, also change a root pip file (usually a comment line in
docs-requirements.txt) so GitHub re-scans from the root. See the comment at the top of that file. - This has been proven twice with a follow-up PR (issues 113 and 223). Doing it in the same PR is not verified.
- After merging, check that the old version is gone:
gh api repos/magiccadai/AI-assisted-PCB-stackup-generator/dependency-graph/sbomshould no longer list it next to the new one (issue 391).
Getting Help¶
- Documentation: Check
docs/directory - Team Communication: Contact team lead or project manager
- Questions: Reach out to senior developers or check existing documentation
- Internal Resources: Refer to internal project management tools
Code Review Guidelines¶
For Reviewers¶
- Be constructive and respectful
- Focus on code quality, not personal preferences
- Explain reasoning for requested changes
- Approve when requirements are met
For Authors¶
- Respond to all comments
- Don't take feedback personally
- Ask for clarification if needed
- Make requested changes or explain why not
Additional Resources¶
- Service Documentation
- Backend Services
- Component Selection
- RF Chain Services
- Environment Variables Guide
- Quick Start Guide
These guidelines help maintain code quality and consistency across the development team. 🚀