Compare commits

...

2 commits

Author SHA1 Message Date
SkateSpots
65914144d1 dist: document self-hosted Forgejo and F-Droid repo
Some checks are pending
Deploy to GitHub Pages / deploy (push) Waiting to run
2026-10-30 22:43:47 +07:00
SkateSpots
a8780d5236 dist: self-hosted Forgejo release page and F-Droid metadata 2026-10-30 22:33:53 +07:00
9 changed files with 302 additions and 0 deletions

View file

@ -2415,6 +2415,29 @@ Rules:
- Any time the deploy output isn't verified by the smoke test, run - Any time the deploy output isn't verified by the smoke test, run
`node scripts/smoke-test.mjs` manually before shipping. `node scripts/smoke-test.mjs` manually before shipping.
### Distribution without GitHub
- **Self-hosted Forgejo:** `https://git.skate-spots.org/skatespots/SkateSpots`
(public source, registration disabled, admin credentials only on the relay
host). It runs on `185.18.221.2` behind Caddy; do not commit its credentials.
- **Latest release (Obtanium HTML source):**
`https://git.skate-spots.org/skatespots/SkateSpots/releases/latest`.
The page exposes one signed `.apk`; Obtanium may need **Override Source →
HTML** because the host is self-hosted, not Codeberg.
- **Static download page:** `public/download/index.html` → `https://skate-spots.org/download/`.
- **Self-hosted F-Droid repo:** `https://fdroid.skate-spots.org/repo`
(`org.skatespots.app`; currently 1.7.61). It is a **third-party repo**, not
F-Droid main. Repo signing fingerprint:
`88:B1:71:1C:24:02:89:FB:B2:A7:FC:C1:B3:1F:BB:9D:60:F5:7F:19:18:E0:3D:62:2D:35:F2:3D:E1:84:46:75`.
The developer APK signature is unchanged; the repo key only signs indexes.
A backup of the repo keystore/config is in
`~/.config/skatespots/fdroid-repo/` (mode 600).
- **F-Droid main/IzzyOnDroid:** still need external review/submission. Source and
recipe draft are ready in `distribution/`; F-Droid main would sign with its own
key and cannot install over the Zapstore APK without uninstalling (local data
loss). Prefer the self-hosted repo/Obtanium until that is explained clearly.
- **No GitHub required.** Keep Zapstore, Forgejo, the self-hosted F-Droid repo,
and the static page in sync for each release.
### Deploy ### Deploy
- **Web (auto)**: a systemd user timer (`skatespots-deploy.timer`) runs `scripts/auto-deploy.sh` every ~3 min. When `origin/main` changes it builds and runs `netlify deploy --prod --dir=dist`. It deploys **only committed code** (skips if tracked files are modified) and never mutates a dirty tree. **Doc/scripts-only commits are skipped** (matches `AGENTS.md`/`*.md`/`scripts/`/`cvm-server/`/`skills/`) — Netlify bills **15 credits per production deploy**, so don't spend them on non-site changes. One-time setup: `netlify login` + `netlify link`. Logs: `journalctl --user -u skatespots-deploy`. Manual run: `scripts/auto-deploy.sh`. - **Web (auto)**: a systemd user timer (`skatespots-deploy.timer`) runs `scripts/auto-deploy.sh` every ~3 min. When `origin/main` changes it builds and runs `netlify deploy --prod --dir=dist`. It deploys **only committed code** (skips if tracked files are modified) and never mutates a dirty tree. **Doc/scripts-only commits are skipped** (matches `AGENTS.md`/`*.md`/`scripts/`/`cvm-server/`/`skills/`) — Netlify bills **15 credits per production deploy**, so don't spend them on non-site changes. One-time setup: `netlify login` + `netlify link`. Logs: `journalctl --user -u skatespots-deploy`. Manual run: `scripts/auto-deploy.sh`.
- ⚠️ **Deploy throttle (2026-09-28):** production deploys are capped to one per **24h** by default (after a week of 68 deploys ≈ **1,020 credits** — a third of the monthly allowance). Batching a day's commits into one 15-credit deploy is the single biggest credit lever. Override with `SKATESPOTS_DEPLOY_MIN_INTERVAL=<seconds>` (`0` disables); deploy on demand with **`scripts/auto-deploy.sh --force`**. A throttled tick deliberately does **not** record the deployed SHA, so the pending change still deploys on a later tick; a **failed** deploy doesn't set the clock, so it retries immediately. - ⚠️ **Deploy throttle (2026-09-28):** production deploys are capped to one per **24h** by default (after a week of 68 deploys ≈ **1,020 credits** — a third of the monthly allowance). Batching a day's commits into one 15-credit deploy is the single biggest credit lever. Override with `SKATESPOTS_DEPLOY_MIN_INTERVAL=<seconds>` (`0` disables); deploy on demand with **`scripts/auto-deploy.sh --force`**. A throttled tick deliberately does **not** record the deployed SHA, so the pending change still deploys on a later tick; a **failed** deploy doesn't set the clock, so it retries immediately.

