#!/usr/bin/env bash # ============================================================================ # prerender-static.sh — build aac.transaction.science as a self-contained # static site. # # AAC ships as a static CSR-hydrate SPA, but it's a Leptos SSR app: the # index.html the browser loads is the SSR server's *rendered* output (it carries # the hydration island markers and the pre-rendered board). A plain # `cargo leptos build` never emits that index.html, and it doesn't copy the # PWA assets that live in `static/` (only the `public/` assets-dir). This script # closes both gaps so the result in `target/site/` is everything prod needs: # # build -> target/site/{pkg/, icons/} (cargo-leptos) # bundle -> target/site/{manifest.json, sw.js} (from static/) # render -> target/site/index.html (capture SSR `/`) # # Output: a self-contained `target/site/` ready to rsync to prod. Idempotent. # ============================================================================ set -euo pipefail cd "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PORT="${AAC_PRERENDER_PORT:-39207}" SITE="target/site" echo "▸ cargo leptos build --release" cargo leptos build --release echo "▸ bundling PWA assets from static/ into $SITE" cp crates/aac-web/static/manifest.json "$SITE/manifest.json" cp crates/aac-web/static/sw.js "$SITE/sw.js" echo "▸ starting SSR server on 127.0.0.1:$PORT to prerender /" LEPTOS_OUTPUT_NAME=aac-web \ LEPTOS_SITE_ROOT="$SITE" \ LEPTOS_SITE_PKG_DIR=pkg \ LEPTOS_SITE_ADDR="127.0.0.1:$PORT" \ LEPTOS_ENV=PROD \ target/release/aac-web > /tmp/aac-prerender-ssr.log 2>&1 & SRV=$! trap 'kill "$SRV" 2>/dev/null || true' EXIT # Wait for the listener (up to ~30s). ready=false for _ in $(seq 1 120); do if curl -sf "http://127.0.0.1:$PORT/" -o /dev/null 2>/dev/null; then ready=true; break; fi sleep 0.25 done if ! $ready; then echo "✗ SSR server did not come up; log:" >&2; tail -5 /tmp/aac-prerender-ssr.log >&2; exit 1 fi echo "▸ capturing rendered / -> $SITE/index.html" curl -sf "http://127.0.0.1:$PORT/" -o "$SITE/index.html" kill "$SRV" 2>/dev/null || true trap - EXIT # Sanity-check the capture is the hydrating SSR shell, not an error page. test -s "$SITE/index.html" grep -q 'mod.hydrate' "$SITE/index.html" || { echo "✗ captured index.html is not the hydrating shell" >&2; exit 1; } grep -q 'AAC' "$SITE/index.html" || { echo "✗ captured index.html missing expected title" >&2; exit 1; } echo "✓ self-contained dist ready at $SITE/" ls -1 "$SITE"