Skip to content

feat(mobile): add the Expo starter and the mobile template kind - #90

Merged
Bccorb merged 3 commits into
mainfrom
feat/mobile-expo-template
Sep 13, 2026
Merged

feat(mobile): add the Expo starter and the mobile template kind#90
Bccorb merged 3 commits into
mainfrom
feat/mobile-expo-template

Conversation

@Bccorb

@Bccorb Bccorb commented Sep 13, 2026

Copy link
Copy Markdown
Contributor

Summary

Closes #36, #37, #38, #39 (the template half of the epic #40). On the published @seamless-auth/react-native 0.1.0, @seamless-auth/express 0.16.0 and @seamless-auth/fastify 0.7.0; the three lockfiles carry them as of the last two commits.

templates/mobile/expo

A complete Expo 57 + Expo Router app on @seamless-auth/react-native:

  • app/_layout.tsx: AuthProvider over bearer transport with the native ports built once at module scope (src/auth/ports.ts: react-native-passkeys, expo-secure-store, expo-web-browser); a configuration screen when EXPO_PUBLIC_API_URL is missing.
  • (auth) group: sign-in (identifier → /login → passkey attempt when the device has one → email code or magic link fallback), sign-up (register → code), verify-code (one screen for both flows; uppercases since the API's codes are six letters; textContentType="oneTimeCode"), magic-link-sent (polls /magic-link/check every 5s for 10 minutes; no deep link needed), register-passkey (enrol with describeDevice(Platform); skip only when hasNonPasskeyLoginMethod).
  • (app) group: the signed-in screen with a protected call to the companion API's /beta_users through useAuthorizedFetch().
  • Route groups redirect on the session; app/index.tsx waits for the keystore restore so a signed-in user never sees sign-in flash.
  • tools/associations/generate.mjs: writes apple-app-site-association and assetlinks.json from team id, bundle id, package, and the certificate SHA-256, and prints the android:apk-key-hash: origin from the same bytes (the hand conversion is the common failure). README covers the prerequisites that cannot be removed and the traps from docs(mobile): association file tooling and per platform setup #39.
  • Standard script set; build is expo export --platform ios --platform android, which the templates CI matrix runs without Xcode or the Android SDK. Vitest covers the pure modules; screens are exercised on a simulator.
  • Dependency versions come from npx expo install, so they are the SDK 57 set.

Repo

  • validate-templates.mjs accepts kind: "mobile"; registry.json adds expo (alias mobile, beta, templates/mobile/expo); template.json places it at mobile/ with EXPO_PUBLIC_API_URL from {{apiUrl}}, requires.cliMin: 0.16.0 (the CLI PR that learns the kind follows).
  • README: layout, registry kind comment, placeholder table (also adds the serveAdminConsole and databaseUrl placeholders the CLI already resolves), a "Mobile templates" note; AGENTS.md likewise; validate.yml says what the mobile build does and does not cover.
  • Express and Fastify starters pass authServerUrl and audience into requireAuth, so a scaffolded API accepts the auth API's access token from a native client alongside browser cookies; bumped to @seamless-auth/express ^0.16 / @seamless-auth/fastify ^0.7.

Not a shared/react-app sync target: React Native cannot use the web kit.

Verified locally

  • npm run validate (registry, manifests, shared sync); --matrix includes expo
  • In templates/mobile/expo: npm run check (typecheck against the real react-native-passkeys types, lint, format, 4 tests) and npm run build: Metro bundles for iOS (2.5MB) and Android (2.8MB) with the real SDK tarballs installed
  • tools/associations/generate.mjs output checked against the spike's known fingerprint → origin pair
  • npm install + lockfiles after the SDK releases
  • Run on a simulator against the local stack (happens in the RoxTarget pilot, which uses the same SDK)

templates/mobile/expo is a complete Expo Router app on
@seamless-auth/react-native: sign up and sign in with a one-time email code, a
sign-in link by polling, or a passkey; passkey enrolment after sign up; route
groups gated on the session; and a protected call to the companion API through
useAuthorizedFetch. The session lives in the platform keystore between
launches. tools/associations/generate.mjs writes the two association files
native passkeys need from one set of inputs and prints the matching Android
origin, so the hex fingerprint and its base64url form cannot drift apart.
build is expo export for iOS and Android, which CI can run without a native
toolchain.

The validator accepts kind mobile, the registry lists the starter as expo
(alias mobile, beta), and the manifest places it at mobile/. The Express and
Fastify starters pass authServerUrl and audience into requireAuth so a
scaffolded API accepts a native client's access token alongside cookies.

Refs #36, #37, #38, #39.
@Bccorb
Bccorb force-pushed the feat/mobile-expo-template branch from df84831 to 694d844 Compare September 13, 2026 16:21
@Bccorb
Bccorb marked this pull request as ready for review September 13, 2026 16:49
@Bccorb
Bccorb merged commit 0d07fb1 into main Sep 13, 2026
3 checks passed
@Bccorb
Bccorb deleted the feat/mobile-expo-template branch September 13, 2026 19:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(mobile): add an Expo mobile template

1 participant