Multi-repository architecture for MTAV application
This is an orchestrator repository that brings together independent backend and frontend services through Docker Compose. The architecture enables maximum flexibility - swap any component without affecting others.
mtav-stack/ # This repo (orchestrator)
├── docker-compose.yml # Service orchestration
├── mtav # Unified development script
├── .env.example # Environment template
├── api/ # Git submodule → mtav-api
│ └── Django REST API
└── spa/ # Git submodule → mtav-spa
└── React SPA
- Purpose: Orchestration and development environment
- Contains: Docker setup, scripts, integration configuration
- URL: TBD (will be created)
- Purpose: Backend REST API (framework-agnostic)
- Current: Django REST Framework
- Contract: REST API endpoints + JSON schemas
- Swappable: Django, Rails, Laravel (without Inertia), FastAPI, etc.
- URL: TBD (will be created)
- Purpose: Frontend SPA (backend-agnostic)
- Current: React + TypeScript
- Contract: Consumes REST API from any backend
- Swappable: React, Vue, Svelte, Angular, etc.
- URL: TBD (will be created)
# Clone with submodules
git clone --recursive [mtav-stack-url]
cd mtav-stack
# Or if already cloned without submodules
git submodule update --init --recursive
# Start everything
./mtav up./mtav up # Start all services
./mtav logs # View logs
./mtav test # Run all tests
./mtav down # Stop everythingWhen running, the following services are available:
- Frontend: http://localhost:3000
- Backend API: http://localhost:8000/api
- API Docs: http://localhost:8000/api/docs/
- Admin Panel: http://localhost:8000/admin
- MailHog: http://localhost:8025
- PostgreSQL: localhost:5432
- Redis: localhost:6379
The backend and frontend communicate solely through a REST API contract:
POST /api/auth/register/- User registrationPOST /api/auth/login/- User login (returns JWT)POST /api/auth/refresh/- Refresh access tokenGET /api/auth/me/- Get current user
GET|POST /api/projects/- Projects list/createGET|PUT|DELETE /api/projects/{id}/- Project detailGET|POST /api/families/- Families list/createGET|PUT|DELETE /api/families/{id}/- Family detailGET|POST /api/units/- Units list/create- ... (see API docs at http://localhost:8000/api/docs/)
All requests/responses use JSON with standard REST conventions.
cd mtav-stack
git submodule deinit api
git rm api
git submodule add [mtav-rails-api-url] api
./mtav rebuild backendThe new backend just needs to implement the same REST contract.
cd mtav-stack
git submodule deinit spa
git rm spa
git submodule add [mtav-vue-spa-url] spa
./mtav rebuild frontendThe new frontend just needs to consume the same REST API.
cd api/
# Make changes
git add .
git commit -m "Add feature"
git push
# Back to orchestrator to update reference
cd ..
git add api
git commit -m "Update api submodule"
git pushcd spa/
# Make changes
git add .
git commit -m "Add component"
git push
# Back to orchestrator to update reference
cd ..
git add spa
git commit -m "Update spa submodule"
git pushChanges to docker-compose.yml, mtav script, or environment setup are done in this repo directly.
- Inertia: Tightly couples frontend and backend (server-driven routing, shared types)
- This: Loose coupling via REST API contract
- Benefit: Swap either side independently
- Problem: Each developer needs to configure Docker, scripts, integration
- This: One clone gets everything working
- Benefit: Unified development experience
- Problem: Frontend and backend version together, harder team separation
- This: Independent versioning and teams
- Benefit: Backend team and frontend team work independently
# All tests
./mtav test
# Backend only
./mtav test-backend
# Frontend only
./mtav test-frontend
# With coverage
./mtav coverage# Build production images
./mtav build production
# Deploy (configure for your platform)
./mtav deployCopy .env.example to .env and configure:
# Django
DEBUG=True
SECRET_KEY=your-secret-key
DATABASE_URL=postgresql://user:pass@db:5432/mtav
# CORS (for API access)
CORS_ALLOWED_ORIGINS=http://localhost:3000
# Email
EMAIL_BACKEND=django.core.mail.backends.smtp.EmailBackend
EMAIL_HOST=mailhog
EMAIL_PORT=1025All data is scoped to projects. Users only see data from projects they're assigned to. Superadmins bypass scoping.
This is enforced at the API level (Django) and transparent to the frontend (React).
Each repository has its own contribution guidelines:
- api/: See
api/README.md - spa/: See
spa/README.md - orchestrator: This file
MIT
- Original Laravel/Vue/Inertia version: devvir/mtav
- Django/React decoupled version: Created for learning and experimentation