86
distribution/README.md Normal file
View file

@ -0,0 +1,86 @@
# Distribution without GitHub
SkateSpots is published from a self-hosted **Forgejo** instance. No GitHub
account is required.
## Current release source
- Forge: <https://git.skate-spots.org/skatespots/SkateSpots>
- Latest release: <https://git.skate-spots.org/skatespots/SkateSpots/releases/latest>
- Signed APK (1.7.61):
<https://git.skate-spots.org/skatespots/SkateSpots/releases/download/v1.7.61/SkateSpots-1.7.61.apk>
- SHA-256:
`db0279f759efd9fa05d9d1bed57a3f5856777e6ccb208d3ed78b15398f266fba`
The APK is signed with the same key as the Zapstore build. Installing an
F-Droid-signed build over it would require uninstalling SkateSpots and losing
the local key/settings. Obtanium and direct APK updates keep the install.
## Obtanium
Obtanium cannot use a Zapstore URL as a source. Use the self-hosted Forgejo
release page instead:
1. Open Obtanium → **Add App**.
2. Paste:
`https://git.skate-spots.org/skatespots/SkateSpots/releases/latest`
3. If Obtanium does not recognise the self-hosted host, select **Override
Source → HTML**.
4. Set version extraction if desired:
`SkateSpots-([0-9.]+)\.apk`, match group `1`.
The release page contains exactly one `.apk`, so Obtanium can follow the latest
release without a custom store listing.
## F-Droid family
### Self-hosted F-Droid repo (live now)
A signed third-party F-Droid repository is published here:
- Repo: <https://fdroid.skate-spots.org/repo>
- App ID: `org.skatespots.app`
- Repo signing fingerprint:
`88:B1:71:1C:24:02:89:FB:B2:A7:FC:C1:B3:1F:BB:9D:60:F5:7F:19:18:E0:3D:62:2D:35:F2:3D:E1:84:46:75`
Users can add this URL in F-Droid, or add it in Obtanium as an **F-Droid Third
Party Repo**. This is not F-Droid main: it is a self-hosted, signed repository
of the developer-signed APK. It keeps the existing install and signing key.
The repository metadata and APK are served from the relay host. The repo index
is signed with a repository key stored on that host; the APK itself keeps the
SkateSpots developer signature.
### F-Droid main and IzzyOnDroid
F-Droid main requires a public, clonable source repository (the Forgejo URL
above), an accepted `fdroiddata` recipe, a reproducible build and maintainer
review. IzzyOnDroid is the easier external submission step. Both remain
external-review processes; the self-hosted repo above is usable without waiting
for either.
Recipe draft: `distribution/fdroiddata/org.skatespots.app.yml`
Store metadata: `fastlane/metadata/android/en-US/`
The Android project is generated by Capacitor and intentionally not committed,
so the prebuild steps must be verified in the F-Droid build environment before
submitting to F-Droid main.
## Release checklist
1. `npm test`
2. `scripts/release.sh patch --yes --deploy` (Zapstore + web)
3. Push the release tag and `main` to Forgejo.
4. Attach `android/app/build/outputs/apk/release/app-release.apk` and its
`.sha256` to the Forgejo release.
5. Copy the signed APK into the F-Droid repo on the relay host, update the
metadata changelog and run `fdroid update`; sync `repo/` to
`/var/www/fdroid/repo/`.
6. Verify the public latest-release page contains the new `.apk`, and that
`https://fdroid.skate-spots.org/repo/index-v2.json` still lists the app.
7. Update the static download page if the displayed version/checksum changes:
`public/download/index.html`.
The Forgejo instance runs on the same host as the relay. It exposes public
read access and HTTPS through Caddy; registration is disabled and administrative
credentials are kept on the host, not in this repository.

