# {{APP_NAME}} A Statum + Spry application, scaffolded by `spry new`. ## Development ```bash spry dev ``` Builds, runs the app on port 8080 (`--port N` to change) and watches `src/`, `meson.build` and `web-config.json`: saving a file rebuilds incrementally — page HTML and resources recompile via the meson codegen targets — and restarts the app when the build succeeds. A failed build keeps the previous process running while the compiler errors are shown. Restarts are cheap: Statum state is client-carried (the browser recovers transparently) and the static keys in `web-config.json` keep sessions alive — just refresh. `--fresh` starts from an empty database; `--no-run` builds once and exits. The environment below is required for the underlying meson builds (the `spry dev` child processes set it for you; export it in shells where you build or run manually): ```bash export WS_PREFIX="$HOME/.local" export PKG_CONFIG_PATH="$WS_PREFIX/lib64/pkgconfig${PKG_CONFIG_PATH:+:$PKG_CONFIG_PATH}" export XDG_DATA_DIRS="$WS_PREFIX/share${XDG_DATA_DIRS:+:$XDG_DATA_DIRS}" export LD_LIBRARY_PATH="$WS_PREFIX/lib64${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" meson setup builddir ninja -C builddir ./builddir/{{APP_NAME}} ``` The server listens on port 8080 (pass another port as the first argument). Static signing/encryption keys live in `web-config.json` (written by `spry keys`; gitignored and mode 0600 — never commit it or bake it into images), so sessions survive a restart. The SQLite store is `./{{APP_NAME}}.sqlite`, or `SPRY_DB_PATH` when that variable is set. An admin account is seeded on boot only when BOTH `SPRY_SEED_ADMIN_USERNAME` and `SPRY_SEED_ADMIN_PASSWORD` are set (the password is never logged); seeding is skipped silently otherwise: ```bash export SPRY_SEED_ADMIN_USERNAME=admin export SPRY_SEED_ADMIN_PASSWORD=change-me ``` ## Layout | Path | Purpose | |---|---| | `src/main.vala` | application wiring: modules, database, pages, actions | | `src/pages/*.html` | Statum pages, compiled to Vala by `statum-mkpstm` at build time | | `src/entrypoints/` | one `StatumEntrypoint` per page | | `src/actions/` | `StatumAction` subclasses | | `src/resources/` | static resources embedded by `statum-mkres` | | `MANIFEST.usm` | USM package manifest: `provides bin:{{APP_NAME}}`, build/runtime/manage deps | | `usm-scripts/` | USM build + install scripts (meson `--prefix=/usr` staging) | | `web-config.json` | static keys and other configuration (gitignored, 0600) | Registrations live between `// spry:*-begin/end` markers in `src/main.vala`, `# spry:*-begin/end` markers in `meson.build` and `` markers in `src/pages/main.html` (the layout's nav, plus the logged-in-only `` block); the `spry add` commands edit only those blocks and are idempotent. ## Growing the app ``` spry dev spry add page [--route /path] spry add action spry add resource spry add login spry add register spry add user-management spry keys spry deploy ``` `add login`, `add register` and `add user-management` also grow the layout nav (a Login/Register link when logged out, a Log-out button once login is added, a Users link for admins) inside the nav markers. ## Deployment (USM) `spry deploy [--exec CMD] [--base IMAGE] [--repository FILE]... [--installer-url URL] [--no-build]` packages the application and builds a single-stage container image through USM (`usm manifest deploy`): the generated `MANIFEST.usm` + `usm-scripts/` drive the in-container build and install, the system package manager provides the platform libraries and toolchain, and USM repositories provide the Web-Stack. The result is `{{APP_NAME}}-.image.tar.xz`, loadable with `podman load -i`. By default USM resolves from the machine's configured repositories — point it at a specific repository (for example a local Web-Stack repository) with repeatable `--repository `. The image installs USM itself from the canonical installer URL baked into usm (`https://packages.astrologue.nz/install-usm.sh`); pass `--installer-url file:///…/install-usm.sh` to carry a locally built installer script into the image instead. `--exec` defaults to `{{APP_NAME}} 8080`. `web-config.json` is never packaged (`.usmignore`), so keys are never baked into the image. Serve pages with ephemeral keys by running the image directly, or mount the config read-only for full authentication: ```bash podman load -i {{APP_NAME}}-0.1.image.tar.xz podman run -d -p 8080:8080 \ -v $PWD/web-config.json:/run/web-config.json:ro \ -e ASTRALIS_CONFIG_PATH=/run/web-config.json \ -e SPRY_DB_PATH=/var/lib/{{APP_NAME}}/{{APP_NAME}}.sqlite \ localhost/{{APP_NAME}}:0.1 ```