# 🔄 Rebuild Guide - When You Need to Rebuild the Image

## Why Rebuild?

SvelteKit's `PUBLIC_*` environment variables are **baked into the JavaScript** at build time. You need to rebuild when:

1. ✅ Changing `PUBLIC_API_URL`
2. ✅ Changing `PUBLIC_URL`
3. ✅ Changing `PUBLIC_UMAMI_ID`
4. ✅ Changing `PUBLIC_UMAMI_SCRIPT`
5. ❌ NOT needed for Directus env vars (those are runtime)

## Quick Rebuild Process

### 1. Update Frontend Environment Variables

Edit the frontend `.env` file:

```bash
nano packages/frontend/.env
```

Set your production values:
```bash
PUBLIC_API_URL=https://sexy.pivoine.art/api
PUBLIC_URL=https://sexy.pivoine.art
PUBLIC_UMAMI_ID=your-umami-id
PUBLIC_UMAMI_SCRIPT=https://umami.pivoine.art/script.js
```

### 2. Rebuild the Image

```bash
# From the project root
docker build -t ghcr.io/valknarxxx/sexy:latest -t sexy.pivoine.art:latest .
```

**Expected Time:** 30-45 minutes (first build), 10-15 minutes (cached rebuild)

### 3. Restart Services

```bash
# If using docker-compose
cd /home/valknar/Projects/docker-compose/sexy
docker compose down
docker compose up -d

# Or directly
docker stop sexy_frontend
docker rm sexy_frontend
docker compose up -d frontend
```

## Monitoring the Build

### Check Build Progress

```bash
# Watch build output
docker build -t ghcr.io/valknarxxx/sexy:latest .

# Build stages:
# 1. Base (~30s) - Node.js setup
# 2. Builder (~25-40min) - Rust + WASM + packages
#    - Rust installation: ~2-3 min
#    - wasm-bindgen-cli: ~10-15 min
#    - WASM build: ~5-10 min
#    - Package builds: ~5-10 min
# 3. Runner (~2min) - Final image assembly
```

### Verify Environment Variables in Built Image

```bash
# Check what PUBLIC_API_URL is baked in
docker run --rm ghcr.io/valknarxxx/sexy:latest sh -c \
  "grep -r 'PUBLIC_API_URL' /home/node/app/packages/frontend/build/ | head -3"

# Should show: https://sexy.pivoine.art/api
```

## Push to GitHub Container Registry

After successful build:

```bash
# Login to GHCR (first time only)
echo $GITHUB_TOKEN | docker login ghcr.io -u valknarxxx --password-stdin

# Push the image
docker push ghcr.io/valknarxxx/sexy:latest
```

## Alternative: Build Arguments (Future Enhancement)

To avoid rebuilding for every env change, consider adding build arguments:

```dockerfile
# In Dockerfile, before building frontend:
ARG PUBLIC_API_URL=https://sexy.pivoine.art/api
ARG PUBLIC_URL=https://sexy.pivoine.art
ARG PUBLIC_UMAMI_ID=

# Create .env.production dynamically
RUN echo "PUBLIC_API_URL=${PUBLIC_API_URL}" > packages/frontend/.env.production && \
    echo "PUBLIC_URL=${PUBLIC_URL}" >> packages/frontend/.env.production && \
    echo "PUBLIC_UMAMI_ID=${PUBLIC_UMAMI_ID}" >> packages/frontend/.env.production
```

Then build with:
```bash
docker build \
  --build-arg PUBLIC_API_URL=https://sexy.pivoine.art/api \
  --build-arg PUBLIC_URL=https://sexy.pivoine.art \
  -t ghcr.io/valknarxxx/sexy:latest .
```

## Troubleshooting

### Build Fails at Rust Installation

```bash
# Check network connectivity
ping -c 3 sh.rustup.rs

# Build with verbose output
docker build --progress=plain -t ghcr.io/valknarxxx/sexy:latest .
```

### Build Fails at WASM

```bash
# Check if wasm-bindgen-cli matches package.json version
docker run --rm rust:latest cargo install wasm-bindgen-cli --version 0.2.103
```

### Frontend Still Shows Wrong URL

```bash
# Verify .env file is correct
cat packages/frontend/.env

# Check if old image is cached
docker images | grep sexy
docker rmi ghcr.io/valknarxxx/sexy:old-tag

# Force rebuild without cache
docker build --no-cache -t ghcr.io/valknarxxx/sexy:latest .
```

### Container Starts But Can't Connect to API

1. Check Traefik routing:
```bash
docker logs traefik | grep sexy
```

2. Check if Directus is accessible:
```bash
curl -I https://sexy.pivoine.art/api/server/health
```

3. Check frontend logs:
```bash
docker logs sexy_frontend
```

## Development vs Production

### Development (Local)
- Use `pnpm dev` for hot reload
- No rebuild needed for code changes
- Env vars from `.env` or shell

### Production (Docker)
- Rebuild required for PUBLIC_* changes
- Changes baked into JavaScript
- Env vars from `packages/frontend/.env`

## Optimization Tips

### Speed Up Rebuilds

1. **Use BuildKit cache:**
```bash
export DOCKER_BUILDKIT=1
docker build --build-arg BUILDKIT_INLINE_CACHE=1 -t ghcr.io/valknarxxx/sexy:latest .
```

2. **Multi-stage caching:**
- Dockerfile already optimized with multi-stage build
- Dependencies cached separately from code

3. **Parallel builds:**
```bash
# Build with more CPU cores
docker build --cpus 4 -t ghcr.io/valknarxxx/sexy:latest .
```

### Reduce Image Size

Current optimizations:
- ✅ Multi-stage build
- ✅ Production dependencies only
- ✅ Minimal base image
- ✅ No dev tools in final image

Expected sizes:
- Base: ~100MB
- Builder: ~2-3GB (not shipped)
- Runner: ~300-500MB (final)

## Automation

### GitHub Actions (Already Set Up)

The `.github/workflows/docker-build-push.yml` automatically:
1. Builds on push to main
2. Creates version tags
3. Pushes to GHCR
4. Caches layers for faster builds

**Trigger a rebuild:**
```bash
git tag v1.0.1
git push origin v1.0.1
```

### Local Build Script

Use the provided `build.sh`:
```bash
./build.sh -t v1.0.0 -p
```

## When NOT to Rebuild

You DON'T need to rebuild for:
- ❌ Directus configuration changes
- ❌ Database credentials
- ❌ Redis settings
- ❌ SMTP settings
- ❌ Session cookie settings
- ❌ Traefik labels

These are runtime environment variables and can be changed in docker-compose.

## Summary

| Change | Rebuild Needed | How to Apply |
|--------|----------------|--------------|
| `PUBLIC_API_URL` | ✅ Yes | Rebuild image |
| `PUBLIC_URL` | ✅ Yes | Rebuild image |
| `PUBLIC_UMAMI_ID` | ✅ Yes | Rebuild image |
| `PUBLIC_UMAMI_SCRIPT` | ✅ Yes | Rebuild image |
| `SEXY_DIRECTUS_*` | ❌ No | Restart container |
| `DB_*` | ❌ No | Restart container |
| `EMAIL_*` | ❌ No | Restart container |
| Traefik labels | ❌ No | Restart container |

---

**Remember:** The key difference is **build-time** (compiled into JS) vs **runtime** (read from environment).
