# Sites & Site Builder Removal Guide **Version:** 1.0 **Date:** November 29, 2025 **Purpose:** Complete guide to remove separate sites/site-builder containers and integrate functionality into main frontend app --- ## Executive Summary This document provides a **safe, step-by-step process** to: 1. Remove the `/sites/` container and folder 2. Remove the `/site-builder/` folder (already empty/deprecated) 3. Integrate Sites Renderer and Site Builder features into the main `/frontend/` application 4. Update all affected components, configurations, and documentation **Current State:** - 3 separate containers: `igny8_frontend`, `igny8_sites`, `igny8_marketing_dev` - Site Builder UI in separate `/sites/` container (port 8024) - Sites Renderer in separate `/sites/` container (port 8024) **Target State:** - 2 containers: `igny8_frontend`, `igny8_marketing_dev` - Site Builder UI integrated into main frontend - Sites Renderer integrated into main frontend - Single unified application on port 8021 --- ## Impact Analysis ### Features That Will Be Affected #### 1. **Site Blueprint Management** (Site Builder) **Current Location:** `/sites/src/builder/` **Current Routes:** `/builder/*` (separate container) **Functionality:** - Site structure wizard - Blueprint creation and management - Preview canvas for site layouts - Blueprint history dashboard **Backend Dependencies:** - API: `/api/v1/site-builder/blueprints/` - Module: `backend/igny8_core/modules/site_builder/` - Business Logic: `backend/igny8_core/business/site_building/` **Impact:** Medium - Needs route integration into main app --- #### 2. **Sites Renderer** (Public Site Viewing) **Current Location:** `/sites/src/pages/SiteRenderer.tsx` **Current Routes:** `/:siteSlug/:pageSlug?` (separate container) **Functionality:** - Loads site definitions from `/data/app/sites-data/` - Renders published sites for public viewing - No authentication required **Backend Dependencies:** - API: `/api/v1/publisher/sites/{site_id}/definition/` - Service: `backend/igny8_core/business/publishing/services/adapters/sites_renderer_adapter.py` - Data: `/data/app/sites-data/clients/{site_id}/v{version}/` **Impact:** High - Public-facing feature, needs careful route handling --- #### 3. **Backend Modules** (Keep These) **Modules to Keep:** ``` backend/igny8_core/ ├── modules/ │ ├── site_builder/ ✅ KEEP (API endpoints) │ └── publisher/ ✅ KEEP (publishing logic) └── business/ ├── site_building/ ✅ KEEP (business logic) └── publishing/ ✅ KEEP (renderer adapter) ``` **Rationale:** Backend functionality is used by the main frontend app, just changing the UI container. --- ## Removal & Integration Plan ### Phase 1: Preparation & Backup #### Step 1.1: Create Backup ```bash # Backup current state cd /data/app/igny8 tar -czf backup-sites-$(date +%Y%m%d-%H%M%S).tar.gz sites/ site-builder/ # Backup docker-compose cp docker-compose.app.yml docker-compose.app.yml.backup # Verify backup ls -lh backup-sites-*.tar.gz ``` #### Step 1.2: Document Current Routes ```bash # Document current running containers docker ps | grep igny8 > current-containers.txt # Test current site builder access curl -I http://localhost:8024/builder/ # Test current sites renderer curl -I http://localhost:8024/ ``` --- ### Phase 2: Frontend Integration #### Step 2.1: Copy Site Builder Components to Frontend **Source:** `/sites/src/builder/` **Destination:** `/frontend/src/pages/Sites/` ```bash cd /data/app/igny8 # Create target directory mkdir -p frontend/src/pages/Sites/Builder # Copy builder components cp -r sites/src/builder/pages/* frontend/src/pages/Sites/Builder/ cp -r sites/src/builder/components/* frontend/src/components/sites/builder/ # Copy shared types if needed cp sites/src/types/index.ts frontend/src/types/siteBuilder.types.ts ``` **Files to Copy:** ``` sites/src/builder/ ├── pages/ │ ├── wizard/ │ │ └── WizardPage.tsx → frontend/src/pages/Sites/Builder/Wizard.tsx │ ├── preview/ │ │ └── PreviewCanvas.tsx → frontend/src/pages/Sites/Builder/Preview.tsx │ └── dashboard/ │ └── SiteDashboard.tsx → frontend/src/pages/Sites/Builder/Dashboard.tsx └── components/ └── layout/ └── BuilderLayout.tsx → frontend/src/components/sites/BuilderLayout.tsx ``` --- #### Step 2.2: Copy Sites Renderer to Frontend **Source:** `/sites/src/pages/SiteRenderer.tsx` **Destination:** `/frontend/src/pages/Sites/` ```bash # Copy renderer components cp sites/src/pages/SiteRenderer.tsx frontend/src/pages/Sites/PublicSiteRenderer.tsx cp sites/src/loaders/loadSiteDefinition.ts frontend/src/services/siteRenderer.api.ts cp -r sites/src/utils/* frontend/src/utils/siteRenderer/ ``` **Files to Copy:** ``` sites/src/ ├── pages/ │ └── SiteRenderer.tsx → frontend/src/pages/Sites/PublicSiteRenderer.tsx ├── loaders/ │ └── loadSiteDefinition.ts → frontend/src/services/siteRenderer.api.ts └── utils/ ├── layoutRenderer.tsx → frontend/src/utils/siteRenderer/layoutRenderer.tsx ├── pageTypeRenderer.tsx → frontend/src/utils/siteRenderer/pageTypeRenderer.tsx └── templateEngine.tsx → frontend/src/utils/siteRenderer/templateEngine.tsx ``` --- #### Step 2.3: Update Frontend Routes **File:** `/frontend/src/App.tsx` **Add these imports:** ```tsx // Site Builder pages const SiteBuilderWizard = lazy(() => import("./pages/Sites/Builder/Wizard")); const SiteBuilderPreview = lazy(() => import("./pages/Sites/Builder/Preview")); const SiteBuilderDashboard = lazy(() => import("./pages/Sites/Builder/Dashboard")); // Public Sites Renderer const PublicSiteRenderer = lazy(() => import("./pages/Sites/PublicSiteRenderer")); ``` **Add these routes:** ```tsx {/* Site Builder Routes - Protected */} } /> } /> } /> {/* Public Sites Renderer - No Auth Required */} } /> ``` **Note:** Public renderer routes changed from `/:siteSlug/*` to `/sites/view/:siteSlug/*` to avoid route conflicts. --- #### Step 2.4: Update API Client for Sites Data **File:** `/frontend/src/services/siteRenderer.api.ts` **Update the API URL resolution:** ```typescript function getApiBaseUrl(): string { // Use environment variable const envUrl = import.meta.env.VITE_API_URL || import.meta.env.VITE_BACKEND_URL; if (envUrl) { return envUrl.endsWith('/api') ? envUrl : `${envUrl}/api`; } // Auto-detect based on current origin if (typeof window !== 'undefined') { const origin = window.location.origin; // If accessing via IP, use backend port 8011 if (/^\d+\.\d+\.\d+\.\d+/.test(origin) || origin.includes('localhost')) { return origin.replace(':8021', ':8011') + '/api'; } } // Production: use subdomain return 'https://api.igny8.com/api'; } ``` --- #### Step 2.5: Update Navigation Menu **File:** `/frontend/src/components/sidebar/AppSidebar.tsx` or navigation component **Add Site Builder menu item:** ```tsx { title: "Site Builder", icon: , items: [ { title: "New Blueprint", path: "/sites/builder" }, { title: "Preview", path: "/sites/builder/preview" }, { title: "History", path: "/sites/builder/dashboard" }, ], } ``` --- ### Phase 3: Docker Configuration Updates #### Step 3.1: Update docker-compose.app.yml **File:** `/docker-compose.app.yml` **Remove the igny8_sites service:** ```yaml # REMOVE THIS ENTIRE SERVICE: # igny8_sites: # image: igny8-sites-dev:latest # container_name: igny8_sites # restart: always # ports: # - "0.0.0.0:8024:5176" # environment: # VITE_API_URL: "https://api.igny8.com/api" # SITES_DATA_PATH: "/sites" # volumes: # - /data/app/igny8/sites:/app:rw # - /data/app/sites-data:/sites:ro # - /data/app/igny8/frontend:/frontend:ro # networks: [igny8_net] ``` **Update igny8_frontend service to access sites-data:** ```yaml igny8_frontend: image: igny8-frontend-dev:latest container_name: igny8_frontend restart: always ports: - "0.0.0.0:8021:5173" environment: VITE_BACKEND_URL: "https://api.igny8.com/api" SITES_DATA_PATH: "/sites" # ADD THIS volumes: - /data/app/igny8/frontend:/app:rw - /data/app/sites-data:/sites:ro # ADD THIS - Read-only access to sites data depends_on: igny8_backend: condition: service_healthy networks: [igny8_net] ``` --- #### Step 3.2: Update Vite Configuration **File:** `/frontend/vite.config.ts` **Add environment variable for sites data path:** ```typescript export default defineConfig({ // ... existing config define: { 'import.meta.env.SITES_DATA_PATH': JSON.stringify( process.env.SITES_DATA_PATH || '/sites' ), }, // ... rest of config }); ``` --- ### Phase 4: Backend Updates (Minor) #### Step 4.1: Update CORS Settings (if needed) **File:** `/backend/igny8_core/settings.py` **Verify CORS allows frontend port:** ```python CORS_ALLOWED_ORIGINS = [ 'http://localhost:5173', # Frontend dev server 'http://localhost:8021', # Frontend external port 'https://app.igny8.com', # Remove: 'http://localhost:8024', # Old sites container ] ``` --- #### Step 4.2: Update Site Definition API (Optional Enhancement) **File:** `/backend/igny8_core/modules/publisher/views.py` **No changes required** - API already works, just being called from different container. **Optional:** Add CORS header for public site renderer if needed: ```python from rest_framework.decorators import api_view, permission_classes from rest_framework.permissions import AllowAny @api_view(['GET']) @permission_classes([AllowAny]) # Public endpoint def get_site_definition(request, site_id): # ... existing code ``` --- ### Phase 5: Testing & Verification #### Step 5.1: Build Updated Frontend ```bash cd /data/app/igny8/frontend # Install any new dependencies (if added) npm install # Build to verify no errors npm run build # Rebuild Docker image cd /data/app/igny8/frontend docker build -t igny8-frontend-dev:latest -f Dockerfile.dev . ``` --- #### Step 5.2: Stop Old Container ```bash # Stop and remove sites container docker stop igny8_sites docker rm igny8_sites # Verify it's stopped docker ps | grep sites ``` --- #### Step 5.3: Start Updated Stack ```bash cd /data/app/igny8 # Start with updated docker-compose docker compose -f docker-compose.app.yml up -d igny8_frontend # Check logs docker logs -f igny8_frontend ``` --- #### Step 5.4: Test Functionality **Test Site Builder:** ```bash # Test builder routes (should require auth) curl -I http://localhost:8021/sites/builder # Test in browser: # http://localhost:8021/sites/builder (wizard) # http://localhost:8021/sites/builder/preview # http://localhost:8021/sites/builder/dashboard ``` **Test Sites Renderer:** ```bash # Test public site renderer curl -I http://localhost:8021/sites/view/test-site # Test in browser: # http://localhost:8021/sites/view/{siteSlug} # http://localhost:8021/sites/view/{siteSlug}/{pageSlug} ``` **Test Existing API:** ```bash # Verify site builder API still works curl -H "Authorization: Bearer YOUR_JWT_TOKEN" \ http://localhost:8011/api/v1/site-builder/blueprints/ # Verify site definition API curl http://localhost:8011/api/v1/publisher/sites/1/definition/ ``` --- ### Phase 6: Cleanup #### Step 6.1: Remove Folders (After Verification) **Only after confirming everything works:** ```bash cd /data/app/igny8 # Remove sites folder rm -rf sites/ # Remove site-builder folder (already empty) rm -rf site-builder/ # Remove empty frontend module rm -rf frontend/src/modules/siteBuilder/ # Verify removal ls -la | grep -E "site-builder|sites" ``` --- #### Step 6.2: Remove Docker Image (Optional) ```bash # Remove unused sites image docker rmi igny8-sites-dev:latest # Verify docker images | grep sites ``` --- #### Step 6.3: Clean Up Build Instructions **File:** `/docker-compose.app.yml` (comments at top) **Remove this line:** ```yaml # Remove: # cd /data/app/igny8/sites && docker build -t igny8-sites-dev:latest -f Dockerfile.dev . ``` --- ### Phase 7: Update Documentation #### Step 7.1: Update Files List **Files to update:** 1. **README.md** - Remove references to `/sites/` container - Update port mapping (remove 8024) - Update build instructions 2. **CHANGELOG.md** - Add entry: "Merged Sites & Site Builder into main frontend app" 3. **docs/MASTER_REFERENCE.md** - Update architecture diagram - Remove igny8_sites container reference - Update route documentation 4. **docs/API-COMPLETE-REFERENCE.md** - Update base URLs if needed - Verify endpoint documentation --- #### Step 7.2: Update Architecture Diagram **In MASTER_REFERENCE.md, update:** **OLD:** ``` ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐ │ Frontend (8021) │ │ Sites (8024) │ │ Backend (8011) │ └──────────────────┘ └──────────────────┘ └──────────────────┘ ``` **NEW:** ``` ┌──────────────────┐ ┌──────────────────┐ │ Frontend (8021) │ │ Backend (8011) │ │ - Main App │ │ - Django API │ │ - Site Builder │ │ - Celery │ │ - Site Renderer │ │ │ └──────────────────┘ └──────────────────┘ ``` --- ## Files & Folders Impact Summary ### Files to Modify | File | Action | Reason | |------|--------|--------| | `/frontend/src/App.tsx` | **UPDATE** | Add site builder and renderer routes | | `/frontend/src/services/siteRenderer.api.ts` | **CREATE** | Site renderer API client | | `/frontend/src/pages/Sites/Builder/` | **CREATE** | Copy from sites/src/builder/ | | `/frontend/src/components/sites/builder/` | **CREATE** | Builder components | | `/frontend/vite.config.ts` | **UPDATE** | Add SITES_DATA_PATH env var | | `/docker-compose.app.yml` | **UPDATE** | Remove igny8_sites service | | `/backend/igny8_core/settings.py` | **VERIFY** | CORS settings (minor) | | `/README.md` | **UPDATE** | Architecture docs | | `/docs/MASTER_REFERENCE.md` | **UPDATE** | Remove sites container refs | --- ### Files to Delete (After Verification) | File/Folder | Safe to Delete | Notes | |-------------|----------------|-------| | `/sites/` | ✅ YES | After copying to frontend | | `/site-builder/` | ✅ YES | Already empty | | `/frontend/src/modules/siteBuilder/` | ✅ YES | Empty folders | | `docker-compose.app.yml.backup` | ✅ YES | After successful migration | | `backup-sites-*.tar.gz` | ⚠️ KEEP | Keep for 30 days as rollback | --- ### Backend Files - NO CHANGES NEEDED **These stay exactly as they are:** ``` backend/igny8_core/ ├── modules/ │ ├── site_builder/ ✅ KEEP - No changes │ └── publisher/ ✅ KEEP - No changes ├── business/ │ ├── site_building/ ✅ KEEP - No changes │ └── publishing/ ✅ KEEP - No changes └── api/ └── wordpress_publishing.py ✅ KEEP - No changes ``` **Rationale:** Backend APIs remain unchanged; only the frontend UI container changes. --- ## Rollback Plan If issues occur, rollback is simple: ### Option 1: Quick Rollback (Docker) ```bash # Restore backup docker-compose cp docker-compose.app.yml.backup docker-compose.app.yml # Restart sites container docker compose -f docker-compose.app.yml up -d igny8_sites # Verify docker ps | grep sites curl -I http://localhost:8024/ ``` --- ### Option 2: Full Rollback (Restore Files) ```bash # Extract backup cd /data/app/igny8 tar -xzf backup-sites-YYYYMMDD-HHMMSS.tar.gz # Rebuild image cd sites docker build -t igny8-sites-dev:latest -f Dockerfile.dev . # Restart docker compose -f docker-compose.app.yml up -d igny8_sites ``` --- ## Migration Checklist **Pre-Migration:** - [ ] Backup `/sites/` folder - [ ] Backup `/docker-compose.app.yml` - [ ] Document current container ports - [ ] Test current site builder functionality - [ ] Test current sites renderer functionality **Migration Steps:** - [ ] Copy site builder components to `/frontend/src/pages/Sites/Builder/` - [ ] Copy sites renderer to `/frontend/src/pages/Sites/PublicSiteRenderer.tsx` - [ ] Copy utilities to `/frontend/src/utils/siteRenderer/` - [ ] Update `/frontend/src/App.tsx` with new routes - [ ] Create `/frontend/src/services/siteRenderer.api.ts` - [ ] Update `/frontend/vite.config.ts` - [ ] Update `/docker-compose.app.yml` (remove igny8_sites, update igny8_frontend) - [ ] Rebuild frontend Docker image - [ ] Stop igny8_sites container - [ ] Start updated igny8_frontend container **Testing:** - [ ] Test site builder wizard at `/sites/builder` - [ ] Test site builder preview at `/sites/builder/preview` - [ ] Test site builder dashboard at `/sites/builder/dashboard` - [ ] Test public site renderer at `/sites/view/{siteSlug}` - [ ] Verify API calls work from frontend - [ ] Check browser console for errors - [ ] Test with authenticated user - [ ] Test without authentication (public renderer) **Post-Migration:** - [ ] Verify all tests pass - [ ] Update documentation (README, MASTER_REFERENCE) - [ ] Remove `/sites/` folder - [ ] Remove `/site-builder/` folder - [ ] Remove empty `/frontend/src/modules/siteBuilder/` - [ ] Remove Docker image `igny8-sites-dev:latest` - [ ] Keep backup for 30 days - [ ] Update portable package documentation --- ## FAQ ### Q: Will this break existing site blueprints? **A:** No. Backend database and APIs remain unchanged. Only the UI container changes. ### Q: What about published sites in `/data/app/sites-data/`? **A:** They remain accessible. The frontend will mount `/sites-data` and load from there. ### Q: Do I need to update WordPress integration? **A:** No. WordPress talks to backend API, which doesn't change. ### Q: What if I want to keep sites as separate container? **A:** Keep current setup. This migration is optional for simplification. ### Q: Will public site URLs change? **A:** Yes, from `http://localhost:8024/:siteSlug` to `http://localhost:8021/sites/view/:siteSlug`. Update any hardcoded links. ### Q: Can I run both containers during transition? **A:** Yes, for testing. Run sites on 8024 and updated frontend on 8021, compare functionality. --- ## Support & Troubleshooting ### Issue: Routes not working after migration **Solution:** Check route order in `App.tsx`. Public renderer routes should be after protected routes. ### Issue: API calls failing **Solution:** Verify `VITE_BACKEND_URL` in environment and check CORS settings. ### Issue: Sites data not loading **Solution:** Verify `/data/app/sites-data` is mounted in docker-compose frontend service. ### Issue: Build errors **Solution:** Run `npm install` to ensure dependencies match between sites and frontend. --- ## Timeline Estimate | Phase | Time | Complexity | |-------|------|------------| | Phase 1: Preparation | 30 min | Low | | Phase 2: Frontend Integration | 2-3 hours | Medium | | Phase 3: Docker Updates | 30 min | Low | | Phase 4: Backend Updates | 15 min | Low | | Phase 5: Testing | 1-2 hours | Medium | | Phase 6: Cleanup | 15 min | Low | | Phase 7: Documentation | 1 hour | Low | | **Total** | **5-7 hours** | **Medium** | --- **End of Document**