Full-Stack Development: Using Claudio with Multi-Service Applications¶
Time: 25-35 minutes
This tutorial explains how to use Claudio effectively with full-stack applications that combine frontend and backend services, using Docker, Docker Compose, and microservices architectures.
Overview¶
Claudio's git worktree architecture excels at coordinating full-stack development:
- Service isolation: Frontend and backend can be developed independently
- Container coordination: Docker containers per worktree avoid port conflicts
- Database isolation: Each worktree can use separate database instances
- API contract enforcement: Changes can be coordinated across the stack
- Integration testing: Each worktree can run full-stack integration tests
Prerequisites¶
- Claudio initialized in your project (
claudio init) - Docker and Docker Compose installed
- Familiarity with basic Claudio operations (see Quick Start)
- Understanding of your stack (React/Vue + Node/Python/Go, etc.)
Understanding Full-Stack and Git Worktrees¶
Typical Full-Stack Structure¶
project/
├── frontend/ # React/Vue/Angular app
│ ├── package.json
│ └── src/
├── backend/ # Node/Python/Go API
│ ├── package.json (or requirements.txt, go.mod)
│ └── src/
├── docker-compose.yml # Service orchestration
├── .env # Environment variables
└── infra/ # Infrastructure configs
Worktree Considerations¶
Each worktree is a complete copy:
.claudio/worktrees/abc123/
├── frontend/ # Independent frontend
├── backend/ # Independent backend
├── docker-compose.yml # Copy of compose file
└── .env # Can be customized per worktree
Key insight: Services in different worktrees need different ports to avoid conflicts.
Strategy 1: Layer-Based Development (Recommended)¶
Best for: Most full-stack applications.
Concept¶
Assign instances to different layers of the application:
Instance 1: Frontend changes
Instance 2: Backend API changes
Instance 3: Database/Infrastructure changes
Instance 4: Integration tests
Workflow¶
Task 1 - Backend API:
Implement the user preferences API in backend/src/api/preferences.
1. Create GET /api/preferences endpoint
2. Create PUT /api/preferences endpoint
3. Add request validation
4. Add unit tests
cd backend
npm install
npm run test
npm run start:dev # Port 4001
Task 2 - Frontend UI:
Implement the preferences page in frontend/src/pages/Preferences.
1. Create PreferencesPage component
2. Add API integration
3. Add form validation
4. Add unit tests
cd frontend
npm install
npm run test
npm run dev -- --port 3001
Task 3 - Integration:
Add E2E tests for the preferences feature.
1. Start both services
2. Write Cypress/Playwright tests
3. Run integration tests
docker-compose up -d
npm run test:e2e
Strategy 2: Docker Compose Per Worktree¶
Best for: Complex multi-service applications.
Port Configuration¶
Create a port offset system for worktrees:
# docker-compose.override.yml (per worktree)
services:
frontend:
ports:
- "${FRONTEND_PORT:-3000}:3000"
backend:
ports:
- "${BACKEND_PORT:-4000}:4000"
postgres:
ports:
- "${DB_PORT:-5432}:5432"
Environment Variables¶
Create .env per worktree with unique ports:
# .claudio/worktrees/abc123/.env
FRONTEND_PORT=3001
BACKEND_PORT=4001
DB_PORT=5433
DB_NAME=app_abc123
# .claudio/worktrees/def456/.env
FRONTEND_PORT=3002
BACKEND_PORT=4002
DB_PORT=5434
DB_NAME=app_def456
Task Instructions¶
Start services with worktree-specific ports:
1. Create .env with:
FRONTEND_PORT=3001
BACKEND_PORT=4001
DB_PORT=5433
DB_NAME=app_${PWD##*/}
2. docker-compose up -d
3. Implement the feature...
Strategy 3: Microservices Coordination¶
Best for: Microservices architectures.
Service Structure¶
project/
├── services/
│ ├── user-service/
│ ├── order-service/
│ ├── payment-service/
│ └── notification-service/
├── gateway/
├── frontend/
└── docker-compose.yml
Task Assignment¶
Each instance handles a specific service:
Instance 1 - User Service:
Implement user preferences in services/user-service.
cd services/user-service
docker-compose up -d user-service postgres
npm run test
npm run dev
Instance 2 - Order Service:
Add discount calculation in services/order-service.
cd services/order-service
docker-compose up -d order-service redis
npm run test
npm run dev
Instance 3 - Gateway:
Add new routes to gateway for preferences.
cd gateway
docker-compose up -d gateway
npm run test
npm run dev
Database Strategies¶
SQLite (Simplest)¶
For development, SQLite provides easy isolation:
PostgreSQL with Isolated Databases¶
Create databases per worktree:
Task instruction:
Set up isolated database and implement feature:
1. Create database: createdb app_$(basename $PWD)
2. Update .env with DATABASE_URL
3. Run migrations
4. Implement feature
Docker PostgreSQL per Worktree¶
# docker-compose.yml
services:
postgres:
image: postgres:15
environment:
POSTGRES_DB: ${DB_NAME:-app}
ports:
- "${DB_PORT:-5432}:5432"
volumes:
- postgres_data_${WORKTREE_ID:-default}:/var/lib/postgresql/data
volumes:
postgres_data_${WORKTREE_ID:-default}:
MongoDB Isolation¶
services:
mongo:
image: mongo:7
ports:
- "${MONGO_PORT:-27017}:27017"
environment:
MONGO_INITDB_DATABASE: ${DB_NAME:-app}
Testing Strategies¶
Unit Tests (Parallel-Safe)¶
Run independently per service:
Frontend:
Backend:
Integration Tests (Need Coordination)¶
Use isolated environments:
Run integration tests with isolated services:
1. Create .env with unique ports
2. docker-compose up -d
3. npm run test:integration
4. docker-compose down
E2E Tests¶
Coordinate E2E tests across the stack:
Option A: Sequential Execution
Option B: Isolated Environments
Run E2E tests in isolated environment:
1. docker-compose -p e2e_$(basename $PWD) up -d
2. npm run test:e2e
3. docker-compose -p e2e_$(basename $PWD) down
Contract Testing¶
For API contracts between services:
Run contract tests for user-service API:
1. Start mock server with contract
2. Run frontend contract tests
3. Run backend contract tests
npm run test:contract
API Development Workflow¶
Backend-First Development¶
# Instance 1: Create API
Implement the new preferences API in backend.
1. Define OpenAPI spec in api/preferences.yaml
2. Generate types from spec
3. Implement endpoints
4. Add tests
# Instance 2: Consume API (depends on Instance 1)
Integrate preferences API in frontend.
1. Generate client from OpenAPI spec
2. Create API service
3. Integrate with components
Frontend-First Development¶
# Instance 1: Create Mock API
Create mock preferences API for frontend development.
1. Create mock server responses
2. Implement frontend features
3. Write frontend tests
# Instance 2: Real API Implementation
Implement actual preferences API matching frontend expectations.
1. Match mock API contract
2. Implement backend logic
3. Run integration tests
Shared Types¶
For shared TypeScript types:
Task instruction:
Update shared types before implementing:
1. Edit shared/types/preferences.ts
2. Run type generation for both services
3. Implement feature using new types
Common Conflict Points¶
File Conflicts¶
| File | Risk | Mitigation |
|---|---|---|
docker-compose.yml | HIGH | One instance for infra changes |
.env | MEDIUM | Usually gitignored |
package.json (both) | MEDIUM | One instance per service |
| Shared types | MEDIUM | Sequential type changes |
| API specs | MEDIUM | One instance owns spec |
Task Design¶
Good decomposition:
├── frontend/ feature changes
├── backend/ API changes
├── shared/ type updates (first)
└── E2E tests (last)
Risky decomposition:
├── Login feature (touches all services)
├── Profile feature (touches all services)
└── Settings feature (touches all services)
Resource Management¶
Memory Considerations¶
Running multiple Docker environments consumes memory:
# docker-compose.yml - set memory limits
services:
backend:
deploy:
resources:
limits:
memory: 512M
postgres:
deploy:
resources:
limits:
memory: 256M
Cleanup Script¶
Create a cleanup script for worktrees:
#!/bin/bash
# scripts/cleanup-worktree.sh
# Stop containers
docker-compose down -v
# Remove volumes
docker volume prune -f
# Remove images
docker image prune -f
Example: Complete Feature Development¶
Scenario¶
Implementing a shopping cart feature across: - Cart API endpoints - Cart UI components - Database schema - E2E tests
Session Setup¶
Tasks¶
Task 1 - Database Schema:
Add cart tables to database schema.
1. Create migration for cart and cart_items tables
2. Add indexes for performance
3. Run migration locally
cd backend
npm run migration:create -- add-cart-tables
npm run migration:run
# Test migration
npm run test:db
Task 2 - Cart API:
Implement cart API endpoints in backend.
Setup:
cd backend
npm install
Implement:
1. POST /api/cart/items - add item to cart
2. GET /api/cart - get cart contents
3. PUT /api/cart/items/:id - update quantity
4. DELETE /api/cart/items/:id - remove item
5. DELETE /api/cart - clear cart
Test:
npm run test -- cart
Task 3 - Cart Service (Frontend):
Create cart service for API integration.
Setup:
cd frontend
npm install
Implement:
1. Create CartService with API client
2. Add CartContext for state management
3. Add useCart hook
4. Add unit tests
Test:
npm run test -- cart
Task 4 - Cart UI:
Implement cart UI components.
Setup:
cd frontend
npm install
Implement:
1. CartIcon with item count badge
2. CartDrawer with item list
3. CartItem component
4. CartSummary with total
Test:
npm run test -- components/cart
Task 5 - E2E Tests:
Add E2E tests for cart functionality.
Setup:
docker-compose up -d
npm run build --prefix frontend
npm run build --prefix backend
Test:
1. Test adding items to cart
2. Test updating quantities
3. Test removing items
4. Test checkout flow
npx playwright test cart.spec.ts
Configuration Recommendations¶
For full-stack projects:
# ~/.config/claudio/config.yaml
# Full-stack builds take time
instance:
activity_timeout_minutes: 45
completion_timeout_minutes: 90
# Assign reviewers by area
pr:
reviewers:
by_path:
"frontend/**": [frontend-team]
"backend/**": [backend-team]
"shared/**": [tech-lead]
"docker-compose.yml": [devops]
"infra/**": [devops]
# Full-stack development can be expensive
resources:
cost_warning_threshold: 15.00
CI Integration¶
Example GitHub Actions workflow:
name: Full-Stack CI
on:
pull_request:
paths:
- 'frontend/**'
- 'backend/**'
- 'shared/**'
- 'docker-compose.yml'
jobs:
frontend:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./frontend
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
cache-dependency-path: frontend/package-lock.json
- run: npm ci
- run: npm run lint
- run: npm run test
- run: npm run build
backend:
runs-on: ubuntu-latest
defaults:
run:
working-directory: ./backend
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
cache-dependency-path: backend/package-lock.json
- run: npm ci
- run: npm run lint
- run: npm run test
- run: npm run build
e2e:
runs-on: ubuntu-latest
needs: [frontend, backend]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
- name: Start services
run: docker-compose up -d
- name: Wait for services
run: sleep 30
- name: Run E2E tests
run: npm run test:e2e
- name: Stop services
run: docker-compose down
Troubleshooting¶
Port already in use¶
Another worktree using the same port.
Solution:
Database connection refused¶
Database not running or wrong port.
Solution:
Container name conflict¶
Docker container names must be unique.
Solution: Use project name:
Shared types out of sync¶
Types don't match between services.
Solution:
# Rebuild shared types
cd shared && npm run build
cd ../frontend && npm install
cd ../backend && npm install
Network conflicts¶
Docker networks conflicting between worktrees.
Solution: Use isolated networks:
What You Learned¶
- Coordinating frontend and backend development
- Docker Compose isolation strategies
- Database management across worktrees
- Testing strategies for full-stack applications
- API development workflow patterns
- CI integration for multi-service applications
Next Steps¶
- Web Development - Frontend-specific patterns
- Monorepo Development - Large multi-service repos
- Configuration Guide - Customize for your team