Pular para o conteúdo principal

Custom Slots

Besides the predefined storefront and checkout slots, a theme can expose its own injection points, called custom slots. This lets a theme developer decide exactly where apps are allowed to render, in places the predefined slots don't cover.

Declaring a custom slot in the theme

A theme exposes a custom slot by placing the nubesdk-slot component in a template, with a type that follows the custom slot naming rules:

{{ component('nubesdk-slot', { type: "custom_this_is_a_special_slot" }) }}

Once the theme renders this, the slot custom_this_is_a_special_slot becomes a target that any app on the store can render into.

Naming rules

A custom slot name must:

  1. Start with the custom_ prefix.
  2. Be written in snake_case.
  3. Be entirely lowercase.
  4. Contain only letters, numbers, and underscores (_) after the prefix.
Slot nameValidReason
custom_promo_bannerFollows every rule.
custom_promo_banner_2Digits are allowed.
custom_promoBannerNot lowercase / not snake_case.
custom_promo-banner- is not an allowed character.
promo_bannerMissing the custom_ prefix.

Rendering into a custom slot

From your app, render into a custom slot exactly like any predefined slot — pass its name to nube.render():

import type { NubeSDK } from "@tiendanube/nube-sdk-types";
import { Box, Text } from "@tiendanube/nube-sdk-jsx";

export function App(nube: NubeSDK) {
nube.render("custom_this_is_a_special_slot", [
<Box key="promo">
<Text>Rendered into a theme-defined custom slot 🎉</Text>
</Box>,
]);
}

Clear it the same way:

nube.clearSlot("custom_this_is_a_special_slot");

Type-level validation

The naming rules are enforced at the type level through the CustomUISlot type, so an invalid custom slot name is rejected by TypeScript at the call site of render / clearSlot:

import type { CustomUISlot } from "@tiendanube/nube-sdk-types";

type A = CustomUISlot<"custom_promo_banner">; // "custom_promo_banner"
type B = CustomUISlot<"custom_promoBanner">; // never — not lowercase / snake_case
type C = CustomUISlot<"custom_promo-banner">; // never — invalid character "-"
type D = CustomUISlot<"promo_banner">; // never — missing "custom_" prefix
nube.render("custom_promo_banner", [/* ... */]); // ✅ compiles
nube.render("custom_promo-banner", [/* ... */]); // ❌ type error

Predefined checkout and storefront slots remain direct members of the slot union, so editor autocomplete for the fixed slot names is preserved.

Handling missing custom slots

Because custom slots depend on the theme, an app can't assume a given custom slot exists on the current store. Render into the name you agreed on with the theme; if the theme hasn't declared that slot, there is simply no target for your content.

You can use the Slot Discovery API to detect whether a custom slot is present: the API classifies every slot on the page as either dynamic-section or static, and custom slots are reported in the static bucket — so they show up in getStatic() (and getAll().static).

One caveat: StaticSlot.slotId is typed as CheckoutUISlot | StorefrontUISlot and does not include custom slot names, so a custom_* slotId won't be recognized by that type. Match it with a plain string check (e.g. slot.slotId === "custom_promo_banner").

Help us improve NubeSDK

Found an issue or have a suggestion? Let us know on GitHub.