# web SvelteKit frontend. Phase 0: one page, one query box, one table. No auth, no styling polish, no routing beyond `/`. ## What it does Textarea for a raw SQL string → `POST {VITE_API_BASE_URL}/query` on `/api` → renders `{columns, rows}` as an HTML table, or shows `{error}` from a rejected/failed query. That's the whole app — see `src/routes/+page.svelte`. ## Why a static build, not a Node server Scaffolded with `@sveltejs/adapter-static`: this page has no server-side data loading (all data comes from a client-side `fetch` triggered by the submit button), so there's nothing here that needs a running SvelteKit server. A prerendered static site is simpler to build, deploy, and reason about than running Node in production for a page that's this thin. Because it's static, `VITE_API_BASE_URL` is baked in at **build time**, not read at container start. Set it before `npm run build` (or pass `--build-arg VITE_API_BASE_URL=...` to `docker build`) — changing it later means rebuilding, not just restarting the container. ## Building & running ```sh npm install cp .env.example .env # adjust VITE_API_BASE_URL if /api isn't on localhost:8080 npm run dev # local dev server with hot reload npm run check # svelte-check, type errors npm run build # static output to build/ npm run preview # serve the static build locally to sanity-check it ``` ```sh docker build -f Dockerfile -t sentry-web . # context is web/, not the repo root docker run -p 3000:3000 sentry-web ``` ## Why nginx, not distroless The repo convention prefers distroless/scratch base images. Serving a static SPA still needs *some* HTTP server, though, and `nginx:alpine` is the boring, standard choice for that job — writing a custom static-file binary just to stay distroless would be more engineering than a Phase 0 placeholder page justifies. `nginx.conf` here is minimal: serve `build/`, fall back to `index.html` for client-side routing (only one route exists today, but this is what you want the moment a second one is added).