# Catalyst Instance registry for tracking infrastructure. Built as a single-page app — no backend, no framework. ## Stack - **sql.js** — SQLite compiled to WebAssembly, runs entirely in the browser - **localStorage** — persists the database between sessions - **nginx** — serves the static files (via Docker) ## Structure ``` index.html Entry point css/app.css All styles js/ config.js Service definitions and seed data db.js Database layer (init, queries, mutations, persistence) ui.js Rendering, modals, toast notifications app.js Router and bootstrap Dockerfile nginx:alpine image nginx.conf SPA routing config (used by Dockerfile) ``` ## Running locally Requires a local HTTP server — `history.pushState` routing won't work over `file://`. ```bash npx serve . --single ``` Then open `http://localhost:3000`. ## Building Push to `main`. Gitea Actions builds and pushes two image tags to your registry: | Tag | Use | |---|---| | `:latest` | Always the current main | | `:` | Pinned to a specific commit (use for rollbacks) | Requires two things set in Gitea repository settings: | Key | Type | Value | |---|---|---| | `REGISTRY_HOST` | Variable | your Gitea hostname | | `GITEA_TOKEN` | Secret | token with `package:write` scope | ## Running the container ```bash docker run -d -p 3000:80 /catalyst:latest ``` ## Migrating to a real backend All database operations are in `js/db.js`. The functions `getInstances`, `getInstance`, `createInstance`, `updateInstance`, and `deleteInstance` are the only things that would change — swap the `db.run()` / `db.exec()` calls for `fetch()` calls to your API and the rest of the app is untouched.