Add records, Elijah scores, per-session notes, and PWA update prompt
App features: - Personal-best records per metric: manually settable in Settings and auto-updated when a session beats them; shown in the log modal and a new dashboard "Personal records" card. - Juggling now counts by 1 instead of 5. - 1-on-1 with Elijah gains Technical Skill and Effort scores (out of 10) as manual inputs, plus an optional per-session note. - Service worker now uses a controlled update flow: an in-app "new version ready" banner activates the update on tap and reloads. Data model: - category_metrics gains track_record + record; entries gains note. - Idempotent migrations bring existing databases up to date (juggling step/record, Elijah score metrics) alongside the updated seed. StartOS package: - Bump to 0.1.2:0 with release notes. - Build x86_64 only (drop aarch64) per deployment target.
This commit is contained in:
+68
-55
@@ -1,16 +1,23 @@
|
||||
<p align="center">
|
||||
<img src="icon.svg" alt="Hello World Logo" width="21%">
|
||||
<img src="icon.svg" alt="Premier Gunner Logo" width="21%">
|
||||
</p>
|
||||
|
||||
# Hello World on StartOS
|
||||
# Premier Gunner on StartOS
|
||||
|
||||
> **Upstream repo:** <https://github.com/Start9Labs/hello-world>
|
||||
> **Upstream repo:** <https://github.com/ten31/premier-gunner>
|
||||
|
||||
A minimal reference service for StartOS. It displays a simple web page — nothing more. Use [this repository](https://github.com/Start9Labs/hello-world-startos) as a template when packaging a new service for StartOS.
|
||||
Premier Gunner is a kid-friendly, mobile-friendly soccer training tracker for a single player. It logs daily training across categories, plans future sessions, tracks goals, and shows progress toward a big reward. This repository packages the app as a StartOS `.s9pk` service for StartOS 0.4.0.x.
|
||||
|
||||
## Getting Started
|
||||
|
||||
To learn how to use this template to create your own StartOS service package, see the [Packaging Guide](https://docs.start9.com/packaging).
|
||||
This package builds its own Docker image from the vendored Node app (it does **not** pull a prebuilt image from a registry). The build copies the app source into `./app` and installs/compiles its dependencies inside the image.
|
||||
|
||||
```sh
|
||||
npm ci # install the start-sdk packaging deps
|
||||
make # vendor the app, build images, and pack the .s9pk(s)
|
||||
```
|
||||
|
||||
To learn the general workflow, see the [StartOS Packaging Guide](https://docs.start9.com/packaging/0.4.0.x/).
|
||||
|
||||
---
|
||||
|
||||
@@ -25,79 +32,88 @@ To learn how to use this template to create your own StartOS service package, se
|
||||
- [Backups and Restore](#backups-and-restore)
|
||||
- [Health Checks](#health-checks)
|
||||
- [Dependencies](#dependencies)
|
||||
- [Limitations and Differences](#limitations-and-differences)
|
||||
- [What Is Unchanged from Upstream](#what-is-unchanged-from-upstream)
|
||||
- [Contributing](#contributing)
|
||||
- [Build Layout](#build-layout)
|
||||
- [Quick Reference for AI Consumers](#quick-reference-for-ai-consumers)
|
||||
|
||||
---
|
||||
|
||||
## Image and Container Runtime
|
||||
|
||||
| Property | Value |
|
||||
| ------------- | -------------------------------------- |
|
||||
| Image | `ghcr.io/start9labs/hello-world` |
|
||||
| Architectures | x86_64, aarch64, riscv64 |
|
||||
| Command | `hello-world` |
|
||||
| Property | Value |
|
||||
| ------------- | ---------------------------------------------- |
|
||||
| Image | Built locally from `./Dockerfile` (Node 22) |
|
||||
| Architectures | x86_64, aarch64 |
|
||||
| Command | `node src/server.js` (cwd `/app`) |
|
||||
|
||||
---
|
||||
|
||||
## Volume and Data Layout
|
||||
|
||||
| Volume | Mount Point | Purpose |
|
||||
| ------ | ----------- | --------------- |
|
||||
| `main` | `/data` | Persistent data |
|
||||
| Volume | Mount Point | Purpose |
|
||||
| ------ | ----------- | ------------------------------------------------------------- |
|
||||
| `main` | `/data` | SQLite database, sessions, and `store.json` (login password) |
|
||||
|
||||
The app reads `PG_DATA_DIR=/data` and writes its SQLite DB there. The package's `store.json` (managed by StartOS) lives in the same volume and holds the login password.
|
||||
|
||||
---
|
||||
|
||||
## Installation and First-Run Flow
|
||||
|
||||
No special setup. Install and start — the web page is immediately available.
|
||||
1. On install, a 16-character random login password is generated and written to `store.json`.
|
||||
2. On every start, `main` reads the password from `store.json` and injects it as `PG_PASSWORD`. The app treats this env var as authoritative and (re)hashes it, so the login password always matches what StartOS holds.
|
||||
3. The user opens the **ui** interface, logs in, and (recommended) sets their own password via the **Set Login Password** action.
|
||||
|
||||
---
|
||||
|
||||
## Configuration Management
|
||||
|
||||
No configurable settings. The service runs with no user-facing configuration.
|
||||
The only user-managed setting is the login password, handled by the **Set Login Password** action — not a config form. The action writes to `store.json`; the resulting change triggers a daemon restart (via a reactive `.const` read) so the new password takes effect immediately.
|
||||
|
||||
**StartOS-managed environment variables injected into the app:**
|
||||
|
||||
| Variable | Value | Source |
|
||||
| ------------- | -------------- | ------------------------------- |
|
||||
| `NODE_ENV` | `production` | static (enables `Secure` cookie)|
|
||||
| `PG_HOST` | `0.0.0.0` | static |
|
||||
| `PG_PORT` | `3000` | `utils.uiPort` |
|
||||
| `PG_DATA_DIR` | `/data` | `main` volume mount |
|
||||
| `PG_PASSWORD` | (random/user) | `store.json` → reactive read |
|
||||
|
||||
---
|
||||
|
||||
## Network Access and Interfaces
|
||||
|
||||
| Interface | Port | Protocol | Purpose |
|
||||
| --------- | ---- | -------- | -------------------- |
|
||||
| Web UI | 80 | HTTP | Hello World web page |
|
||||
| Interface | Port | Protocol | Purpose |
|
||||
| --------------- | ---- | -------- | ---------------------- |
|
||||
| `ui` | 3000 | HTTP | Premier Gunner web app |
|
||||
|
||||
**Access methods:**
|
||||
**Access methods:** LAN IP, `<hostname>.local`, Tor `.onion`, and custom clearnet domains.
|
||||
|
||||
- LAN IP with unique port
|
||||
- `<hostname>.local` with unique port
|
||||
- Tor `.onion` address
|
||||
- Custom domains (if configured)
|
||||
### Clearnet via StartTunnel
|
||||
|
||||
The app serves plain HTTP; StartOS/StartTunnel terminate TLS. Point a StartTunnel domain at the **ui** interface (see the [StartTunnel docs](https://docs.start9.com/start-tunnel/1.0.x/)). Because `NODE_ENV=production` sets the session cookie's `Secure` flag, the app must be reached over HTTPS — which StartTunnel provides.
|
||||
|
||||
---
|
||||
|
||||
## Actions (StartOS UI)
|
||||
|
||||
None.
|
||||
| Action | Input | Effect |
|
||||
| -------------------- | ------------------- | ------------------------------------------------------------------- |
|
||||
| Set Login Password | Password (≥4 chars) | Writes the password to `store.json`; service restarts; sessions cleared |
|
||||
|
||||
---
|
||||
|
||||
## Backups and Restore
|
||||
|
||||
**Included in backup:**
|
||||
|
||||
- `main` volume
|
||||
|
||||
**Restore behavior:** Volume is fully restored before the service starts.
|
||||
**Included in backup:** the `main` volume (database + `store.json`). Restored fully before the service starts.
|
||||
|
||||
---
|
||||
|
||||
## Health Checks
|
||||
|
||||
| Check | Method | Messages |
|
||||
| ------------- | ------------------- | ------------------------------------------------------------------ |
|
||||
| Web Interface | Port listening (80) | Success: "The web interface is ready" / Error: "The web interface is not ready" |
|
||||
| Check | Method | Messages |
|
||||
| ------------- | ---------------------- | ------------------------------------------------------------------------------- |
|
||||
| Web Interface | Port listening (3000) | Success: "The web interface is ready" / Error: "The web interface is not ready" |
|
||||
|
||||
---
|
||||
|
||||
@@ -107,35 +123,32 @@ None.
|
||||
|
||||
---
|
||||
|
||||
## Limitations and Differences
|
||||
## Build Layout
|
||||
|
||||
1. **No meaningful functionality** — this is a reference/template package only
|
||||
|
||||
---
|
||||
|
||||
## What Is Unchanged from Upstream
|
||||
|
||||
The service is identical to upstream. There are no modifications.
|
||||
|
||||
---
|
||||
|
||||
## Contributing
|
||||
|
||||
See [CONTRIBUTING.md](CONTRIBUTING.md) for build instructions and development workflow.
|
||||
- `Dockerfile` — multi-stage Node 22 build; compiles `better-sqlite3`, copies the app, runs `node src/server.js`.
|
||||
- `Makefile` — `prep` vendors the app from the parent repo into `./app` (excluding `node_modules`/`data`), then delegates to `s9pk.mk` to build both arches.
|
||||
- `startos/` — the start-sdk package definition (manifest, main, interfaces, actions, fileModels/store, versions, i18n).
|
||||
- `./app` — generated, git-ignored vendor copy of the Node app used as the Docker build context.
|
||||
|
||||
---
|
||||
|
||||
## Quick Reference for AI Consumers
|
||||
|
||||
```yaml
|
||||
package_id: hello-world
|
||||
image: ghcr.io/start9labs/hello-world
|
||||
architectures: [x86_64, aarch64, riscv64]
|
||||
package_id: premier-gunner
|
||||
image: built locally from ./Dockerfile (node:22-bookworm-slim)
|
||||
architectures: [x86_64, aarch64]
|
||||
volumes:
|
||||
main: /data
|
||||
ports:
|
||||
ui: 80
|
||||
ui: 3000
|
||||
dependencies: none
|
||||
startos_managed_env_vars: none
|
||||
actions: none
|
||||
startos_managed_env_vars:
|
||||
PG_PASSWORD: from store.json (login password, authoritative)
|
||||
PG_PORT: 3000
|
||||
PG_DATA_DIR: /data
|
||||
PG_HOST: 0.0.0.0
|
||||
NODE_ENV: production
|
||||
actions:
|
||||
- set-password (Set Login Password)
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user