Publishing
Reference for what `publish` does, how versioning works, and what changes will break users.
i99dash publishDoes:
- Validate — runs the full pre-flight (see What
validatedoes below). Schema,APP_VERSIONdrift, and same-version-republish warning all fire here. Failures exit non-zero before any upload-url is minted, so a stale CLI costs you ~150 ms instead of 15 seconds. - Build via your
buildCommandif set, else copyappRoot/→distDir/. - Stamp
manifest.jsonintodistDir. - Tarball
distDir→ deterministic.tar.gzin temp. - Request a presigned upload URL from the backend.
- Upload the tarball to the presigned URL (direct-to-CDN).
- Submit the manifest with the bundle id to the catalog.
--dry-run runs 1–4 and stops. Useful for CI smoke checks before you
have an SSH key registered (or a token in I99DASH_TOKEN).
What validate does
i99dash validate is the canonical pre-flight. publish runs it
first; you can run it on its own from a PR check or a pre-commit hook.
Layered checks, ordered by cost:
| Check | Cost | Severity | Closes |
|---|---|---|---|
Schema-validate manifest.json | instant | fatal | (baseline) |
APP_VERSION literal vs manifest.version | filesystem walk | warning | cli.md §3 |
manifest.version already published | 1 HTTP | warning | cli.md §4 |
The schema check is fatal; everything else is structured so a caller
can run with --offline (or no I99DASH_TOKEN) and still get the
schema + drift checks.
i99dash validate # full preflight (HTTP-backed checks too)
i99dash validate --offline # schema + filesystem checks onlyTracks: production vs beta
By default, publish lands on the production track — every user
sees the new bundle on next launch. Pass --track beta to ship to a
limited cohort of testers instead:
i99dash publish --track beta --release-notes "Rebased map tiles"The bundle is the same; only the catalog pointer changes. Full walkthrough — inviting testers, promoting beta to production, and the limits — is at Beta testing.
What "published" means
After submit, your app enters one of two states:
reviewStatus | Meaning |
|---|---|
auto-approved | Your app is live in the catalog immediately. |
pending | A human review is queued. You can keep iterating locally; re-running publish bumps a new bundle under the same review ticket. |
If your previous version was rejected or revoked, the next
publish lands in pending instead of auto-approving — the platform
team gets a second look so a previously-rejected app doesn't
silently re-appear with new bytes. Want a re-review of the existing
bundle without uploading new bytes? Use the developer portal's
"Request re-review" button on the rejected app card.
You'll receive notifications on every state change:
- A Telegram DM when an admin approves, rejects, or revokes (with the reason inline).
- A portal inbox row at
/developers/inbox— same events, durable record. Email-only developers (or anyone whose Telegram was undeliverable) rely on the inbox for parity.
Run i99dash status from the CLI to see every app's current
review status + rejection reason in a single round-trip.
Versioning
The version field is opaque to the backend but has one rule you
can't dodge: incrementing is mandatory per publish. The backend
rejects a resubmission with the same id and version. Pick semver
(1.2.3) so the number reflects the change size.
The id is durable and should never change post-publish — it
lives in pinned home-screen shortcuts on users' devices. Rotating
id orphans every launcher icon anyone ever pinned for your app.
Updating after publish
Just i99dash publish again with a new version. No separate
"update" command — publish is idempotent per (id, version).
Versioning strategy
| You changed… | Bump |
|---|---|
| Copy / CSS only | patch (1.2.3 → 1.2.4) |
| New feature, backwards compatible | minor (1.2.3 → 1.3.0) |
| Bridge contract dependency (new host version needed) | major (1.2.3 → 2.0.0) — bump minHostVersion too |
What breaks users
| Change | Breaks |
|---|---|
Rotate id | Orphans every pinned home-screen shortcut. Don't. |
Drop a locale from name | Users on that locale see a fallback. Not strictly broken, but noticeable. |
Bump minHostVersion | Users on older hosts see an "update your app" card instead of your mini-app. |
Change url origin | Host rejects at launch unless the new origin is allow-listed. Coordinate with ops. |
Flip safeWhileDriving: true → false | Users get the "not available while driving" dialog they didn't used to see. Communicate in release notes. |
CI integration
# .github/workflows/publish.yml
- run: pnpm install --frozen-lockfile
- run: i99dash validate
- run: i99dash build
- run: i99dash publish
env:
I99DASH_TOKEN: ${{ secrets.I99DASH_TOKEN }}Use validate as a PR check; reserve publish for tag-triggered
workflows.