# Local Compiler

Run the Quickback compiler locally using Docker. This is a fully supported
compiler mode, not a reduced fallback: it uses the exact same Docker image as
the hosted compiler and produces the same backend, migrations, SDKs, and SPA
builds while keeping compile source on the local machine.

## Prerequisites

- Docker Desktop installed and running
- Quickback monorepo cloned locally

## Quick Start

From the monorepo root:

```bash
cd apps/compiler-local && bash dev.sh
```

This will:
1. Ensure Docker Desktop is running
2. Stop any existing compiler container
3. Build the Docker image from `apps/compiler/Dockerfile`
4. Start it in explicit local mode, published only on `127.0.0.1:3000`

### Custom Port

```bash
bash dev.sh 3001
```

## Compiling a Project

Point the CLI to your local compiler:

```bash
QUICKBACK_API_URL=http://localhost:3000 quickback compile
```

Or export it for the session:

```bash
export QUICKBACK_API_URL=http://localhost:3000
quickback compile
```

The supported launcher does not require `quickback login`. It opts the compiler
into local mode and binds Docker's host port to loopback, so the unauthenticated
compile endpoint is not exposed to the LAN. The CLI skips its login prompt only
when `QUICKBACK_API_URL` has the exact hostname `localhost`, `127.0.0.1`, or
`::1`; longer hostnames and URLs that merely contain those strings still use
hosted authentication.

## Manual Build & Run

You can also build and run the Docker image directly from the monorepo root:

```bash
# Build
docker build -t quickback-compiler -f apps/compiler/Dockerfile .

# Run with the same security boundary as the supported launcher
docker run --rm \
  -e QUICKBACK_COMPILER_MODE=local \
  -p 127.0.0.1:3000:3000 \
  quickback-compiler
```

`QUICKBACK_COMPILER_MODE` is fail-closed: only the exact value `local` bypasses
compile authentication. If the variable is absent or misspelled, the compiler
uses hosted authentication. Never publish a local-mode container on
`0.0.0.0` or a non-loopback interface.

## Verify

Check the compiler is running:

```bash
curl http://localhost:3000/health
```

## How It Works

The Docker image includes:
- Pre-installed dependencies for compiled projects (`/deps/node_modules`)
- CMS and Account SPA source code (`/spa/cms/`, `/spa/account/`)
- Pre-installed SPA dependencies (`/spa-deps/cms/`, `/spa-deps/account/`)

When compiling a project with `cms: true` or `account: true`, the compiler builds the SPAs from source inside the container with the correct Vite environment variables (e.g., `VITE_QUICKBACK_API_URL`, `VITE_QUICKBACK_ACCOUNT_URL`). This ensures each project gets properly configured SPA assets without manual intervention.

The generated worker additionally injects the same per-project values into every served SPA shell as `window.__QUICKBACK_RUNTIME`, and the SPAs prefer that runtime blob over the baked env — so the served behavior is identical even with a generic (no-`.env`) SPA build.

## Deploying to Cloud

After making changes to the compiler, deploy to `compiler.quickback.dev`:

```bash
cd apps/compiler-cloud && bash deploy.sh
```

## Troubleshooting

### Container not starting

```bash
docker logs quickback-compiler-local
```

### Port already in use

```bash
# Find what's using the port
lsof -i :3000

# Use a different port
bash dev.sh 3001
```

### Docker out of disk space

```bash
docker system prune -af
```

### SPA asset warnings

Compiles never build the SPAs — the Docker image carries generic prebuilt CMS/Account bundles (built once, at image build) that a compile copies into `src/apps/`. A "prebuilt … SPA assets not found" warning means the image was built without the `spa-prebuilt` stage completing; rebuild it with `bash dev.sh`.

SPA dependency manifests (`apps/compiler/deps-spa-cms-package.json`, `deps-spa-account-package.json`) are only consumed by that image-build stage — if one is stale, the **image build** fails loudly, never a user compile.
