Drop X-Auth into the App Router. advice() in a client component, verify() in a route handler โ same project, same SDK.
The React SDK powers client components; the core SDK runs server-side in route handlers.
npm install @xentranet/x-auth-react @xentranet/x-authXAuthProviderAdd a thin client wrapper so the provider renders below your server-rendered html/body shell.
'use client';
import { XAuthProvider } from '@xentranet/x-auth-react';
export function Providers({ children }: { children: React.ReactNode }) {
return (
<XAuthProvider tenantId={process.env.NEXT_PUBLIC_XAUTH_TENANT_ID!}>
{children}
</XAuthProvider>
);
}import { Providers } from './providers';
export default function RootLayout({ children }: { children: React.ReactNode }) {
return <html><body><Providers>{children}</Providers></body></html>;
}advice() from a client componentUse useXAuth() in any client component. The returned bearer is bound to the action you described.
'use client';
import { useXAuth } from '@xentranet/x-auth-react';
export function TransferForm() {
const { advice } = useXAuth();
async function submit(amount: number) {
const { decision, access_token } = await advice({
action: 'transfer', amount, currency: 'USD',
});
if (decision !== 'ALLOW') return;
await fetch('/api/transfer', {
method: 'POST',
headers: { Authorization: `Bearer ${access_token}` },
body: JSON.stringify({ amount }),
});
}
return <button onClick={() => submit(2999)}>Transfer</button>;
}Stand up an App Router endpoint that calls verify() and asserts the bound action+amount match the request body.
import { NextResponse } from 'next/server';
import { XAuth } from '@xentranet/x-auth';
const xauth = XAuth.init({ tenantId: process.env.XAUTH_TENANT_ID! });
export async function POST(req: Request) {
const bearer = req.headers.get('authorization')?.replace('Bearer ', '');
const body = await req.json();
const { transaction_ctx } = await xauth.verify(bearer, {
expect: { action: 'transfer', amount: body.amount },
});
await ledger.transfer(transaction_ctx);
return NextResponse.json({ ok: true });
}Push the verify() into Server Actions, or front it with middleware.