Strangler Studio is a production-quality demonstration of the Strangler Fig patternβa proven architectural approach for migrating legacy monoliths to modern microservices without downtime. This Halloween-themed showcase features an nginx gateway routing traffic between a legacy PHP application and a modern FastAPI service, with contract-first API design via OpenAPI, feature flags for gradual migration, and automated validation workflows powered by Kiro AI.
graph TB
Client[Client Browser]
Gateway[Gateway<br/>nginx reverse proxy<br/>:8888]
Legacy[Legacy PHP App<br/>Server-rendered HTML<br/>Feature flags]
NewAPI[New API Service<br/>FastAPI + Python<br/>REST JSON endpoints]
Contract[OpenAPI Contract<br/>Source of Truth<br/>YAML specification]
Client -->|HTTP| Gateway
Gateway -->|/ /requests| Legacy
Gateway -->|/api/*| NewAPI
Legacy -.->|use_new=1| NewAPI
NewAPI -.->|validates against| Contract
Legacy -.->|references| Contract
style Gateway fill:#ff6b35,stroke:#f8f9fa,stroke-width:2px,color:#0a0a0a
style Legacy fill:#4ecdc4,stroke:#f8f9fa,stroke-width:2px,color:#0a0a0a
style NewAPI fill:#4ecdc4,stroke:#f8f9fa,stroke-width:2px,color:#0a0a0a
style Contract fill:#c1121f,stroke:#f8f9fa,stroke-width:2px,color:#f8f9fa
-
Gateway (nginx): Single entry point routing traffic based on URL paths
/and/requestsβ Legacy PHP App/api/*β New API Service (strips/apiprefix)
-
Legacy PHP App: Server-rendered MVC application
- Feature flag logic (
use_newparameter) - Calls New API Service when
use_new=1 - Falls back to stub data when
use_new=0 - Premium Halloween-themed UI with glassmorphism
- Feature flag logic (
-
New API Service: Modern FastAPI REST service
- Contract-first design with OpenAPI
- Deterministic seed data
- Full CORS support
- Automatic schema validation
-
OpenAPI Contract: Source of truth specification
- Defines all endpoints and schemas
- Enables client code generation
- Powers automated contract testing
- Docker and Docker Compose installed
- Ports 8888 and 8080 available on your machine
-
Clone the repository
git clone <repository-url> cd strangler-studio
-
Start all services
docker-compose up --build
-
Access the application
-
Via Gateway (recommended):
- Landing page: http://localhost:8888/
- Requests (legacy): http://localhost:8888/requests?use_new=0
- Requests (new API): http://localhost:8888/requests?use_new=1
- API directly: http://localhost:8888/api/requests
-
Direct access to Legacy PHP:
-
-
Stop services
docker-compose down
For development with live reloading:
# Start services in detached mode
docker-compose up -d
# View logs
docker-compose logs -f
# Restart specific service
docker-compose restart new-api
# Rebuild after code changes
docker-compose up --buildFollow these steps to experience the Strangler Fig pattern in action:
./scripts/demo.shThis automated script will:
- Start all Docker services
- Wait for health checks
- Demonstrate all key features
- Show formatted output
- Clean up services
Step 1: View the Landing Page
curl http://localhost:8888/You'll see the Halloween-themed landing page explaining the architecture.
Step 2: View Legacy Data (Stub)
curl http://localhost:8888/requests?use_new=0This uses the legacy stub data without calling the new API.
Step 3: View New API Data (Migration)
curl http://localhost:8888/requests?use_new=1This fetches data from the New API Serviceβdemonstrating the migration!
Step 4: Access API Directly
curl http://localhost:8888/api/requestsDirect access to the New API Service through the gateway.
Step 5: Get Single Request
curl http://localhost:8888/api/requests/1Retrieve a specific Student Request by ID.
- Open http://localhost:8888/ in your browser
- Click "Run the Ritual" button
- Toggle the witch switch between "Legacy Curse" and "Modern Magic"
- Observe the data source indicator change
- Notice the premium Halloween theme with glassmorphism effects
./scripts/test_all.shThis executes:
- Smoke tests: Verify critical paths return 200
- Contract tests: Validate API responses against OpenAPI schema
- Golden tests: Compare legacy vs new data for semantic equivalence
- Property-based tests: Verify universal properties across 100+ iterations
Smoke Tests
./tests/test_smoke.shGolden Tests
./tests/test_golden.shProperty-Based Tests
# Gateway routing
./tests/test_property_gateway_routing.sh
# Data equivalence
./tests/test_property_data_equivalence.sh
# API contract compliance
cd new-api && pytest tests/test_property_contract_compliance.py./scripts/validate_openapi.shThis project was built using Kiro AI with a spec-driven development workflow:
Kiro helped create three foundational documents in .kiro/specs/strangler-studio/:
-
requirements.md: User stories with EARS-compliant acceptance criteria
- 10 requirements covering gateway routing, feature flags, API design, testing, and UI
- Each requirement includes 3-8 acceptance criteria following INCOSE quality rules
-
design.md: Comprehensive technical design
- Architecture diagrams and component specifications
- 5 correctness properties for property-based testing
- Data models, error handling, and UI design system
- Testing strategy with dual approach (unit + property tests)
-
tasks.md: Actionable implementation plan
- 20 tasks broken into sub-tasks
- Each task references specific requirements
- Property-based test tasks annotated with property numbers
- Optional tasks marked for flexible MVP development
Kiro used steering files in .kiro/steering/ to maintain consistency:
- code-quality.md: PHP CS Fixer, Black formatting, naming conventions
- testing-standards.md: 80% coverage targets, property-based testing patterns
- halloween-theme.md: Color palette, typography, glassmorphism effects
- api-conventions.md: REST design, status codes, error formats
These files were automatically included in Kiro's context during implementation.
Kiro configured automated workflows in .kiro/hooks/:
- validate-openapi.json: Validates OpenAPI on file save
- generate-client.json: Generates typed client after validation
- run-tests.json: Runs test suite on code changes
- Correctness-first: Property-based testing caught edge cases early
- Consistency: Steering files ensured uniform code style
- Traceability: Every task linked back to requirements
- Automation: Hooks prevented broken contracts from being committed
strangler-studio/
βββ .kiro/ # Kiro AI configuration
β βββ specs/strangler-studio/ # Spec documents
β β βββ requirements.md # User stories & acceptance criteria
β β βββ design.md # Technical design & properties
β β βββ tasks.md # Implementation task list
β βββ steering/ # Project guidelines
β β βββ code-quality.md
β β βββ testing-standards.md
β β βββ halloween-theme.md
β β βββ api-conventions.md
β βββ hooks/ # Automation hooks
β βββ validate-openapi.json
β βββ generate-client.json
β βββ run-tests.json
βββ contracts/
β βββ openapi.yaml # OpenAPI 3.0 specification
βββ gateway/
β βββ nginx.conf # Routing configuration
β βββ Dockerfile
βββ legacy-php/
β βββ public/
β β βββ index.php # Front controller
β βββ src/
β β βββ Controllers/ # MVC controllers
β β βββ Services/ # API client
β β βββ Views/ # HTML templates
β βββ styles/
β β βββ halloween.css # Premium theme
β βββ Dockerfile
βββ new-api/
β βββ app/
β β βββ main.py # FastAPI application
β β βββ models.py # Pydantic models
β β βββ data/
β β βββ seed_data.py # Deterministic test data
β βββ tests/
β β βββ test_property_*.py # Property-based tests
β β βββ test_*.py # Unit tests
β βββ requirements.txt
β βββ Dockerfile
βββ scripts/
β βββ demo.sh # Complete demo workflow
β βββ test_all.sh # Run all test suites
β βββ validate_openapi.sh # Validate contract
β βββ generate_client.sh # Generate typed client
βββ tests/
β βββ test_smoke.sh # Integration smoke tests
β βββ test_golden.sh # Legacy vs new comparison
β βββ test_property_gateway_routing.sh
β βββ test_property_data_equivalence.sh
βββ docker-compose.yml # Service orchestration
βββ README.md # This file
- Cinematic Design: Modern horror film aesthetic, not party decorations
- Glassmorphism: Frosted glass cards with backdrop blur
- Glow Effects: Atmospheric lighting on interactive elements
- Typography: Cinzel (headings) + Inter (body) from Google Fonts
- Color Palette:
- Deep black (#0a0a0a) background with grain texture
- Pumpkin orange (#ff6b35) for CTAs
- Ghostly cyan (#4ecdc4) for accents
- Blood red (#c1121f) for critical states
- Microinteractions: Hover glow, smooth transitions, animated gradients
- OpenAPI 3.0+ specification as source of truth
- Automatic schema validation with Pydantic
- Type-safe client generation
- Swagger UI at
/docsand ReDoc at/redoc
- Hypothesis library for Python tests
- Minimum 100 iterations per property
- 5 correctness properties validated:
- Gateway routing correctness
- API ID lookup correctness
- API response completeness
- OpenAPI contract compliance
- Legacy-to-new data semantic equivalence
- Toggle between legacy and new implementations
- Gradual migration without downtime
- Visual indicators showing data source
- Witch switch UI with thematic design
Problem: Error starting userland proxy: listen tcp4 0.0.0.0:80: bind: address already in use
Solution:
# Find process using port 80
sudo lsof -i :80
# Kill the process (replace PID)
sudo kill -9 <PID>
# Or change the port in docker-compose.yml
ports:
- "8080:80" # Access at http://localhost:8080Problem: Containers exit immediately or fail health checks
Solution:
# Check logs for specific service
docker-compose logs gateway
docker-compose logs legacy-php
docker-compose logs new-api
# Rebuild from scratch
docker-compose down -v
docker-compose up --buildProblem: Gateway can't reach backend services
Solution:
# Verify all services are running
docker-compose ps
# Check network connectivity
docker-compose exec gateway ping new-api
docker-compose exec legacy-php ping new-api
# Restart services
docker-compose restartProblem: Test suite returns non-zero exit code
Solution:
# Ensure services are running
docker-compose up -d
# Wait for health checks
sleep 10
# Run tests with verbose output
./scripts/test_all.sh
# Check individual test suites
./tests/test_smoke.sh
./tests/test_golden.shProblem: scripts/validate_openapi.sh reports errors
Solution:
# Check YAML syntax
yamllint contracts/openapi.yaml
# Validate against OpenAPI 3.0 spec
# Fix reported errors in contracts/openapi.yaml
# Regenerate client after fixes
./scripts/generate_client.shProblem: Landing page appears unstyled
Solution:
# Check file exists
ls -la legacy-php/styles/halloween.css
# Verify volume mount in docker-compose.yml
docker-compose config
# Restart legacy-php service
docker-compose restart legacy-php
# Clear browser cache and hard reload (Cmd+Shift+R)Problem: ./scripts/demo.sh: Permission denied
Solution:
# Make scripts executable
chmod +x scripts/*.sh
chmod +x tests/*.sh
# Run again
./scripts/demo.sh- API Service: 85% code coverage (exceeds 80% target)
- Property-Based Tests: 100 iterations per property, all passing
- Contract Tests: All endpoints validate against OpenAPI schema
- Golden Tests: Legacy and new data semantically equivalent
- Smoke Tests: All critical paths return 200 OK
This is a demonstration project, but contributions are welcome!
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Follow code quality standards (see
.kiro/steering/) - Ensure all tests pass (
./scripts/test_all.sh) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License - see below for details:
MIT License
Copyright (c) 2024 Strangler Studio
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
- Strangler Fig Pattern: Martin Fowler's architectural pattern for legacy migration
- FastAPI: Modern Python web framework with automatic OpenAPI generation
- Hypothesis: Property-based testing library for Python
- Kiro AI: AI-powered development assistant for spec-driven development
- Halloween Theme: Inspired by modern horror cinema and premium dark mode interfaces
- Strangler Fig Pattern
- OpenAPI Specification
- FastAPI Documentation
- Property-Based Testing
- Docker Compose
- Kiro AI
Built with β€οΈ and π using Kiro AI