i99dash docs
Getting started

Publishing

Reference for what `publish` does, how versioning works, and what changes will break users.

i99dash publish

Does:

  1. Validate — runs the full pre-flight (see What validate does below). Schema, APP_VERSION drift, 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.
  2. Build via your buildCommand if set, else copy appRoot/distDir/.
  3. Stamp manifest.json into distDir.
  4. Tarball distDir → deterministic .tar.gz in temp.
  5. Request a presigned upload URL from the backend.
  6. Upload the tarball to the presigned URL (direct-to-CDN).
  7. 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:

CheckCostSeverityCloses
Schema-validate manifest.jsoninstantfatal(baseline)
APP_VERSION literal vs manifest.versionfilesystem walkwarningcli.md §3
manifest.version already published1 HTTPwarningcli.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 only

Tracks: 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:

reviewStatusMeaning
auto-approvedYour app is live in the catalog immediately.
pendingA 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 onlypatch (1.2.31.2.4)
New feature, backwards compatibleminor (1.2.31.3.0)
Bridge contract dependency (new host version needed)major (1.2.32.0.0) — bump minHostVersion too

What breaks users

ChangeBreaks
Rotate idOrphans every pinned home-screen shortcut. Don't.
Drop a locale from nameUsers on that locale see a fallback. Not strictly broken, but noticeable.
Bump minHostVersionUsers on older hosts see an "update your app" card instead of your mini-app.
Change url originHost rejects at launch unless the new origin is allow-listed. Coordinate with ops.
Flip safeWhileDriving: truefalseUsers 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.

On this page