- Tech Stack
- Repo Structure
- Frontend Development
- Development Setup
- Recommended VSCode Settings
- Application Execution
- API Testing with Postman
- Database Interactions
- Version Control Guide
- Claude Code Integration
- Formatting and Linting
- Testing
- FAQ & Debugging
Frontend:
- React 19.2.0
- TypeScript 5.9.3
- Vite 7.2.4 (build tool)
- React Router v7.12.0 (routing)
- Tailwind CSS v4.1.18 (styling)
- pnpm (package manager)
Backend: Python, FastAPI, SQLModel Database: PostgreSQL Authentication: Firebase Auth Containerization: Docker & Docker Compose
food4kids/
├── backend/
│ └── python/
│ ├── app/
│ │ ├── dependencies/ # Dependency injection (auth, etc.)
│ │ ├── migrations/ # Alembic database migrations
│ │ ├── models/ # SQLModel database models
│ │ ├── routers/ # FastAPI route handlers
│ │ ├── schemas/ # Pydantic schemas for API
│ │ ├── services/ # Business logic layer
│ │ │ ├── implementations/ # Concrete service implementations
│ │ │ └── jobs/ # Scheduled Cron Jobs
│ │ │ └── protocols/ # Algorithms and how the server handles data
│ │ ├── templates/ # Email/HTML templates
│ │ └── utilities/ # Shared utility functions
│ ├── tests/ # Unit and functional tests
│ ├── alembic.ini # Alembic configuration
│ ├── requirements.txt # Python dependencies
│ └── server.py # Application entry point
├── frontend/ # React + TypeScript frontend (see Frontend Development section)
├── db-init/ # Database initialization scripts
├── docker-compose.yml # Multi-container Docker setup
└── README.md
The frontend is built with React 19, TypeScript, and Vite, using modern development practices and tooling. This section covers the project structure, coding conventions, and development workflow.
frontend/
├── src/
│ ├── api/ # API client configuration
│ ├── assets/
│ │ ├── fonts/ # Custom web fonts
│ │ └── images/ # Images, logos, icons
│ ├── components/
│ │ ├── common/ # Reusable UI components (buttons, inputs, cards, modals)
│ │ └── features/ # Feature-specific components with business logic
│ ├── constants/ # Application constants and configuration values
│ ├── contexts/ # React Context providers for state management
│ ├── hooks/ # Custom React hooks (useAuth, useFetch, etc.)
│ ├── layouts/ # Layout wrapper components (navigation, sidebars, footers)
│ ├── pages/ # Page-level components for routing
│ ├── types/ # TypeScript type definitions and interfaces
│ ├── utils/ # Utility helper functions
│ ├── main.tsx # Application entry point
│ ├── App.tsx # Root component
│ └── index.css # Global styles (Tailwind imports)
├── public/ # Static assets served directly
├── vite.config.ts # Vite configuration
├── tsconfig.json # TypeScript configuration
├── eslint.config.js # ESLint rules
├── .prettierrc # Prettier formatting rules
└── package.json # Dependencies and scripts
Architecture: The frontend uses a feature-based modular architecture with separation of concerns between reusable UI components and feature-specific business logic.
When to use components/common/:
- Reusable UI elements that can be used across multiple features
- Generic components: buttons, inputs, cards, modals, dropdowns, tooltips
- No business logic or feature-specific knowledge
- Examples:
Button.tsx,Input.tsx,Card.tsx,Modal.tsx
When to use components/features/:
- Components tied to specific business logic or features
- Feature-specific functionality that won't be reused elsewhere
- Examples:
UserProfileCard.tsx,OrderSummary.tsx,DonationForm.tsx
Naming Conventions:
- Use PascalCase for component files and names:
UserCard.tsx,LoginForm.tsx - Use descriptive names that clearly indicate the component's purpose
- Avoid generic names like
Component1.tsxorTemp.tsx
Best Practices:
- One component per file
- Always define TypeScript interfaces for props
- Colocate component-specific types with the component file
- Export components using named exports (not default exports)
- Keep components focused and single-purpose
The project uses Tailwind CSS v4, which introduces a CSS-first approach without a tailwind.config.js file.
Setup:
/* src/index.css */
@import 'tailwindcss';Utility-First Methodology:
- Use Tailwind utility classes directly in JSX
- Compose utilities to build complex designs
- Avoid custom CSS unless absolutely necessary
Class Sorting:
- Prettier automatically sorts Tailwind classes using
prettier-plugin-tailwindcss - Classes are ordered by function (layout → spacing → colors → typography, etc.)
The project uses TypeScript strict mode for maximum type safety.
Where to Define Types:
-
Global/Shared Types →
src/types/// src/types/user.ts export interface User { id: string; name: string; email: string; role: 'admin' | 'user' | 'donor'; }
-
Component-Specific Types → Inline or in component file
// src/components/UserCard.tsx interface UserCardProps { user: User; onEdit?: () => void; }
-
API Response Types →
src/api/types/(when implemented)// src/api/types/responses.ts export interface ApiResponse<T> { data: T; message: string; success: boolean; }
Props Typing Pattern:
// Always define props interface
interface ButtonProps {
label: string;
onClick: () => void;
variant?: 'primary' | 'secondary';
disabled?: boolean;
}
export const Button = ({ label, onClick, variant = 'primary', disabled = false }: ButtonProps) => {
// Component implementation
};Best Practices:
- Avoid
anytype - useunknownwith type guards when type is unclear - Use union types for string literals:
type Status = 'pending' | 'approved' | 'rejected' - Leverage TypeScript utility types:
Partial<T>- Make all properties optionalPick<T, K>- Pick specific propertiesOmit<T, K>- Omit specific propertiesRecord<K, V>- Object with specific key-value types
Example with Utility Types:
interface User {
id: string;
name: string;
email: string;
password: string;
}Running the Frontend Locally (not recommended, use docker instead):
# Navigate to frontend directory
cd frontend
# Install dependencies (first time only)
pnpm install
# Start development server
pnpm dev
# Access at http://localhost:3000Building for Production:
# TypeScript type-check and build
pnpm build
# Preview production build locally
pnpm previewPort Configuration:
- Default port:
3000(configured in vite.config.ts:7) - Automatically opens in browser
- Supports HMR (Hot Module Replacement) for instant updates
Development Features:
- Fast Refresh: React components update instantly without losing state
- TypeScript Checking: Vite shows TypeScript errors in the terminal
- ESLint Integration: Code quality issues highlighted in real-time
- Auto-Import Sorting: Imports automatically organized on save
ESLint Configuration:
- TypeScript ESLint with strict rules
- React plugin with recommended settings
- React Hooks rules for proper hook usage
- JSX Accessibility (a11y) rules for inclusive design
- Import plugin with auto-sorting
Prettier Configuration:
{
"semi": true,
"trailingComma": "es5",
"singleQuote": true,
"printWidth": 80,
"tabWidth": 2
}Running Code Quality Checks:
# Check for linting issues
pnpm lint
# Auto-fix linting issues
pnpm lint:fix
# Format code with Prettier
pnpm formatRecommended Workflow:
- Install recommended VSCode extensions (see Recommended VSCode Settings)
- Enable format on save and auto-fix ESLint
- Code is automatically formatted and linted as you work
- Run
pnpm lintbefore committing changes
- Install Docker Desktop and ensure it's running
- Clone this repository:
git clone [email protected]:uwblueprint/food4kids.git
cd food4kidsYou will need to create environment files: .env (backend) and frontend/.env (frontend). Talk to the PL to obtain these.
Frontend Environment Variables:
- A
frontend/.env.examplefile is provided as a template - Copy it to
frontend/.envand fill in the required values - Common variables include API endpoints, Firebase configuration, and feature flags
- Never commit
.envfiles - they are gitignored for security
Build and start all services using Docker Compose:
docker-compose up --buildThis will start:
- Frontend: React development server on port 3000
- Backend: FastAPI server on port 8080
- Database: PostgreSQL on port 5432
To ensure consistent code formatting and linting across the team, configure VSCode with these settings.
- Create a
.vscode/settings.jsonfile in the project root (if it doesn't exist) - Add the configuration below
- Install the required VSCode extensions
{
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
}
}formatOnSave: Automatically formats code with Prettier when you save a filedefaultFormatter: Sets Prettier as the default code formatter for all file typessource.fixAll.eslint: Automatically fixes ESLint errors on save (imports, spacing, etc.)
Install these extensions for the best development experience:
-
Prettier - Code formatter (
esbenp.prettier-vscode)- Formats code according to
.prettierrcconfiguration - Install: Prettier Extension
- Formats code according to
-
ESLint (
dbaeumer.vscode-eslint)- Highlights linting errors and warnings in real-time
- Auto-fixes issues on save
- Install: ESLint Extension
-
Tailwind CSS IntelliSense (
bradlc.vscode-tailwindcss)- Autocomplete for Tailwind CSS classes
- Shows CSS preview on hover
- Install: Tailwind CSS IntelliSense
-
TypeScript Error Translator (
mattpocock.ts-error-translator)- Makes TypeScript errors easier to understand
- Install: TS Error Translator
After setup, test that everything works:
- Open a
.tsxfile in the frontend - Make a formatting change (e.g., remove a semicolon)
- Save the file - Prettier should auto-format it
- Add an unused import - ESLint should highlight it and remove it on save
# Start all services
docker-compose up --build
# Start in detached mode (background)
docker-compose up -d --buildAccess Points:
- Frontend: http://localhost:3000
- Backend API: http://localhost:8080
- API Documentation: http://localhost:8080/docs (development only)
- ReDoc Documentation: http://localhost:8080/redoc (development only)
Postman is a powerful tool for testing API endpoints during development. For detailed setup instructions and best practices, see our Postman Setup Guide.
Quick Start:
- Ensure the backend container is running (
docker-compose up) - Import the Postman collection (if available) or manually configure requests
- Set the base URL to
http://localhost:8080 - Configure authentication headers as needed (see the Notion guide for details)
Alternative: You can also test endpoints using the interactive Swagger UI at http://localhost:8080/docs
The project uses Alembic for database migrations. All commands run from the project root:
# Check current migration status
docker-compose exec backend alembic current
# Generate new migration (auto-detect model changes)
docker-compose exec backend alembic revision --autogenerate -m "description_of_changes"
# Apply pending migrations
docker-compose exec backend alembic upgrade head
# Check if database schema matches models
docker-compose exec backend alembic check
# View migration history
docker-compose exec backend alembic history# Connect to development database
docker-compose exec db psql -U postgres -d f4k
# Connect to test database
docker-compose exec db psql -U postgres -d f4k_test
# Once inside the DB, try these common PostgreSQL commands:
\dt # List all tables
\d table_name # Describe table structure
\q # Quit
SELECT * FROM users; # Run SQL queries# Populate database with randomized test data
docker-compose exec backend python -m app.seed_database- Branch off
mainfor all feature work and bug fixes - Use descriptive branch names in kebab-case:
username/feature-description - Example:
colin/user-authentication-fix
Use rebase instead of merge to integrate main changes:
# Update feature branch with main changes
git pull origin main --rebase
# If conflicts occur, resolve them and continue
git add .
git rebase --continue
# Force push to remote feature branch
git push --force-with-lease# Build images
docker-compose build
# Start containers (builds if needed)
docker-compose up
# Start with fresh build
docker-compose up --build
# Stop containers
docker-compose down
# Stop containers and remove volumes
docker-compose down --volumes
# View running containers
docker ps
# Clean up unused Docker resources
docker system prune -a --volumesClaude Code is integrated into the CI/CD pipeline via GitHub Actions:
Workflow: .github/workflows/claude-code-review.yml
Triggered on:
- Pull Request Ready for Review - Automatically runs when a PR is marked as ready
- @claude Comment - Manually trigger by commenting
@claude reviewon any PR
What it Reviews:
- Code quality and adherence to best practices
- Potential bugs and edge cases
- Performance considerations
- Security vulnerabilities
- Test coverage and quality
- TypeScript/Python type safety
- Documentation completeness
Benefits:
- Catches issues before human review
- Provides consistent, objective feedback
- Suggests concrete improvements with examples
- Saves review time by flagging common mistakes
- Helps maintain code quality standards
Example Usage:
# In a pull request comment, trigger a review:
@claude review
# Claude Code will respond with:
# - Code quality analysis
# - Bug reports with severity levels
# - Performance recommendations
# - Security concerns
# - Suggested fixes with code examplesFor more details on CI/CD workflows, see CI/CD Tasks below.
The project uses Ruff for Python linting and formatting, and mypy for static type checking:
# Check for linting issues
docker-compose exec backend ruff check .
# Auto-fix linting issues
docker-compose exec backend ruff check --fix .
# Format code
docker-compose exec backend ruff format .
# Check formatting without making changes
docker-compose exec backend ruff format --check .# Run type checking
docker-compose exec backend mypy . --config-file mypy.ini# Run all quality checks (linting, formatting, type checking)
docker-compose exec backend ruff check . && docker-compose exec backend ruff format --check . && docker-compose exec backend mypy . --config-file mypy.iniConfiguration Files:
- Ruff:
backend/python/pyproject.toml(under[tool.ruff]) - mypy:
backend/python/mypy.ini
# Check linting issues
docker-compose exec frontend pnpm lint
# Auto-fix linting issues
docker-compose exec frontend pnpm lint:fix
# Format code with Prettier
docker-compose exec frontend pnpm formatConfiguration Files:
- ESLint:
frontend/eslint.config.js - Prettier:
frontend/.prettierrc - TypeScript:
frontend/tsconfig.json
IMPORTANT: This project uses pnpm as the package manager, not npm or yarn.
Why pnpm?
- Faster installs: Up to 2x faster than npm
- Efficient disk usage: Hard links save space by sharing packages across projects
- Strict dependency resolution: Prevents phantom dependencies and ensures consistency
- CI/CD compatibility: All workflows use pnpm exclusively
Installation:
# Option 1: Via npm (recommended)
npm install -g pnpm
# Option 2: Via Homebrew (macOS)
brew install pnpm
# Option 3: Via Corepack (Node.js 16.13+)
corepack enable
corepack prepare pnpm@latest --activate
# Verify installation
pnpm --versionUsage:
# Install dependencies
cd frontend
pnpm install
# Add a new package
pnpm add <package-name>
# Add a dev dependency
pnpm add -D <package-name>
# Remove a package
pnpm remove <package-name>
# Update dependencies
pnpm updateImportant Notes:
pnpm-lock.yamlmust be committed to version control- Do NOT use
npm installoryarn install- this will cause dependency conflicts - CI workflows will fail if you don't use pnpm
- Docker containers are configured to use pnpm
The project uses GitHub Actions for continuous integration. All workflows are located in .github/workflows/.
Active Workflows:
-
lint.yml- Code Quality Checks- Triggers: Push or PR to
mainbranch (frontend and backend paths) - Frontend:
- Runs
pnpm install --frozen-lockfile - Executes
pnpm lint - Uses Node.js 20.11.1 with pnpm 9
- Runs
- Backend:
- Runs Ruff linter:
ruff check . - Runs Ruff formatter check:
ruff format --check . - Runs MyPy type checker:
mypy .
- Runs Ruff linter:
- Triggers: Push or PR to
-
pytest.yml- Backend Testing- Triggers: Push or PR to
mainforbackend/python/**paths - Sets up PostgreSQL service container
- Runs
pytest -q --disable-warnings -ra - Python 3.11
- Triggers: Push or PR to
-
claude-code-review.yml- Automated Code Review- Triggers: PR ready for review, or
@claude reviewcomment - Reviews code quality, bugs, performance, security, and test coverage
- See Claude Code Integration for details
- Triggers: PR ready for review, or
Running CI Checks Locally:
Before pushing changes, run the same checks that CI will run:
# Frontend checks
cd frontend
pnpm lint # ESLint check
pnpm format # Prettier format
pnpm build # TypeScript compilation check
# Backend checks
docker-compose exec backend ruff check .
docker-compose exec backend ruff format --check .
docker-compose exec backend mypy . --config-file mypy.ini
docker-compose exec backend pytestNote: Frontend testing framework is not yet configured. This will be added in a future update.
# Run all backend tests
docker-compose exec backend python -m pytest
# Run specific test file
docker-compose exec backend python -m pytest tests/unit/test_models.py
# Run with coverage
docker-compose exec backend python -m pytest --cov=appHow do I test API endpoints?
- Ensure the backend container is running
- Visit http://localhost:8080/docs for interactive API documentation
- Use the "Authorize" button to add your Firebase auth token
- Test endpoints in Postman or directly in the Swagger UI
Database connection errors
- Ensure Docker Desktop is running
- Check that the database container is healthy:
docker-compose ps - Verify environment variables in
.envfile - Try rebuilding containers:
docker-compose down --volumes && docker-compose up --build
"ENOSPC: no space left on device" when building containers
Clean up Docker resources:
docker system prune -a --volumes
docker-compose up --buildMigration errors
- Check current migration status:
docker-compose exec backend alembic current - Ensure database is running and accessible
- Verify model changes are properly defined in
app/models/ - For migration conflicts, you may need to manually resolve in the database
Firebase authentication issues
- Verify Firebase configuration in environment files
- Check that Firebase project settings match your configuration
- Ensure Firebase Admin SDK credentials are properly formatted
- Fork the repository
- Create a feature branch from
main - Make your changes following the coding standards
- Run tests and linting
- Submit a pull request with a clear description