# syntax=docker/dockerfile:1
#
# docker/web.Dockerfile
# ---------------------------------------------------------------------------
# Multi-stage build for the Wisp web app.
#
#   Stage 1 (builder):  Uses the official Bun image to install dependencies and
#                       run the Expo/Metro static web export. The output is a
#                       fully static SPA in /app/dist.
#
#   Stage 2 (runtime):  A tiny nginx:alpine image that serves the exported
#                       static files. nginx is configured (docker/nginx.conf)
#                       to send the cross-origin isolation headers that the
#                       multi-threaded WASM Whisper backend requires, namely:
#                         Cross-Origin-Opener-Policy: same-origin
#                         Cross-Origin-Embedder-Policy: require-corp
#
# Build:  docker build -f docker/web.Dockerfile -t wisp-web:latest .
# Run:    docker run --rm -p 8080:8080 wisp-web:latest
#
# NOTE: build context must be the repository root (so the whole repo + lockfile
#       are available to the builder).
# ---------------------------------------------------------------------------

# ---------------------------------------------------------------------------
# Stage 1: build the static site with Bun + Expo export
# ---------------------------------------------------------------------------
# Pin to the Bun 1.x line. `oven/bun:1` tracks the latest 1.x patch release;
# pin to an exact digest/tag in production if you want fully reproducible builds.
FROM oven/bun:1 AS builder

WORKDIR /app

# Copy manifest + lockfile first so Docker can cache the (slow) dependency
# install layer independently of source changes. `bun.lock` is Bun's lockfile.
COPY package.json bun.lock ./

# Install EXACTLY what the lockfile specifies. --frozen-lockfile fails the build
# if package.json and bun.lock have drifted, which keeps CI deterministic.
RUN bun install --frozen-lockfile

# Now copy the rest of the repository (app code, assets, config, etc.).
# Anything matched by .dockerignore (node_modules, dist, .git ...) is skipped.
COPY . .

# Produce the static web bundle. `bun run export:web` maps to
# `expo export --platform web`, which writes the static site to ./dist
# (Expo's default --output-dir). app.json sets web.output = "static", so this
# emits prerendered HTML + the JS/WASM assets for the SPA.
RUN bun run export:web

# ---------------------------------------------------------------------------
# Stage 2: serve the static site with nginx
# ---------------------------------------------------------------------------
FROM nginx:alpine AS runtime

# Drop the stock nginx site config and install ours. Our config:
#   - listens on 8080 (non-privileged port; matches docker-compose + reverse proxy)
#   - SPA fallback (try_files ... /index.html)
#   - COOP/COEP/CORP cross-origin isolation headers (for threaded WASM)
#   - gzip + long-lived caching for hashed static assets
#   - serves /wisp.apk if an APK has been dropped into the web root
COPY docker/nginx.conf /etc/nginx/conf.d/default.conf

# Copy the exported static site from the builder stage into nginx's web root.
COPY --from=builder /app/dist /usr/share/nginx/html

# Document the port the container listens on (informational; publish with -p).
EXPOSE 8080

# nginx:alpine's default entrypoint already runs nginx in the foreground
# ("daemon off") via /docker-entrypoint.sh, so no CMD override is needed.