View file

@ -0,0 +1,48 @@
Categories:
- Sports
License: AGPL-3.0-only
AuthorName: SkateSpots
WebSite: https://skate-spots.org
SourceCode: https://git.skate-spots.org/skatespots/SkateSpots
IssueTracker: https://git.skate-spots.org/skatespots/SkateSpots/issues
Changelog: https://git.skate-spots.org/skatespots/SkateSpots/releases
AutoName: SkateSpots
Summary: Local-first skate map, crews, events and marketplace
Description: |-
SkateSpots is a local-first skating map for finding spots, crews, events and
gear. Your keys stay on your device, your messages stay in encrypted crew
chats and the app does not use analytics or sell your data.
Find skate spots on the map, add new ones, organise sessions with your crew,
follow events and browse the community marketplace. The Android app bundles
the same web app for fast shell startup and native camera, location, push and
NFC support where available.
SkateSpots is self-hosted and built on open protocols. You can run your own
relay and Blossom storage instead of relying on a central service.
RepoType: git
Repo: https://git.skate-spots.org/skatespots/SkateSpots.git
Builds:
- versionName: 1.7.61
versionCode: 10761
commit: 50c95d0ff7e083f81eaeeee167c4cb7c68e3b038
subdir: .
prebuild:
- npm ci
- npm run android:init
- npm run android:sync
build:
- cd android && ./gradlew assembleRelease --no-daemon
output: android/app/build/outputs/apk/release/app-release.apk
# The generated Android project is intentionally not committed. This
# recipe recreates it with Capacitor before Gradle runs. F-Droid will sign
# the resulting APK with its own key. The F-Droid buildserver supplies the
# JDK/Android SDK; do not install packages with sudo in a recipe.
AutoUpdateMode: Version
UpdateCheckMode: Tags
CurrentVersion: 1.7.61
CurrentVersionCode: 10761

View file

@ -0,0 +1 @@
Cordn setup now shows visible progress: the device-key step is checked once prepared, and the approval step shows a spinner while waiting. The APK uses the same signing key as the Zapstore release.

View file

@ -0,0 +1,15 @@
SkateSpots is a local-first skating map for finding spots, crews, events and
gear. Your keys stay on your device, your messages stay in encrypted crew chats
and the app does not use analytics or sell your data.
Find skate spots on the map, add new ones, organise sessions with your crew,
follow events and browse the community marketplace. The Android app bundles the
same web app for fast offline shell startup and native camera, location, push
and NFC support where available.
SkateSpots is self-hosted and built on open protocols. You can run your own
relay and Blossom storage instead of relying on a central service.
Lightning payments are optional and self-custodial. Transport and driver
profiles are self-attested; SkateSpots does not verify a licence, insurance or
vehicle roadworthiness.

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View file

@ -0,0 +1 @@
Local-first skate map, crews, events and marketplace.

View file

@ -0,0 +1 @@
SkateSpots

127
public/download/index.html Normal file
View file

