This document outlines the refactoring from a scattered experimental structure to a clean, production-ready monorepo.
The following experimental and deprecated directories have been removed:
enterprise_upgrade_pack/- Experimental enterprise featuresenterprise_upgrade_pack_v3/- Deprecated versiondigicloset-upgrade-pack/- Dev scaffolddigicloset-upgrade-pack-complete/- Old upgrade packdigi_upgrade_pack/- Duplicate scaffolddigi_reorg_scaffold/- Experimental reorganizationarchive/- Old archived codedocs_ops_clear/- Outdated documentationfrontend_clear/- Old frontend experimentdigicloset_shopify_revenue_features/- Moved into main appsecurity_hardening_pack_v1/- Integrated into main servicesai-service-layer/- Consolidated with primary AI service
The main FastAPI application moved to the new Shopify app structure:
app/
├── ai/ → apps/shopify-app/backend/ai/
├── api/ → apps/shopify-app/backend/api/
├── core/ → apps/shopify-app/backend/core/
├── db/ → apps/shopify-app/backend/db/
├── middleware/ → apps/shopify-app/backend/middleware/
├── models/ → apps/shopify-app/backend/models/
├── optimizations/ → apps/shopify-app/backend/optimizations/
├── routes/ → apps/shopify-app/backend/routes/
├── services/ → apps/shopify-app/backend/services/
├── utils/ → apps/shopify-app/backend/utils/
└── main.py → apps/shopify-app/backend/main.py
AI recommendation engine moved to dedicated service:
ai_service/
├── embeddings/ → services/ai-service/embeddings/
├── indexing/ → services/ai-service/indexing/
├── recommendation/ → services/ai-service/recommendation/
├── vector_db/ → services/ai-service/vector_db/
├── api/ → services/ai-service/api/
├── main.py → services/ai-service/main.py
└── requirements.txt → services/ai-service/requirements.txt
Shopify integration moved to app directory:
shopify-app-core/
├── index.js → apps/shopify-app/index.js (OAuth backend)
├── widget.js → apps/shopify-app/widget.js (Storefront widget)
├── admin-ui/ → apps/shopify-app/admin-ui/
├── package.json → apps/shopify-app/package.json
└── shopify.config.js → apps/shopify-app/shopify.config.js
Billing logic moved to Shopify app:
backend/
├── billing_service.py → apps/shopify-app/billing/billing_service.py
├── metrics_service.py → apps/shopify-app/billing/metrics_service.py
├── catalog_service.py → apps/shopify-app/billing/catalog_service.py
└── config/ → apps/shopify-app/billing/config/
Inference service moved to services directory:
inference_service/
├── main.py → services/inference-service/main.py
└── requirements.txt → services/inference-service/requirements.txt
Background job processor:
worker.py → services/queue-worker/worker.py
Shared job definitions moved to shared packages:
jobs/
├── redis_conn.py → packages/shared/jobs/redis_conn.py
├── ai_jobs.py → packages/shared/jobs/ai_jobs.py
└── ... → packages/shared/jobs/...
Database schema moved to database package:
prisma/
└── schema.prisma → packages/database/schema.prisma
Configuration files moved to shared package:
config/
├── config.json → packages/shared/config/config.json
├── feature_flags.json → packages/shared/config/feature_flags.json
└── ... → packages/shared/config/...
/packages/shared - Core shared utilities:
packages/shared/
├── __init__.py
├── config.py # Centralized configuration management
├── logging.py # Structured JSON logging
├── types.py # Pydantic models and schemas
├── exceptions.py # Custom exception classes
├── redis_utils.py # Redis connection and caching utilities
├── requirements.txt # Shared dependencies
└── jobs/ # Job definitions and utilities
/packages/database - Database package:
packages/database/
└── schema.prisma # Prisma ORM schema
/packages/storage - Storage adapters:
packages/storage/
├── __init__.py
├── base.py # Abstract storage interface
├── local.py # Local filesystem adapter
└── s3.py # Amazon S3 adapter
/infra/docker - Service Dockerfiles:
infra/docker/
├── Dockerfile.shopify-app # Main app container
├── Dockerfile.ai-service # AI service container
├── Dockerfile.inference-service # Inference service container
└── Dockerfile.queue-worker # Queue worker container
/infra/k8s - Kubernetes manifests:
infra/k8s/
├── shopify-app-deployment.yaml
├── ai-service-deployment.yaml
├── inference-service-deployment.yaml
├── queue-worker-deployment.yaml
├── postgres-statefulset.yaml
├── redis-deployment.yaml
└── ingress.yaml
/infra/ci-cd - CI/CD pipelines (moved from cicd-workflows/)
All code now uses absolute imports from the monorepo root.
# From app/main.py
from app.api.router import api_router
from app.core.config import settings
from app.db.models import Shop
# From ai_service/main.py
from ai_service.embeddings import CLIPEmbedder
from ai_service.utils import setup_logging# From apps/shopify-app/backend/main.py
from packages.shared.config import config
from apps.shopify_app.backend.api.router import api_router
from apps.shopify_app.backend.db.models import Shop
# From services/ai-service/main.py
from packages.shared.config import config
from packages.shared.logging import get_logger
from services.ai_service.embeddings import CLIPEmbedderImporting from shared packages:
# Configuration
from packages.shared.config import config
# Logging
from packages.shared.logging import get_logger, configure_logging
# Types and responses
from packages.shared.types import APIResponse, ErrorResponse, Status
from packages.shared.types import ShopSchema, AiResultSchema, OutfitSchema
# Exceptions
from packages.shared.exceptions import (
ValidationError,
AuthenticationError,
NotFoundError,
RateLimitError,
)
# Redis utilities
from packages.shared.redis_utils import (
get_redis_connection,
cache_result,
invalidate_cache,
)
# Job definitions
from packages.shared.jobs.ai_jobs import AnalyzeProductJobImporting from database package:
# Prisma client (after generate)
from packages.database.prisma_client import PrismaClientImporting from storage package:
from packages.storage import get_storage_adapter
# Use
storage = get_storage_adapter()
await storage.upload("key", data)Importing from services (cross-service):
# Shopify App → AI Service (via HTTP, not imports!)
import httpx
async def get_recommendations(product_id: str):
async with httpx.AsyncClient() as client:
response = await client.post(
"http://ai-service:8001/api/v1/search",
json={"product_id": product_id}
)
return response.json()Importing within same service:
# Within apps/shopify-app/backend/
from .api.router import api_router
from .services.ai_service import AIService
from .core.config import settings
# Within services/ai-service/
from .embeddings import CLIPEmbedder
from .recommendation import RecommenderEnsure Python path includes monorepo root:
export PYTHONPATH=/path/to/digicloset:$PYTHONPATHAlready configured in Dockerfiles:
ENV PYTHONPATH=/app:$PYTHONPATHUpdate your IDE's Python path to include the monorepo root.
For each service being updated:
- Update all relative imports to absolute imports
- Replace local config references with
packages.shared.config - Update logging to use
packages.shared.logging - Update exception handling to use
packages.shared.exceptions - Update type definitions to use
packages.shared.types - Update Redis connections to use
packages.shared.redis_utils - Test all imports work with
python -c "import module" - Run tests:
pytest - Build Docker image:
docker build -f infra/docker/Dockerfile.xxx .
docker-compose -f docker-compose.dev.yml upAll services will start with hot reload enabled.
Shopify App:
cd apps/shopify-app/backend
PYTHONPATH=/path/to/digicloset:$PYTHONPATH \
uvicorn main:app --port 8000 --reloadAI Service:
cd services/ai-service
PYTHONPATH=/path/to/digicloset:$PYTHONPATH \
uvicorn main:app --port 8001 --reloadQueue Worker:
cd services/queue-worker
PYTHONPATH=/path/to/digicloset:$PYTHONPATH \
python worker.pycd packages/database
# Generate Prisma client
npx prisma generate
# Run migrations
npx prisma migrate deploy
# Or create database from schema
npx prisma db pushAll services use DATABASE_URL from .env:
from packages.shared.config import config
db_url = config.DATABASE_URL
# postgresql://digicloset:digicloset_dev@localhost:5432/digicloset-
Copy
.env.exampleto.env:cp .env.example .env
-
Update with actual values:
SHOPIFY_API_KEY=your-key SHOPIFY_API_SECRET=your-secret DATABASE_URL=postgresql://user:password@host:5432/digicloset REDIS_URL=redis://localhost:6379/0 -
Load environment:
set -a source .env set +a
Error: ModuleNotFoundError: No module named 'packages.shared'
Solution: Ensure PYTHONPATH includes monorepo root:
export PYTHONPATH=/path/to/digicloset:$PYTHONPATHError: ConnectionError: HTTPConnectError to http://ai-service:8001
Solution: In development, use localhost:
ai_service_url = "http://localhost:8001" # Development
ai_service_url = "http://ai-service:8001" # Docker/K8sError: ModuleNotFoundError: prisma not found
Solution: Generate Prisma client:
cd packages/database
npx prisma generateError: FATAL: remaining connection slots reserved for non-replication superuser connections
Solution: Check database is running and DATABASE_URL is correct.
- ✅ Clean repository structure created
- ✅ All code consolidated into services/packages
- ✅ Shared utilities extracted
- ✅ Docker and deployment files created
- ⏳ Update imports in all service files (in progress)
- ⏳ Test all services locally
- ⏳ Update CI/CD pipelines if needed
- ⏳ Document any API changes
- No performance impact from monorepo structure
- Services still run independently
- Shared code is imported, not duped
- Docker images are built per-service for efficiency
- Local development is simplified with docker-compose
For questions about the new structure or specific import patterns, refer to ARCHITECTURE.md or inline code comments.