Saltar al contenido principal

Implementing NubeSDK on stores with open FTP

NubeSDK apps render into slots , and slots are pieces of markup that live in the theme's template files. Official Nuvemshop themes already ship every slot, so on a standard theme apps just work.

A store with open FTP runs a private copy of the theme, frozen at the moment the FTP was opened. If that happened before May 11, 2026, when the NubeSDK slots were added to the official themes, that copy has no slot markup at all — and no app can render anything on the storefront, no matter how well the app is written.

This guide is for those stores: how to tell if you are affected, and how to add the slots back into your theme code.

What the platform already gives you

You do not need to add any script tag. The SDK loader is injected by the platform through {% head_content %}, which your theme's layout already calls. What is missing in an old FTP copy is only the slot markup — the empty divs the SDK mounts into.

1. Check whether your theme has the slots

Open your storefront, view the page source (or use the browser DevTools) and look for:

  • id="nubesdk-root" and id="nubesdk-runtime" — the SDK mount points.
  • class="js-nubesdk-slot" with a data-nubesdk-slot="..." attribute — one per slot.

If none of these appear, your theme has no slots. You can also check the code directly:

grep -rn "nubesdk-slot" .

Run it from the root of your local theme copy. No results means the same thing.

2. Download your theme code

Pull your theme with the Nuvemshop CLI FTP workflow :

nuvemshop theme ftp setup \
--ftp-server FTP_HOST \
--ftp-username FTP_USER \
--ftp-password FTP_PASSWORD \
--store-url https://yourstore.com

nuvemshop theme ftp pull

Any FTP client works too, but the CLI gives you push and watch for the rest of the process.

3. Compare against an up-to-date theme

The fastest way to find where each slot belongs is to diff your copy against a current version of the theme it was forked from — the slot calls sit right next to markup you will recognize.

  1. Get a current copy of the base theme (for example, install it on a test store and pull it, or use the theme code you already have from a store on the up-to-date theme).
  2. Diff the two trees and look only at the nubesdk-slot lines:
diff -r my-ftp-theme/ current-theme/ | grep -E '^(diff|Only in )|nubesdk-slot'

Keeping the diff / Only in lines means every match stays under the header naming the file it came from, so you can tell which template each slot belongs to.

  1. Copy each slot call you want into the equivalent place in your own templates.

Your FTP copy has diverged, so the surrounding markup will not match line by line. Use the diff to learn which file and which anchor each slot belongs to, not to paste blindly.

4. Add before_main_content first — it is mandatory

before_main_content is not just another slot. It renders the SDK's two mount points, #nubesdk-root and #nubesdk-runtime. Without #nubesdk-root the SDK does not boot at all, and without #nubesdk-runtime none of the runtime-rendered slots exist — that includes every fixed slot (corner_*, edge_*), modal_content, and drawer_left / drawer_right.

Add it as the first element inside <body> in layouts/layout.tpl:

<body class="...">

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

{# rest of the layout #}

Which renders:

<div id="nubesdk-root"></div>
<div id="nubesdk-runtime"></div>
<div class="js-nubesdk-slot" data-nubesdk-slot="before_main_content"></div>
Start here

If you only add one slot, add this one. With before_main_content in place the SDK runs, and apps using fixed, modal or drawer slots already work.

5. Add the remaining slots

Ideally, add every slot, so your theme behaves like an official one and any app can render on it. The minimum is the set of slots the apps you actually use need — start there if you cannot do all of them at once. Each slot is a single line, placed at the anchor its name describes.

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

Each slot name says where it belongs — after_header goes after the closing </header>, before_go_to_checkout right before the checkout button, and so on. For the full list of slot names and the pages each one covers, see Storefront Slots ; the diff from step 3 tells you which file in your copy holds each anchor.

Slots that repeat on the page

Only two families of slots take pick: the product grid item slots (product_grid_item_image_*, before/after_product_grid_item_name, before/after_product_grid_item_price) and the cart line item slot (before_line_item). Every other slot appears once per page and needs no pick.

These repeat many times on one page, so the SDK needs to know which entity each occurrence belongs to. pick defaults to product.id, which is already correct inside a grid item, so pass it explicitly only for the cart line item, where the entity is the line item:

{{ component('nubesdk-slot', { type: "before_line_item", pick: item.id }) }}

Image slots need a positioned container

The product_grid_item_image_{position} slots — _top_left, _top_right, _bottom_left and _bottom_right — render absolutely positioned divs over the image. Their parent element must have position: relative, otherwise the content anchors to the wrong box.

Cart slots live in two places

A store has two carts, and each cart slot has to be added to both or it will be missing on one of them:

  • The AJAX cart — the modal or drawer opened from the header, which is what most shoppers see.
  • The full-page cart on the /comprar route, which is still reachable directly and used as a fallback.

In most themes these are separate templates, so check the diff from step 3 for both before considering a cart slot done.

Cart slots and the empty cart

Cart slots are rendered hidden when the cart is empty and revealed by the platform's cart scripts through the js-visible-on-cart-filled class. The component handles both the class and the initial inline style — you do not need to add anything. It does rely on the standard cart JS being present in your theme; if your copy replaced it, verify the slot becomes visible after adding a product.

6. Push and verify

nuvemshop theme ftp push

Then, on the storefront:

  1. Confirm #nubesdk-root and #nubesdk-runtime are in the DOM.
  2. Confirm each slot you added is in the DOM with the expected data-nubesdk-slot value.
  3. Install an app and check it renders. The DevTools extension shows which slots the SDK detected on the page.

Apps can also verify at runtime with the Slot Discovery API , which lists the slots actually present on the current page.

consejo

nuvemshop theme ftp watch pushes on every save, so you can check each slot as you add it instead of waiting until the end.

Going further: your own slots

Because you control the theme code, you are not limited to the predefined slots — you can expose your own injection points with the custom_ prefix and have apps render into them.

Learn more about Custom Slots →

Help us improve NubeSDK

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