@ -0,0 +1,127 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
<meta name="color-scheme" content="dark" />
<title>SkateSpots APK</title>
<meta
name="description"
content="Download the signed SkateSpots Android APK. No account, no store, no tracking."
/>
<style>
:root {
color-scheme: dark;
--bg: #090b0c;
--panel: #121719;
--line: #273033;
--text: #f2f5f4;
--muted: #9aa7a5;
--teal: #56e0c0;
--amber: #f5b83d;
}
* { box-sizing: border-box; }
body {
margin: 0;
min-height: 100dvh;
display: grid;
place-items: center;
padding: 24px;
background:
radial-gradient(circle at 20% 0%, rgba(86, 224, 192, 0.12), transparent 42%),
var(--bg);
color: var(--text);
font: 15px/1.55 ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
}
main {
width: min(100%, 560px);
padding: 28px;
border: 1px solid var(--line);
border-radius: 18px;
background: color-mix(in srgb, var(--panel) 92%, transparent);
box-shadow: 0 18px 60px rgba(0, 0, 0, 0.35);
}
.eyebrow {
margin: 0 0 10px;
color: var(--teal);
font-size: 12px;
font-weight: 800;
letter-spacing: 0.14em;
text-transform: uppercase;
}
h1 { margin: 0; font-size: clamp(28px, 7vw, 38px); line-height: 1.02; }
p { margin: 14px 0 0; color: var(--muted); }
a.download {
display: flex;
align-items: center;
justify-content: space-between;
gap: 16px;
margin-top: 24px;
padding: 16px 18px;
border-radius: 12px;
background: var(--teal);
color: #06201b;
font-weight: 800;
text-decoration: none;
}
a.download:focus-visible { outline: 3px solid var(--amber); outline-offset: 3px; }
a.download span:last-child { font-size: 20px; }
.meta {
display: grid;
gap: 8px;
margin-top: 18px;
padding-top: 18px;
border-top: 1px solid var(--line);
color: var(--muted);
font-size: 13px;
}
code {
overflow-wrap: anywhere;
color: var(--text);
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
font-size: 12px;
}
.links { display: flex; flex-wrap: wrap; gap: 10px 18px; margin-top: 16px; }
.links a { color: var(--amber); font-weight: 700; text-decoration: none; }
.links a:hover { text-decoration: underline; }
</style>
</head>
<body>
<main>
<p class="eyebrow">SkateSpots · Android</p>
<h1>Get the signed APK.</h1>
<p>
Local-first skating map, crews, events and marketplace. No store account
required. This is the same signing key as the Zapstore and Obtanium
releases, so it updates over an existing install.
</p>
<a
class="download"
href="https://git.skate-spots.org/skatespots/SkateSpots/releases/download/v1.7.61/SkateSpots-1.7.61.apk"
rel="noopener"
>
<span>Download SkateSpots-1.7.61.apk · 56 MB</span>
<span aria-hidden="true">↓</span>
</a>
<div class="meta">
<span>Requires Android 7.0 or newer.</span>
<span>SHA-256: <code>db0279f759efd9fa05d9d1bed57a3f5856777e6ccb208d3ed78b15398f266fba</code></span>
<span>Only install APKs from a source you trust. Android will ask you to allow installs from your browser.</span>
</div>
<div class="links">
<a href="https://git.skate-spots.org/skatespots/SkateSpots/releases">All releases</a>
<a href="https://git.skate-spots.org/skatespots/SkateSpots">Source code</a>
<a href="https://skate-spots.org">Open the web app</a>
</div>
<div class="meta">
<span><strong>Obtanium:</strong> add the latest release page above as the app source, or select <em>Override Source → HTML</em> if it is not recognised.</span>
<span><strong>F-Droid repo:</strong> <a href="https://fdroid.skate-spots.org/repo">https://fdroid.skate-spots.org/repo</a> (third-party self-hosted repo; app ID <code>org.skatespots.app</code>).</span>
<span>Repo signing fingerprint: <code>88:B1:71:1C:24:02:89:FB:B2:A7:FC:C1:B3:1F:BB:9D:60:F5:7F:19:18:E0:3D:62:2D:35:F2:3D:E1:84:46:75</code></span>
</div>
</main>
</body>
</html>