For the complete documentation index, see llms.txt. This page is also available as Markdown.

Verified Dashboard with the React SDK

Build a multi-page dashboard with popup sign-in, protected routes, and content gating using the React SDK — covers HumanityProvider, HumanityGate, and HumanityProfile in a Vite + React App

This guide uses the sandbox environment.

The SDK QuickStart gets auth working on one page. This adds routing, a protected dashboard gated on real preset data, and a profile page listing every identity:read preset's status.

Full list is under SDK OAuth Scopes and Presets.


Before you start

You need:

New to this? See the Generating Mock Credentials guide.


01. Create the project

bun create vite verified-dashboard-react-sdk --template react-ts
cd verified-dashboard-react-sdk
bun add @humanity-org/react-sdk react-router-dom
bun add -d vite-plugin-node-polyfills @types/node

Update vite.config.ts:


02. Configure the Developer Portal

Go to developers.humanity.org, open your application, and switch to the Sandbox tab in Settings.

  • Add http://localhost:5173/ as a redirect URI

  • Under scopes, enable:

    • OpenID Connect (openid)

    • Identity Information (identity:read)

The SDK matches the callback by origin + path only, ignoring the query string — so your redirect URI can point straight at /. No dedicated callback route needed.


03. Set up environment variables

Create .env.local at the project root:

Get your client_id from the Developer Portal under your application's Sandbox tab.


04. Set up the folder structure


05. Wire up HumanityProvider and routing

HumanityProvider must sit inside BrowserRouter.

Replace src/main.tsx:


06. Add the protected route

Create src/components/ProtectedRoute.tsx:


07. Build the app routes

Replace src/App.tsx:


08. Build the Home page

Create src/pages/Home.tsx:

The useEffect covers the case where an already-authenticated user lands on / — they skip the login screen and go straight to the dashboard.


09. List the identity presets

identity:read covers 12 presets — Profile lists all of them. Both pages also share a couple of small helpers for working with batch results, so this is worth its own file instead of duplicating them.

Create src/presets.ts:

Batch limit: verifyAll() caps at 10 presets per call — requesting all 12 fails. verifyAllBatched() splits into batches of PRESET_BATCH_LIMIT, runs them in parallel, and flattens the results.

10. Build the Dashboard

Create src/pages/Dashboard.tsx:

Each social card asks two separate questions: is this platform linked at all, and if it is, does the link actually carry any data?.

Three states instead of two — not-linked, linked-empty, linked — a linked-but-empty account is a real case, not an edge case then humanVerified runs through isPassed() .

Once it flips true, the heading drops "Linked accounts" and welcomes the user by their humanity_uuid instead, falling back to "Verified human" only if that specific preset didn't come back verified.

verifyAll returns the preset field in camelCase — request is_human and the response comes back as isHuman. Because of this, looking up a result using the exact string you requested won't match through usePresets's built-in isVerified() / getResult(). findPresetResult() handles this by matching on presetName instead, which preserves the original request string.


11. Build the Profile page

Create src/pages/Profile.tsx:

resultFor reuses the Dashboard's findPresetResult(), so the lookup logic stays in one place. Most values are rendered with a plain JSON.stringify. social_accounts gets its own table instead — one row per account beats scanning a JSON blob for who's linked.


12. Add styles

Replace src/index.css:


12. Run it

Open http://localhost:5173. Click Sign in with Humanity, complete consent, and you'll land on the Dashboard.

  • Once is_human passes, the heading swaps to your humanity_uuid and each platform gets its own card, color-coded by link status

  • /profile lists all 12 identity:read presets — status, value, and the full social_accounts breakdown

  • Sign out clears the session and drops you back at /

⚠️ Firefox and Safari users: both can clear sessionStorage mid-redirect during cross-domain OAuth. The SDK always stores the PKCE verifier and OAuth state there, regardless of the storage prop — so a clear mid-flow breaks the callback with a state/PKCE mismatch.

Switch to Chrome or Brave if you hit this in testing.


How it works

The SDK owns the full OAuth flow internally — PKCE, token exchange, storage. On your side: isAuthenticated for route protection, user for profile data, usePresets().verifyAll() for a batch check across every preset you care about, and a simple count or per-preset lookup for gating.

Compare with the Frontend OAuth with the Connect SDK guide — there you call buildAuthUrl(), exchangeCodeForToken(), and verifyPresets() directly. Here you drop in components.

Next steps

The Human First Content Platform App builds on this same project — same HumanityProvider setup, same usePresets pattern — but swaps the single is_human gate for four content tiers, each unlocked by its own preset.

Last updated