Skip to main content
Lynx is ByteDance’s cross-platform UI framework (Android, iOS, web), and ReactLynx is its React flavor. There is no @glinr/theauth-lynx package. The framework-neutral session store in @glinr/theauth-client is what a Lynx app uses, and this page says what it needs from the runtime, what I checked and what I did not.
I did not run this on a Lynx simulator or device. The checks below are the Lynx documentation, a type check of the recipe against @lynx-js/react 0.126.0, and a test that runs the store against the real theAuth handler with the globals Lynx lacks removed. Treat the cookie and fetch notes as the first things to test on a device.

What Better Auth does

Better Auth documents Lynx with a better-auth/lynx entry that exports createAuthClient and a useStore hook over its nanostores session atom, with @lynx-js/react as the only added dependency. Its page says nothing about cookies, storage or the thread model, so it does not tell you what the runtime needs.

What Lynx gives you

From the Lynx docs (networking, fetch reference, best practices, @lynx-js/react):
  • fetch is provided and described as compatible with the Web API, with “subtle differences”. It needs the HTTP service of the integrated Lynx Service. The compatibility note says Lynx does not support Web-only features like CORS, redirect and keepalive, and that FormData and Blob are unsupported. credentials, AbortController and signal are not mentioned.
  • No web storage. I found no built-in localStorage. The Lynx native modules guide shows a storage module you write yourself on each platform.
  • No TextEncoder or TextDecoder in PrimJS, the JavaScript engine. Lynx ships TextCodecHelper for UTF-8.
  • React 17 API. ReactLynx follows React 17 and skips concurrent features such as useTransition. useSyncExternalStore is in the @lynx-js/react API reference.
  • Two threads. Rendering runs on the main thread. Effects, event handlers and native module calls belong on the background thread, and calling native modules from the main thread blocks the UI.

What the session store needs

The store change that came out of this check: refresh used new AbortController() unconditionally and would throw where it is missing. It is now optional, and packages/client/tests/session-store-email-password.test.ts runs a full sign up, verify, sign in, refresh, rehydrate and sign out against the real handler with AbortController, window, localStorage, TextEncoder and TextDecoder removed.

Recipe

Sign-in goes through the email and password routes. Lynx has no page origin, so basePath is an absolute URL. Storage is a native module you implement, and the store persists through it by subscribe and hydrateSession, because native calls are asynchronous and the store’s own storage hook is synchronous.
lib/auth.ts
SignIn.tsx
Both files type check against @lynx-js/react 0.126.0 and @glinr/theauth-client. The thread rules are yours to apply: keep startAuth and the handlers that call store on the background thread.

What a first-class Lynx client would need

I would not add a package yet. If Lynx use turns out to be real, in order:
  1. A device check of fetch with the bearer token: does the response body parse, is Set-Cookie kept, does credentials: "include" do anything.
  2. An async storage option on the session store (getItem returning a promise), so the native module recipe collapses into one option. Expo already has this shape in TheAuthStorage.
  3. A thin useSyncExternalStore hook export from a @glinr/theauth-client/lynx subpath, which is what Better Auth ships, so users do not copy the hook.
  4. Whether @glinr/theauth-react runs unchanged under @lynx-js/react (it uses useSyncExternalStore, useMemo and the automatic JSX runtime). It is untested, which is why the recipe uses the store directly.
Last modified on October 19, 2026