storepulse_

Tutorial

From zero to your real board. Steps 1–2 take a minute; steps 3–4 are five-minute, one-time setups on Apple's and Google's side.

step 1

Run the demo

Prerequisite: Node.js ≥ 20.12 — no clone, no install, no credentials.

$ npx storepulse demo

The demo board uses sample data shaped like a real team — two apps, each with a prod and dev variant, on both platforms. Every badge you'll ever see is in it: LIVE, 50% (staged rollout), REVIEW, REJECTED, draft. Prefer a browser? npx storepulse serve --demo serves the same board at 127.0.0.1:4780.

step 2

List your apps

$ npx storepulse init

Works in any folder — it creates storepulse.config.json and a .env template (existing files are never overwritten) and git-ignores the credential files. In a clone of this repo, cp storepulse.config.example.json storepulse.config.json does the same. Now open storepulse.config.json and list your apps:

fieldwhat it is
keyAny unique name (internal use)
nameDisplay name shown on the board
groupOptional label — e.g. prod / dev
platformios or android
storeIdiOS: numeric Apple ID · Android: package name
latestTesterUrlOptional Android HTTPS URL for the latest eligible tester build
installLinksOptional Android HTTPS URLs keyed by exact versionCode
Finding the iOS numeric ID — App Store Connect → your app → App Information → General Information → Apple ID (a number like 1234567890).

step 3

Apple — App Store Connect API key

From here on you're filling in the .env that storepulse init created (repo clone: cp .env.example .env).

  1. App Store Connect → Users and Access → Integrations → App Store Connect API
  2. Under Team Keys, click +. Role: Developer is recommended — it covers everything storepulse reads. App Manager works too, but a leaked App Manager key can submit apps and edit metadata, so grant the least privilege you can.
  3. Download the .p8 file. Apple allows exactly one download — keep it safe (storepulse init git-ignores it for you). This key can write as much as its role allows — if it ever leaks, revoke it immediately in App Store Connect.
  4. Fill in three values:
ASC_KEY_ID=ABC123DEFG          # "Key ID" column of your key
ASC_ISSUER_ID=xxxxxxxx-...     # "Issuer ID" at the top of the page
ASC_PRIVATE_KEY_PATH=./AuthKey_ABC123DEFG.p8

Console menus move around from time to time — if they have, follow Apple's official guide: Creating API Keys for App Store Connect API.

step 4

Google — Play service account

  1. In Google Cloud Console, pick (or create) a project and enable the Google Play Android Developer API.
  2. IAM & Admin → Service Accounts → create one (no roles needed) → Keys tab → Add key → JSON.
  3. In Play Console → Users and permissions → Invite new users → paste the service account email (…@…iam.gserviceaccount.com) → grant View app information on your apps. Grant only that — never give the service account any Release/publish permissions; storepulse doesn't need them, and a leaked key stays read-only.
  4. Point .env at the JSON:
PLAY_SERVICE_ACCOUNT_PATH=./service-account.json

If the console layout has changed, Google's official guide covers the same steps: Getting started with the Google Play Developer API.

CI tip — both secrets accept a *_BASE64 variant (ASC_PRIVATE_KEY_BASE64, PLAY_SERVICE_ACCOUNT_BASE64) so you can run storepulse in CI without files on disk.

step 5

Run

$ npx storepulse

Your real board appears (in a clone of this repo, pnpm status does the same). Rows with credential problems show an inline error — they never hide the rest of the board.

step 6

See it in a browser

$ npx storepulse serve

Open http://127.0.0.1:4780 — the board appears as an auto-refreshing web dashboard. If your config uses the optional group field, the selector shows one group at a time; it stays hidden when no app has a group. Each app card separates iOS and Android rows, with the latest bundle beside its delivery channels, while the OS chips filter platform rows. Click a row to expand full release notes, dates, and a TestFlight expiry countdown. Click a state badge (not the row) to open a dialog explaining what that state means, and flip the UI between English and Korean with the EN/KO switcher in the header — your browser remembers the choice. No credentials yet? npx storepulse serve --demo works too. It binds to 127.0.0.1 by default: the board may list unreleased versions, so keep it local.

Android installs — use the header navigation to open the dedicated install catalog. It shows Production and Development together. Add a fixed latestTesterUrl or provider-returned installLinks such as "41": "https://provider.example/exact-download-url". Storepulse never guesses a download URL; a release without one stays visible but is not clickable. Installing an older build may require uninstalling the current app and can remove local data.

step 7 — optional

Link Expo (EAS) builds

Ship with Expo? Add an access token to .env (create one at expo.dev → Access tokens; for organizations, prefer a View Only robot token — storepulse only reads builds and submissions) and give each Expo app in storepulse.config.json its easProjectId (app.json → extra.eas.projectId):

EAS_TOKEN=...

The snapshot JSON and the web dashboard's detail panel now show which EAS build each store version came from — commit, build profile, submission status (the terminal board keeps its summary) — and npx storepulse doctor verifies the whole EAS chain in its [5] section.

CI — optional

Fail builds on release states

$ npx storepulse check --fail-on rejected,halted

Use the normalized states live, rollout, in-review, pending, rejected, halted, draft, or unknown. Exit code 0 means no match, 1 means a policy violation, and 2 means invalid arguments or a collection error. Add --format json for machine-readable output or --demo to try it without credentials.

troubleshooting

When something's off

First, run npx storepulse doctor — it diagnoses most of the causes below automatically, with a one-line fix for each.

symptomlikely cause
ASC API 401Wrong Key ID / Issuer ID, or the .p8 doesn't match the Key ID
ASC API 404storeId isn't the numeric Apple ID, or the key's role can't see that app
Play API 403Service account not invited in Play Console, or the Android Developer API isn't enabled
Play API 404Package-name typo, or the app has never had a release
No Android review stateNot a bug — Google's API doesn't expose review status

Still stuck? Open an issue — include the exact error line from the board.