Read the current user

Get the signed-in user's ID, email and profile on the client and the server.

On the client

useUser() returns the user's profile. useAuth() returns IDs and actions.

tsx
"use client";
import { useUser, useAuth } from "@daywalker/auth/react";

export function Greeting() {
  const { isLoaded, user } = useUser();
  const { isSignedIn } = useAuth();

  if (!isLoaded) return <p>Loading…</p>;   // first render, before the session is known
  if (!isSignedIn) return <p>Hello, stranger.</p>;

  const email = user!.emailAddresses.find((e) => e.primary)?.email;
  return <p>Hello, {user!.firstName ?? email}!</p>;
}

Always check isLoaded first. On the very first render the SDK hasn't asked the server yet, so the user is unknown, which is not the same as signed out.

The user object looks like this:

json
{
  "id": "user_2x8k…",
  "firstName": "Ada",
  "lastName": "Lovelace",
  "imageUrl": null,
  "emailAddresses": [
    { "id": "email_9f…", "email": "[email protected]", "primary": true, "verified": true }
  ],
  "publicMetadata": {},
  "twoFactorEnabled": false,
  "lastSignInAt": "2026-10-21T20:15:00.000Z",
  "createdAt": "2026-10-01T12:00:00.000Z"
}

On the server

auth() gives you the IDs instantly from the session token, with no network call:

ts
import { auth } from "@daywalker/auth/nextjs";

const { isSignedIn, userId, sessionId } = await auth();

For profile details, fetch the user with the backend API:

tsx
// app/account/page.tsx
import { Suspense } from "react";
import { auth, backend } from "@daywalker/auth/nextjs";

export default async function Account() {
  const { userId } = await auth();
  if (!userId) return null;
  return (
    <main>
      <h1>Your account</h1>
      {/* The heading shows immediately; the profile streams in when ready */}
      <Suspense fallback={<p>Loading profile…</p>}>
        <Profile userId={userId} />
      </Suspense>
    </main>
  );
}

async function Profile({ userId }: { userId: string }) {
  const user = await backend().users.get(userId);
  return <p>{user.emailAddresses[0].email}</p>;
}

Tip Use userId as the foreign key in your own database (e.g. orders.owner_id). It never changes, unlike email addresses.

Public and private metadata

Field Visible to Use it for
publicMetadata The user's browser and your server Non-sensitive data your UI needs, like a plan name
privateMetadata Your server only (backend API). Encrypted at rest. Internal IDs, such as a billing customer ID