Next.js SDK — API Reference & Troubleshooting
Reference for the @bildit-platform/nextjs and @bildit-platform/nextjs-api APIs used in the Integration Guide, plus how free-trial plan entitlement gates production rendering and how to diagnose a blank production site.
How rendering works (architecture)
There are two independent paths, and they never touch each other:
- Visual Editor (postMessage). When a page is opened inside the VEE, the site's editor bridge and the Visual Editor handshake over
postMessage(IFRAME_READY→INJECT_SCRIPT→SCRIPT_INJECTED): the site injects the Visual Editor script, and the editor pushes scheduled content to it viapostMessage. This is for editing slots; it works regardless of plan / API-key state and never calls the public scheduled content endpoint. - Production site (server fetch). On your real website, the
@bildit-platform/nextjsSDK fetches published scheduled content server-side from{BILDIT_API_URL}/remote-webbanners_v1_4and renders it throughBilditProvider+SlotPlaceholder.
Because they're separate, scheduled content can render in the VEE preview while showing nothing on the production site — that difference is almost always plan entitlement (a free-trial plan is blocked on production) or a location mismatch (below).
Free-trial plan entitlement
Whether your key serves on the production site depends on your plan, not the key itself. On a free trial, the production endpoint returns nothing (the live site stays blank) — while the Visual Editor still renders, because the editor uses a separate path that doesn't go through the keyed endpoint. Upgrade to a paid plan and the same key serves on production; no key re-issue needed.
| Where | Free trial | Paid plan |
|---|---|---|
| Visual Editor | ✅ renders | ✅ renders |
| Production site (real traffic) | 🚫 blank | ✅ renders |
That's the signature of a free trial, not a key problem. The same key serves once you upgrade. Working as designed.
RemoteConnector (@bildit-platform/nextjs-api)
Server-side data connector. Construct it with your key + Functions base URL, then call getWebBanners.
new RemoteConnector(options)
| Option | Type | Required | Notes |
|---|---|---|---|
key | string | ✅ | Your web instance API key (sent as ?key=). |
baseURL | string | ✅ | VEE Functions base URL. The SDK appends /remote-webbanners_v1_4. |
appCheckToken | string | — | Firebase App Check token, if enabled. |
previewDate | string | — | Sent as the X-Bildit-Preview-Date header. |
timeout | number | — | Request timeout (ms); default 30000. |
onResponseFulfilled / onResponseRejected | function | — | Axios response interceptors. |
getWebBanners(params)
const result = await connector.getWebBanners({
location: pathname, // match scheduled content by page path
date: previewDate, // optional preview date
mode: 'csr',
tomorrow: true,
source: 'live',
})
// result.data => WebBanner[]
| Param | Type | Notes |
|---|---|---|
location | string | Matched against each scheduled content item's assigned location(s). Omit/mismatch → empty result. |
date | number | string | Preview date; omit for production "now". |
mode | 'csr' | 'ssr' | 'both' | Render mode. |
tomorrow | boolean | Include scheduled content set to start soon. |
source | 'auto' | 'live' | 'cdn' | 'live' fetches the Functions endpoint directly. |
apiVersion | string | Optional version prefix. |
Returns { data, codelib, lastUpdated, meta }; pass data (WebBanner[]) to BilditProvider's banners prop — see the Integration Guide for the wiring.
BilditProvider (@bildit-platform/nextjs)
Client component that processes fetched scheduled content and exposes it to SlotPlaceholder.
| Prop | Type | Required | Notes |
|---|---|---|---|
banners | BannerType[] | ✅ | The data from getWebBanners. |
extraDependenciesConfig | Record<string, { module, globalName? }> | recommended | Modules scheduled content may import (see cmsDependencies in the guide). |
content | RemoteContentResponse[] | — | Remote content blocks, if used. |
extraStyles | string[] | — | Extra CSS to inject. |
onRenderError | (error) => void | — | Render-error callback. |
errorFallback | (bannerId, error) => ReactNode | — | Per-item error UI. |
SlotPlaceholder (@bildit-platform/nextjs)
| Prop | Type | Required | Notes |
|---|---|---|---|
slotId | string | ✅ | Must match the web slot assigned to the scheduled content in the VEE. |
className | string | — | Class on the slot element. |
fallback / children | ReactNode | — | Default content when no scheduled content is assigned. |
forceFallback | boolean | — | Keep the fallback in place (for admin tooling). |
disableStyleScoping | boolean | — | Disable automatic CSS scoping for this slot. |
Middleware & preview-date helpers (@bildit-platform/nextjs)
enhanceMiddlewareWithBildit(middleware)— wraps your middleware to forward the VEE preview date. Your middleware should also setx-pathnamefromrequest.nextUrl.pathnameso scheduled content can be matched by location.getPreviewDateFromHeaders(headers)— returns the preview date (epoch ms) from the request headers, orundefinedon production traffic.
For the raw HTTP endpoint behind the connector, see Remote API Endpoints.
Troubleshooting: blank on the production site
Work top to bottom — these are ordered by how often they're the culprit:
- Preview / trial key — blocked on production by design. Upgrade or use a production key. (See Preview & free-trial keys.)
- Scheduled content location — the scheduled content must have a Location matching the page path;
/remote-webbanners_v1_4returns an empty set otherwise. (Note: this is stricter than the legacy non-versioned endpoint, which ignored location.) BILDIT_API_URL— must be the VEE Functions base URL; the SDK appends/remote-webbanners_v1_4. Wrong host → no scheduled content.force-dynamicmissing — without it the layout is statically cached and never reads the per-request headers.- Env vars in production — are
BILDIT_API_KEYandBILDIT_API_URLset in your host's environment (not just locally)? Missing in prod → nothing renders. transpilePackagesmissing —@bildit-platform/nextjsmust be listed, or the build errors.cmsDependenciesincomplete — scheduled content importing an unregistered module throws a render error (check the server/browser console).- Response caching — the connector caches responses (~5 min, in-memory per process). After flipping a key or schedule, wait briefly or redeploy.