Amba
Platform

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-web under vite dev, next dev, react-scripts start, parcel, webpack-dev-server, and any framework that serves on localhost over HTTP. Every wrapped namespace (auth, events, entitlements, config, collections, flags, storage) goes through the same fetch path and the same CORS rules.
  • @layers/amba-expo under npx 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-native under npx react-native start. Native fetch, no CORS.
  • @layers/amba-node under node --watch, tsx watch, nodemon, or any reload-on-save runner. Server-side, no CORS.

Point apiUrl at production from your local environment:

await Amba.configure({
  projectId: process.env.AMBA_PROJECT_ID!,
  clientKey: process.env.AMBA_CLIENT_KEY!,
  apiUrl: 'https://api.amba.dev',
});

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 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.

  1. 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: call amba_developer_signup and 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.

  2. Put its keys in .env.local:

    AMBA_PROJECT_ID=<sandbox project id>
    AMBA_CLIENT_KEY=<sandbox client key>
  3. Reset the sandbox at any time from your developer tools. Ask your agent to run the amba_users_reset_sandbox MCP tool, or call the admin route with your developer token:

    curl -X DELETE \
      "https://api.amba.dev/v1/admin/projects/$AMBA_PROJECT_ID/users/reset-sandbox?confirm=$AMBA_PROJECT_ID" \
      -H "Authorization: Bearer $AMBA_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 confirm value must equal the project id. Only the project owner or an admin can reset, and only a free project: paid projects answer 403 TIER_NOT_SUPPORTED, and server keys answer 403 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.

On this page