@supa-media/dev
v1.0.1
Published
Development orchestrator — runs Convex dev + Expo together
Readme
@supa-media/dev
One command that starts a Convex + Expo app. supa-dev runs the Convex dev
server and Metro together in one terminal with labeled, colored output, and
handles the small chores that otherwise cost you the first five minutes of every
session: a stale lockfile, a leftover process squatting on the Metro port, and
wiring EXPO_PUBLIC_CONVEX_URL through to Expo.
Install
pnpm add -D @supa-media/devThen wire it up at the workspace root:
{
"scripts": {
"dev": "supa-dev",
"dev:mobile": "supa-dev --mobile",
"dev:convex": "supa-dev --convex"
}
}Flags
| Flag | What runs |
| --- | --- |
| (none) | Convex dev and expo start --web |
| --convex | Convex dev only |
| --mobile | Expo only, no platform flag (Expo picks) |
| --web | Expo only, --web |
| --ios | Expo only, --ios |
| --android | Expo only, --android |
Flags are matched by exact presence in process.argv; unknown arguments are
ignored. --convex suppresses Expo even if another platform flag is also passed.
What it does, in order
- Finds the workspace root by walking up from the cwd for a
pnpm-workspace.yamlorpnpm-lock.yaml. - Loads
supa.config.js/supa.config.tsfrom that root, if present (.tsneedstsxorts-noderesolvable). Readsdev.metroPort(default8081) andconvex.functionsDir. - Reinstalls if the lockfile moved. Compares
pnpm-lock.yaml's mtime+size against a marker atnode_modules/.pnpm-lock-hashand runspnpm installwhen they differ (or whennode_modulesis missing). - Resolves the Convex URL —
EXPO_PUBLIC_CONVEX_URLfrom the environment, else from.env.local, else derived fromCONVEX_DEPLOYMENTashttps://<slug>.convex.cloud— and passes it to the Expo child process. - Spawns
npx convex dev [--functions <dir>]from the workspace root, andnpx expo start --port <port> [platform flag]from the first ofapps/mobile,apps/expo, or the root that contains anapp.json/app.config.js/app.config.ts.
Before starting Expo it frees the Metro port by lsof-ing the listener and
kill -9ing it. SIGINT/SIGTERM shuts both children down, and if either child
exits non-zero the other is killed too.
⚠️ Two side effects you should know about before wiring this into a script. It will run
pnpm installon your behalf when the lockfile has changed, and it will kill whatever is listening on the Metro port — including an unrelated process on 8081. Both are unconditional.lsof/killalso means macOS and Linux only.
Running with --mobile, --web, --ios, or --android and no reachable Convex
URL exits 1 rather than starting Expo against nothing.
Programmatic use
require("@supa-media/dev") exposes run() (the same entry point the bin calls,
reading process.argv itself) plus the helpers findWorkspaceRoot,
getConvexUrl, ensureDependencies, and killProcessOnPort.
No tests ship with this package.
Part of the Supa Media framework — https://github.com/Supa-Media/supa-framework. MIT.
