React SDK
@nopii/react puts the browser SDK in context, so any component can protect the requests it sends and reveal the tokens it renders.
Preview
Install
npm install @nopii/browser @nopii/reactVercel AI SDK chat
Wrap the app in NoPIIProvider with the routes to protect, then give useChat the protected fetch. Messages render in plaintext. /api/chat receives only tokens.
import { useChat } from "@ai-sdk/react";
import { DefaultChatTransport } from "ai";
import { NoPIIProvider, useNoPIIFetch } from "@nopii/react";
export function App() {
return (
<NoPIIProvider
config={{ baseUrl: "https://api.nopii.co", sessionToken: getSessionToken }}
protect={[{ match: "/api/chat", request: "ai-sdk" }]}
>
<Chat />
</NoPIIProvider>
);
}
function Chat() {
const fetch = useNoPIIFetch();
const { messages, sendMessage } = useChat({
transport: new DefaultChatTransport({ fetch }),
});
// render messages as usual
}getSessionToken returns a client session from your backend, cached until shortly before it expires. See Initialize for an example, and the Node.js SDK for the route that mints it.
NoPIIProvider
| Prop | Meaning |
|---|---|
config | Options for NoPII.init. Or pass client with an instance you created. |
protect | Routes to protect. Read once, when the provider mounts. |
patchGlobalFetch | Also patch the global fetch while mounted. Off by default. |
intercept | Route browser provider calls through NoPII (Tier 1). true or interception options. |
Routes are registered before any child renders, so a component that sends a request as soon as it mounts is already protected. The global patch is applied and removed with the provider, and survives StrictMode's double mount.
Hooks and components
useNoPIIFetch and useNoPII
useNoPIIFetch() returns the protected fetch. useNoPII() returns the instance, for tokenize, detect, sockets, and everything else on the browser SDK.
Revealed and useRevealed
For tokenized text you render yourself, such as a history list loaded from your API:
import { Revealed, useRevealed } from "@nopii/react";
<Revealed text={message.body} fallback={<Skeleton />} />
const { text, pending, error } = useRevealed(message.body);Tokens the page already holds render at once. Others are fetched under the reveal policy and replace the tokens when they arrive. A token the user may not see stays a token.
useRevealDom
For HTML you do not render as text, such as a third-party widget or server-rendered markup:
import { useRevealDom } from "@nopii/react";
function Transcript({ html }: { html: string }) {
const ref = useRevealDom<HTMLDivElement>();
return <div ref={ref} dangerouslySetInnerHTML={{ __html: html }} />;
}It reveals tokens anywhere inside the element as they render and stops when the element unmounts. Subtrees marked data-nopii-raw are left alone. Prefer Revealed where you can, since React then owns the revealed text.
Related
- Browser SDK: every option the provider accepts
- Node.js SDK: the /api/chat route and session endpoint