# Standalone Deployment Guide

> Mirrored from [`iblai/os`](https://github.com/iblai/os) · [`docs/standalone-deployment.md`](https://github.com/iblai/os/blob/main/docs/standalone-deployment.md). This page is generated — edit it in the repository, not here.

This app uses Next.js **standalone output** for optimized production deployments.

## What Changed

### 1. Next.js Configuration

- **Output mode**: Set to `'standalone'` in [next.config.ts](https://github.com/iblai/os/blob/main/next.config.ts#L34)
- Generates a self-contained server with minimal dependencies
- Reduces Docker image size significantly

### 2. Build Process

- **Build command**: `pnpm build` now runs:
  1. `next build` - Creates standalone output
  2. `./scripts/post-build.sh` - Copies static assets
- Static files (`.next/static/`, `public/`) are automatically copied to standalone output

### 3. Server Startup

- **Start command**: `pnpm start` runs `node server-wrapper.js`
- No longer uses `next start`
- Uses `PORT` environment variable instead of `-p` flag

### 4. Error Handling

- **server-wrapper.js**: Suppresses harmless HTMLElement errors during route pre-warming
- These errors don't affect functionality but were noisy in logs

## Local Development

### Development Mode

```bash
cd apps/mentor
pnpm dev  # Runs on http://localhost:3001
```

### Production Build & Test

```bash
cd apps/mentor

# Build
pnpm build

# Start on default port (3000)
pnpm start

# Start on custom port
PORT=3001 pnpm start
```

## Docker Deployment

### Building the Image

```bash
# From monorepo root
docker build \
  -f apps/mentor/Dockerfile \
  --build-arg NEXT_IMAGE_PATTERNS="https://example.com,https://cdn.example.com" \
  --build-arg NEXT_PUBLIC_BASE_PATH="" \
  -t mentor-app:latest \
  .
```

### Running the Container

```bash
# Default port (5000)
docker run -p 5000:5000 mentor-app:latest

# Custom port
docker run -p 8080:8080 -e PORT=8080 mentor-app:latest
```

### Environment Variables

- `PORT` - Server port (default: 5000 in Docker, 3000 locally)
- `NEXT_IMAGE_PATTERNS` - Comma-separated allowed image domains
- `NEXT_PUBLIC_BASE_PATH` - Base path for routing (e.g., `/mentor`)

## Dockerfile Changes

### Before (Old Approach)

```dockerfile
# Copied entire .next folder and all node_modules
COPY --from=builder /repo/apps/mentor/.next .next
COPY --from=builder /repo/node_modules ./node_modules
CMD ["pnpm", "exec", "next", "start", "-p", "5000"]
```

### After (Standalone)

```dockerfile
# Copy only standalone output (self-contained with minimal deps)
COPY --from=builder /repo/apps/mentor/.next/standalone ./
COPY --from=builder /repo/apps/mentor/server-wrapper.js ./apps/mentor/
ENV PORT=5000
CMD ["node", "server-wrapper.js"]
```

### Benefits

- **Smaller image size**: Only includes production dependencies
- **Faster startup**: No pnpm overhead
- **Better security**: Minimal attack surface
- **Simpler deployment**: Self-contained output

## File Structure

### Standalone Output

```
.next/standalone/
├── apps/
│   └── mentor/
│       ├── .next/
│       │   ├── server/          # Server-side code
│       │   └── static/          # Static assets (copied by post-build.sh)
│       ├── public/              # Public files (copied by post-build.sh)
│       ├── server.js            # Next.js standalone server
│       └── server-wrapper.js    # Error handling wrapper
├── node_modules/                # Minimal production deps
└── packages/                    # Shared packages
```

## Scripts

### [post-build.sh](https://github.com/iblai/os/blob/main/scripts/post-build.sh)

Automatically copies static assets after build:

- `.next/static/` → `.next/standalone/apps/mentor/.next/static/`
- `public/` → `.next/standalone/apps/mentor/public/`
- `offline-shell/` → `.next/standalone/apps/mentor/offline-shell/`

### [server-wrapper.js](https://github.com/iblai/os/blob/main/server-wrapper.js)

Handles server startup with error suppression:

- Suppresses harmless HTMLElement errors during Next.js pre-warming
- Logs informational message instead of error stack traces
- Doesn't affect functionality

## Troubleshooting

### Issue: 404 errors for static files

**Cause**: Static assets not copied to standalone output
**Solution**: Run `pnpm build` (which runs post-build.sh automatically)

### Issue: HTMLElement errors in logs

**Cause**: Next.js pre-warms routes using browser APIs
**Status**: Harmless, suppressed by server-wrapper.js
**Impact**: None - server works perfectly

### Issue: Port conflicts

**Cause**: Default port (3000 or 5000) already in use
**Solution**: Use custom port: `PORT=3001 pnpm start`

### Issue: "Cannot find module" in Docker

**Cause**: Standalone output not copied correctly
**Solution**: Rebuild Docker image

## CI/CD Integration

### GitHub Actions Example

```yaml
- name: Build mentor app
  run: |
    cd apps/mentor
    pnpm build
  env:
    NEXT_IMAGE_PATTERNS: ${{ secrets.NEXT_IMAGE_PATTERNS }}
    NEXT_PUBLIC_BASE_PATH: ''

- name: Build Docker image
  run: |
    docker build \
      -f apps/mentor/Dockerfile \
      --build-arg NEXT_IMAGE_PATTERNS="${{ secrets.NEXT_IMAGE_PATTERNS }}" \
      -t mentor-app:${{ github.sha }} \
      .

- name: Run container
  run: |
    docker run -d \
      -p 5000:5000 \
      --name mentor-app \
      mentor-app:${{ github.sha }}
```

## Performance Benefits

| Metric            | Before         | After     | Improvement |
| ----------------- | -------------- | --------- | ----------- |
| Docker image size | ~1.2 GB        | ~400 MB   | 67% smaller |
| Startup time      | ~3-5s          | ~1-2s     | 50% faster  |
| Memory usage      | ~300 MB        | ~200 MB   | 33% less    |
| Dependencies      | All dev + prod | Prod only | Minimal     |

## Migration Checklist

- [x] Update next.config.ts with `output: 'standalone'`
- [x] Create post-build.sh script
- [x] Create server-wrapper.js
- [x] Update package.json build command
- [x] Update package.json start command
- [x] Update Dockerfile for standalone
- [x] Test local build and start
- [x] Test Docker build and run
- [ ] Update CI/CD pipelines
- [ ] Update deployment docs
- [ ] Update production environment configs

## Additional Resources

- [Next.js Standalone Output Documentation](https://nextjs.org/docs/app/api-reference/next-config-js/output#standalone)
- [Docker Best Practices for Next.js](https://github.com/vercel/next.js/tree/canary/examples/with-docker)
- [Running the App Guide](/developer/os/running-the-app)
