Quickstart
From zero to a running mini-app in five minutes. Copy-paste the commands; nothing else to configure.
This is the fast path. You'll scaffold a mini-app, run it locally with a simulated host, and publish it to the catalog. ~5 minutes if your machine already has Node 20+.
If anything fails: jump to Troubleshooting. If you want the longer reading first: What is a mini-app?.
Prerequisites
| Tool | Version | Check |
|---|---|---|
| Node | ≥ 20 | node --version |
| pnpm | ≥ 9 | pnpm --version |
| Git | any | git --version |
If your machine is fresh, see Installation for a full prereq walkthrough.
1 — Scaffold
pnpm dlx @i99dash/sdk-cli init my-app
cd my-app
pnpm installYou get:
my-app/
├── package.json
├── manifest.json ← the row the catalog stores
├── sdk.config.json ← dev-server config
├── src/index.html ← your app
└── mocks/
└── fuel-stations.GET.json2 — Run locally
pnpm devsdk-dev-server boots at http://127.0.0.1:5173. Open it — you'll see a
hello-world page. The control panel at http://127.0.0.1:5173/_sdk/ui lets
you toggle driving state, VIN, locale, and theme live.
Your first real edit
Open src/main.ts and replace its body with:
import { MiniAppClient } from '@i99dash/sdk';
const root = document.querySelector('#root')!;
const ctx = await MiniAppClient.fromWindow().getContext();
root.innerHTML = `
<h1>Hello from your first mini-app</h1>
<p>App: <code>${ctx.appId}</code></p>
<p>Locale: <code>${ctx.locale}</code> · Dark: <code>${ctx.isDark}</code></p>
`;Save. The dev-server hot-reloads. Open /_sdk/ui and flip the locale —
the page re-renders the new value when you reload. That's the bridge
working: getContext() reads from the dev-server's shim, the same way
it reads from the real host in production.
3 — Validate the manifest
manifest.json is the catalog row for your app. The scaffold creates a
minimal one:
{
"id": "my-app",
"name": { "en": "My App", "ar": "تطبيقي" },
"iconUrl": "https://your-cdn.example.com/icons/my-app.png",
"url": "https://your-cdn.example.com/my-app/",
"version": "0.1.0",
"category": "info"
}(Real iconUrl and url must point at an origin the host's
allow-list recognises — coordinate with ops before publishing.)
Three rules the backend won't let you bend after publish: id is forever,
version must increment on every publish, url and iconUrl must be on
the host's allow-list. Full details: MiniAppManifest.
pnpm validateCI-friendly: exit 0 on valid, exit 3 on schema failure. Catches
missing locales, http:// URLs, and other paper cuts before they hit
the backend.
4 — Log in
pnpm dlx @i99dash/sdk-cli loginOpens a browser → you approve → CLI stores the API key in your OS keychain. Full flow (incl. CI / headless): Authentication.
5 — Publish
pnpm publish # validate → build → tarball → upload → submit
# or
pnpm publish --dry-run # all of the above without uploadingThe CLI prints a status URL you can share to track review / rollout. Full reference: Publishing.
That's it
Your app is live in the i99dash catalog. Users who install it from the Store tab get your bundle on next launch.
What just happened?
You connected your code to the host bridge, made a backend-style call
through it (well, just getContext() — but every call uses the same
mechanism), and shipped a bundle to a CDN catalog. The next page goes
deep on the mental model — read it once and the rest of the SDK clicks.
Next
The bridge
What `MiniAppClient` actually wraps, and why your code never touches it directly.
Calling your backend
The next thing you'll want to do. Mental model + working example.
Fetch and render a list
The simplest real recipe — call your backend, render JSON, handle errors. ~10 minutes.
Best practices
The non-obvious rules that prevent production incidents. Read before shipping.