rudra-js

bundleSchema

import { bundleSchema } from '@rudra-js/core';

bundleSchema lets you check a set of products you sell together at one price.

bundleSchema: z.ZodObject<{ id: z.ZodString; skus: z.ZodArray<z.ZodString>; price: z.ZodNumber; currency: z.ZodDefault<z.ZodString>; label: z.ZodOptional<z.ZodString>; }, z.core.$strict>

Reference

bundleSchema

Returns

bundleSchema.parse(set) returns a Bundle, with currency set to 'USD' when you left it out.

Caveats

  • Pass the same bundles to RudraComponent that you passed to parseTrackingInput. The block carries only the id of the set core picked. The renderer looks that id up in the list you pass it.
  • Every product in a set has to be one of your candidates. Set ids have to be unique.
  • The model writes the words around a set. It never sees the set's price.
  • Core picks the set as the page is served. It goes on the shopper's basket first, then what they've viewed, then the category being browsed.
  • Core skips a set that doesn't fit in what's left of context.maxItems, which defaults to 4. It also skips a set when any product in it is out of stock, in signals.dislikes, already shown in the block, or the product in context.currentSku.
  • A product in signals.lastPurchased or signals.cart can still be in a set.
  • label is your own name for the set. The block shows it as you wrote it, above the model's words.

Fields

NameTypeDefaultConstraints
idstring1 to 128 chars
skusstring[]2 to 5 items
pricenumbermin 0
currencyoptionalstring"USD"pattern ^[A-Z]{3}$
labeloptionalstring1 to 200 chars

Usage

Offering a bundle on a product page

Add the set to bundles in the page view. Build it from the products that go with the one on the page, and leave that product out.

import { createAnthropicProvider } from '@rudra-js/anthropic';
import { bundleSchema, createComponentGenerator, parseTrackingInput } from '@rudra-js/core';
import { RudraComponent } from '@rudra-js/react';

const generator = createComponentGenerator({
  provider: createAnthropicProvider({ apiKey: process.env.ANTHROPIC_API_KEY! }),
});

const trailKit = bundleSchema.parse({
  id: 'trail-kit',
  skus: ['SK-201', 'GT-310'],
  price: 49,
  label: 'Trail kit',
});

export async function TrailShoeRecommendations({ shopperId }: { shopperId: string }) {
  const input = parseTrackingInput({
    user: { id: shopperId },
    context: { surface: 'pdp', currentSku: 'TR-102' },
    candidates: [
      { sku: 'TR-102', title: 'Switchback Trail Shoe GTX', category: 'Trail Running', price: 174 },
      { sku: 'SK-201', title: 'Merino Hiking Socks', category: 'Socks', price: 22 },
      { sku: 'GT-310', title: 'Trail Gaiters', category: 'Accessories', price: 34 },
    ],
    bundles: [trailKit],
  });
  const spec = await generator.generate(input);

  return <RudraComponent spec={spec} products={input.candidates} bundles={input.bundles} />;
}

If no set shows up, see Bundles never appear.

Troubleshooting

Bundles never appear

Only the model asks for a bundle block. With no provider, or when the model fails, you get the block core builds without a model, which never holds a bundle. Log event.source to see whether the model answered.

Check that RudraComponent gets bundles. The renderer drops a bundle block when its set is missing from that prop.

If both are in place, either the model didn't ask for a bundle block this time, or core skipped every set you sent. Check each set against the caveats.