const generator = createComponentGenerator({ provider: null });
const spec = await generator.generate(input);
// → { tone: 'neutral', headline: 'Goes with your cart', blocks: [ … ] }
verify('Four stars, down from $80', { numerals: ['39'], tags: ['Cookware'] });
// → { ok: false, findings: [ { layer: 'numeral', text: '80' } ] }npm install @rudra-js/core @rudra-js/react @rudra-js/attested zod@^4.5Every package lives under the @rudra-js scope. The unscoped rudra-js package on npm belongs to someone else, so keep the @.
You need Node 22.12 or later, and zod 4.5 or later — the public API of @rudra-js/core is zod schemas, so your app and the package have to resolve the same copy. Released under the MIT license.
In a Next.js app:
import { createComponentGenerator, parseTrackingInput } from '@rudra-js/core';
import { RudraComponent } from '@rudra-js/react';
export default async function Page() {
const generator = createComponentGenerator({ provider: null });
const input = parseTrackingInput({
user: { id: 'shopper-1' },
context: { surface: 'pdp', currentSku: 'A-1', currentCategory: 'Cookware' },
candidates: catalog,
});
return <RudraComponent spec={await generator.generate(input)} products={input.candidates} />;
}Without a model — no API key, nothing billed, and a fully supported setting rather than a stub:
const generator = createComponentGenerator({ provider: null });With a model, when you are ready. Everything above keeps its shape; the model now writes the wording, the layout and the emphasis:
import { createAnthropicProvider } from '@rudra-js/anthropic';
const generator = createComponentGenerator({
provider: createAnthropicProvider({ apiKey: process.env.ANTHROPIC_API_KEY }),
});If a language model writes raw HTML, it can put a price you never charged onto your page. rudra-js never lets it write HTML. The model picks a layout, writes a headline and provides the copy — and there is no field for it to invent a price, a product name, an image or a link.
rudra-js is four packages, published together at one version.
@rudra-js/core — the contracts and logic that turn one tracking payload into one renderable component specification@rudra-js/react — renders that specification as React Server Components, with no client JavaScript@rudra-js/anthropic — talks to the Anthropic API, and is the only package that makes a billed call@rudra-js/attested — checks model-written copy against the facts a shop stands behind, with no dependenciesYou can also run it without a model at all.
Tested on Node 22.12 and the latest Node 22. Node 20 is end of life, so it is neither built nor tested. React 18.2+ or 19 as a peer, and zod 4.5+.
Questions and ideas go in Discussions, bugs in Issues, and vulnerabilities privately.