> ## Documentation Index
> Fetch the complete documentation index at: https://docs.blursec.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Frontend

# Mobile & frontend apps

The SDK is isomorphic — it runs in browsers, edge runtimes, Deno, and Bun,
not just Node. But for React, Flutter, or any mobile/SPA app, the question
isn't *"does it run?"* — it's *"where should it run?"*

**Rule: the API key never ships in a client app.** Anything bundled into
JavaScript or a mobile binary is public — anyone can extract a `bsk_` key
from a JS bundle or a decompiled APK and use it against your account. So the
architecture is the same for every frontend framework:

```text theme={null}
React / Flutter / Swift / Kotlin app
        │  POST /login (your backend, over TLS)
        ▼
Your server  ──  @blursec/sdk  ──►  Blursec API
                (key stays here)    (sees only a 10-char hash prefix)
```

Your frontend needs **zero Blursec code**. The credential check lives in
front of `/login` on your server — see
[examples/login-endpoint.ts](https://github.com/blur-sec/blursec-sdk/blob/main/examples/login-endpoint.ts). That's by
design: it keeps the key secret *and* keeps the 1500 ms fail-open latency
budget where it belongs.

## React / Vue / SPA (web)

For login, do nothing special — the form posts to your backend as usual and
the server runs `credentials.check`.

There is one pattern where client-side SDK code genuinely helps: **pre-hash
screening**. The hash helpers (`hashCredential`, `hashString`) work in any
modern browser via `crypto.subtle`, so a signup or password-change form can:

1. Hash `email:password` locally with `hashCredential()`.
2. Send **only the 64-char digest** to your backend.
3. Your backend calls `credentials.checkHash(digest)` — and Blursec still
   only ever sees the first 10 characters.

The plaintext password never leaves the page, never appears in your server
logs, and never reaches Blursec. Full working example:
[examples/react-prehash.tsx](https://github.com/blur-sec/blursec-sdk/blob/main/examples/react-prehash.tsx).

Caveats:

* `crypto.subtle` requires a **secure context** (HTTPS or `localhost`).
* This is for *screening* (signup, password change, security checkups). For
  *login* your server needs the password anyway to verify it against your
  own store — hash server-side there.
* Never call the Blursec API directly from the browser, even with hashes —
  that requires shipping the key. Always proxy through your backend. See
  [examples/browser.ts](https://github.com/blur-sec/blursec-sdk/blob/main/examples/browser.ts) for the longer sermon.

## React Native / Expo

Two extra wrinkles:

* **No `crypto.subtle`.** Hermes does not implement WebCrypto, so
  `hashCredential()` throws. Either polyfill it
  (`react-native-quick-crypto` exposes a compatible `subtle`, inject it
  before importing the SDK) or — simpler and recommended — don't hash on
  the device at all and let your backend do everything.
* **Same key rule.** A key in an `.ipa`/`.apk` is public. Proxy through
  your backend.

The recommended React Native integration is therefore identical to web:
post credentials to your own `/login` over TLS, check server-side.

## Flutter, Swift, Kotlin, and everything else

There is no Dart/Swift/Kotlin SDK, and for the standard integration you
don't need one — the app talks to *your* backend, and your backend (Node,
edge, or anything that can run this SDK) talks to Blursec.

If you have a hard requirement to hash on-device (e.g. an offline-first
password screener), the protocol is deliberately tiny and documented in
[Advanced usage](/docs/advanced):

1. `digest = SHA-256(lowercase(trim(email)) + ":" + password)` as lowercase hex.
2. Send the first 10 chars (`HASH_PREFIX_LENGTH`) to
   `POST /v1/credentials/check` — *from your backend*, which holds the key.
3. Compare the returned suffixes against your local digest.

Every platform above has a native SHA-256 (CryptoKit, `crypto` in Dart,
`MessageDigest` in Kotlin), so step 1 is a few lines anywhere.

## Decision table

| You're building…             | Do this                                                                                                                                               |
| ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| React/Vue/Svelte login       | Nothing client-side. Server-side `check()` in your login route.                                                                                       |
| SPA signup / password change | Optional: pre-hash in the browser, `checkHash()` on your backend.                                                                                     |
| React Native / Expo app      | Post to your backend; avoid on-device hashing (no WebCrypto in Hermes).                                                                               |
| Flutter / native mobile      | Post to your backend; no Blursec code in the app.                                                                                                     |
| Next.js / Remix / Nuxt       | SDK in route handlers / server actions — these are servers; works as-is.                                                                              |
| Static site, no backend      | Use an edge function as proxy — see [examples/cloudflare-worker.ts](https://github.com/blur-sec/blursec-sdk/blob/main/examples/cloudflare-worker.ts). |
