Local development
Run your Amba-powered app on localhost — what works in vite, next dev, expo, and React Native, and the one gotcha with magic-link callbacks.
The Amba browser SDK is designed to work in local development out of the box. Browser CORS preflight from http://localhost:* (or http://127.0.0.1:*, or http://[::1]:*) is allowed against https://api.amba.dev for every Amba project — no extra config, no proxy, no signed certificate.
This page covers what works, what doesn't, and the workarounds for the cases that don't.
What works
@layers/amba-webundervite dev,next dev,react-scripts start,parcel,webpack-dev-server, and any framework that serves onlocalhostover HTTP. Every wrapped namespace (auth,events,entitlements,config,collections,flags,storage) goes through the same fetch path and the same CORS rules.@layers/amba-expoundernpx expo start. Expo runs your app in the Expo Go shell (or a development build on a device). API calls go out from the device's network — no browser CORS involved.@layers/amba-react-nativeundernpx react-native start. Native fetch, no CORS.@layers/amba-nodeundernode --watch,tsx watch,nodemon, or any reload-on-save runner. Server-side, no CORS.
Point apiUrl at production from your local environment:
Everything tracked, fetched, or mutated during local dev hits the same project as your deployed app. If you don't want that — see Use a separate dev project below.
What doesn't work (and the workaround)
Magic-link sign-in callbacks
Magic-link emails ship the verify URL pinned to your project's deployed app URL (https://your-app.app.amba.host or your verified custom domain). Clicking a link from a localhost run lands you in the deployed app, not your local dev server.
Workarounds:
- Use email/password or anonymous auth during local dev. Magic-link is an intent verification flow — testing it on localhost is the same as testing it on production, since the verify URL is project-scoped.
- Forward the verify URL to localhost. Click the link, then copy the
?token=…query param onto your localhost URL:http://localhost:3000/auth/callback?token=…. The token validates server-side; the redirect URL never reaches the API.
Cross-origin cookies
The SDK uses header authentication, not cookies — X-Api-Key on every request, Authorization: Bearer <session_token> after sign-in. So cross-origin cookie restrictions don't apply. If you're seeing cookie warnings in dev tools, those are from your own app, not the SDK.
Service workers + offline mode
If your local dev server doesn't run a service worker (vite dev / next dev usually don't), the SDK's offline event queue is still active but uses localStorage exclusively. Events written while you're disconnected from the network will be flushed on reconnect.
Use a separate dev project
Keep your live tenant clean by running local dev against a second Amba project — same SDK code, different keys, separate database.
-
Sign up a sandbox project:
npx -y @layers/amba init(auto-detects non-TTY agent invocations and runs headlessly; in a real terminal you'll be prompted to pick or create the project). Or via the agentic flow: callamba_developer_signupand reuse the project it provisions — sandbox is the default tier for any newly-minted developer. Signup is open, so no invite code is needed; see Getting access. -
Put its keys in
.env.local: -
Reset the sandbox at any time from your developer tools. Ask your agent to run the
amba_users_reset_sandboxMCP tool, or call the admin route with your developer token:This deletes every user in the free project along with their sessions, progress, engagement and telemetry events, the media they uploaded, and other per-user data. Their tracked-link clicks stay in link stats as anonymous clicks with the user cleared. The project itself stays, so your keys keep working. The
confirmvalue must equal the project id. Only the project owner or an admin can reset, and only a free project: paid projects answer403 TIER_NOT_SUPPORTED, and server keys answer403 OWNER_CREDENTIAL_REQUIRED. The client key in your app cannot reset a project.
Security model recap
The SDK is always authenticated by X-Api-Key (your project's clientKey). The clientKey is browser-public by design — it's safe to ship in JavaScript bundles, embed in mobile apps, or paste into a dev environment. Every client request also carries either an anonymous device ID or, after sign-in, a Bearer session token.
CORS is defense-in-depth, not the security boundary. We allow localhost origins on the API because letting any origin with a valid clientKey call the API is the same posture as allowing every *.app.amba.host customer-app subdomain, which we already accept. The boundary that matters is the clientKey + Bearer token combination, not the request Origin header.