Auctions
Browse auction items, submit bids, and buy items with optional React components.
Use the auction example to browse live data and view the complete source.
Shared Lockerverse interface
The optional auction UI follows the public Lockerverse web app: image cards and status filters, a photo gallery with a full-screen viewer, item details, and a two-step bid or purchase checkout. It uses the community color by default. Override the shared theme variables with style when the host site needs different branding.
The item layout responds to its container width, so the same component can fill a page or sit inside a narrow embed. The SDK supplies its own scoped CSS and does not require Next.js or Tailwind. Dates follow the public app’s America/New_York display policy and honor each auction’s time-display settings.
For public item pages, pass backHref to LockerverseAuctionItem so its return controls are real links. Add onBack to connect ordinary clicks to the host router or item selection; modified clicks keep native browser behavior. onBack without backHref keeps the existing button controls. Pass communityName only when the host needs to override the API community name. Keep the catalog mounted but hidden while showing an item to preserve the selected auction and filter. The example demonstrates this pattern.
On a dedicated public item page, pass itemHeadingLevel={1} and use a non-heading label for the shared auction title so the item name is the page’s main heading. The default is level 2 for embedded details. The bid, purchase, and item-status headings use the next level: H2 under an item H1, or H3 under the default item H2. This changes heading semantics without changing its visual style.
The inline gallery gives the first photo high fetch priority, loads the selected photo eagerly, and loads other photos lazily. Lazy photos use their rendered width when the browser supports automatic image sizing. Set galleryImageSizes to a responsive HTML sizes value that matches your page container when its layout differs from the default full-width mobile and 45vw desktop layout. This also sizes the first photo correctly before hydration. Full-screen photos keep their separate viewport sizes.
Pass returnToItemHref to add a Return to item link after a completed bid or purchase. It opens the item URL as a fresh page visit. When backHref or onBack is also supplied, View auction items remains as the secondary action. The completed result uses backHref as a fresh page visit when it is set. The link does not reset or resume checkout in the mounted component. Hosts that restore purchase recovery must clear completed recovery before a new page visit.
The item component loads its checkout code only after the visitor continues to payment, or when it resumes an existing purchase. Item details still render on the server. Keep the emitted dynamic JavaScript chunks available in your deployment; no host-side lazy wrapper is required. If that code cannot load, visitors who have not submitted a purchase can return to the item or choose to reload the page. For an existing purchase recovery, the component keeps the lock and directs the visitor to the auction organizer; it never reloads automatically or clears recovery.
For internal adoption, import these same SDK components and stylesheet. Keep routing, page metadata, and the site header in the app. Change auction presentation in the SDK rather than copying its markup or styles into a second implementation. The host owns route URLs, metadata, and page chrome; the SDK owns the shared auction presentation.
Choose your UI
@lockerverse/sdk/auctions: framework-independent clients, validated data, pricing estimates, bids, purchases, and status lookup.@lockerverse/react/auctions:useLockerverseAuctionsand the optionalLockerverseAuctionscatalog. This entry does not import Stripe.@lockerverse/react/auction-data: the React data hook only, with no UI, icons, or Stripe.@lockerverse/react/auction: one loaded auction and its item cards, without the community auction list or checkout.@lockerverse/react/auction-item: optionalLockerverseAuctionItemdetail and card checkout.@lockerverse/react/auction.css: catalog and single-auction styles only.@lockerverse/react/auction-item.css: item details, gallery, and checkout styles only.@lockerverse/react/auctions.css: all auction styles, retained for existing integrations.
import { LockerverseAuctions, useLockerverseAuctions } from "@lockerverse/react/auctions";
import { LockerverseAuctionItem } from "@lockerverse/react/auction-item";
import "@lockerverse/react/auctions.css";
const auctions = useLockerverseAuctions({ communitySlug: "auburn" });
// In your component, keep the selected auction and item in application state.
<LockerverseAuctions
auctions={auctions}
onSelectItem={(auction, item) => setSelection({ auction, itemId: item.id })}
theme="light"
/>;
// Render only when selection exists. Remount when its resource identity changes.
<LockerverseAuctionItem
key={`${selection.auction.id}:${selection.itemId}`}
auction={selection.auction}
client={auctions.client}
itemId={selection.itemId}
onBidSubmitted={handleBidSubmitted}
onPurchaseComplete={handlePurchaseComplete}
theme="light"
/>;
Install the same optional Stripe peers as the payment component:
npm install @lockerverse/react react react-dom @stripe/react-stripe-js @stripe/stripe-js
Production is the default. For development, explicitly pass environment: "development" and the development apiBaseUrl.
Serve auction images through your site
Set mediaBaseUrl to an absolute HTTPS URL when your host has a fixed server rewrite to https://media.lockerverse.com. For example, configure /lockerverse-media/:path* on your host to forward to https://media.lockerverse.com/:path*, then pass:
const auctions = useLockerverseAuctions({
communitySlug: "wsu",
mediaBaseUrl: "https://your-site.example/lockerverse-media",
});
This option also works with useLockerverseAuction and createLockerverseAuctionClient. It changes Lockerverse auction, community, and item image URLs on every list, load, and refresh. Other image hosts keep their original URLs. Without this option, all image URLs stay unchanged. The host must configure the rewrite before using the option; the SDK does not create it.
The returned auction retains mediaBaseUrl. Pass the full auction snapshot to the React components, including when you serialize server-loaded data as initialAuction. Auction cards, item photos, thumbnails, and the full-screen gallery use the existing responsive WebP sizes through that exact proxy origin and path. The proxy must forward the w and f query parameters unchanged. Images outside that path, signed URLs, and unsupported formats keep their original URLs; a failed resized image falls back to its original URL.
A page for one auction
Use LockerverseAuction when the host already knows which auction to show. It goes straight to that auction’s items, without an intermediate auction-list card. Use useLockerverseAuction(options, auctionSlug) from @lockerverse/react/auction-data for a dedicated page. It calls client.load(auctionSlug) directly and never requests the community auction list. The host handles initial loading, errors, and missing auctions before rendering this component.
import { LockerverseAuction } from "@lockerverse/react/auction";
import "@lockerverse/react/auction.css";
// auction is a validated, loaded Lockerverse auction.
<LockerverseAuction
auction={auction}
onSelectItem={(auction, item) => openItem(auction, item.id)}
showFilters={false}
showHeader={false}
showLineup={false}
theme="light"
/>;
showFilters and showHeader default to true. showLineup defaults to false, so the static introduction and separate count are hidden. These options also work on LockerverseAuctions. The auction header omits the auction date range; item dates remain on item cards. Hiding filters shows all items and clears the previous filter. Changing the auction resets its filter. Hiding headings never removes the section’s accessible name. onBack is optional, so a dedicated auction page does not need a link to all auctions.
Direct loading and refresh
import { useLockerverseAuction } from "@lockerverse/react/auction-data";
const resource = useLockerverseAuction(
{ communitySlug: "lckrvrs-internal" },
"auction"
);
The result contains client, auction, loading, error, and refresh(). Without an initial seed, initial loading has no auction. Refresh keeps the last successful snapshot, including when the request fails. Show a refresh error beside the existing UI. Show a retry button only when loading fails; do not add a manual refresh button to the normal auction view. Community, auction slug, environment, API base URL, and media base URL are immutable: use a new React key when the resource identity changes.
Both data hooks refresh by default after the document changes from hidden to visible. They do not poll, refresh on mount twice, or reload the page. Disable this policy when the host supplies its own refresh:
useLockerverseAuction(options, "auction", { refreshOnReturn: false });
useLockerverseAuctions(options, { refreshOnReturn: false });
The React-only AuctionRefreshOptions type is exported from auction-data and auctions. Both hooks retain their last successful data during a refresh or failure. Return events during an in-flight read coalesce into at most one later read while visible. Manual refresh still works; older responses cannot replace newer data. Return refresh updates display data, never a bid or payment result. Checkout still reviews server pricing before submission. Use the local State Lab response controls to stage prices, stock, missing items, errors, or independently paused reads. No real bid or charge occurs there.
Try the complete single-auction example. Its copyable source is self-contained. Community, auction, and item links use native document navigation with community, auction, and item query parameters; existing host parameters are preserved. Direct item links support reload, Back/Forward, new tabs, item-not-found handling, and return to the loaded auction. The community/auction form clears the old item selection. It reads the link before mounting a data hook, so the first request is the auction detail request. An empty auction slug selects the separate all-auctions example.
LockerverseAuctionItem accepts fresh same-ID data while selecting an item. Once payment is open, it preserves the transaction snapshot until the user returns to selection. Checkout’s own server review takes precedence over an older host snapshot. Keep a selected item mounted during refresh, errors, and item disappearance while a submission or recovery is locked; a loading or not-found branch must never discard it.
For Lovable, start with the built-in styled UI and supported public configuration. Do not automatically switch to headless based on inferred design needs. Use the headless SDK only when a custom implementation is explicitly requested.
Initial server data
Pass a complete SDK snapshot to the React hook when a server route has already
loaded it. The plural hook accepts initialAuctions in its second argument;
the singular hook accepts initialAuction in its third argument.
import type { LockerverseAuction } from "@lockerverse/sdk/auctions";
import {
useLockerverseAuction,
useLockerverseAuctions,
} from "@lockerverse/react/auction-data";
function useServerAuctions(
communitySlug: string,
initialAuctions: LockerverseAuction[]
) {
return useLockerverseAuctions(
{ communitySlug },
{ initialAuctions }
);
}
function useServerAuction(
communitySlug: string,
auctionSlug: string,
initialAuction: LockerverseAuction
) {
return useLockerverseAuction(
{ communitySlug },
auctionSlug,
{ initialAuction }
);
}
The seed is read once on mount. An empty initialAuctions: [] is valid data.
The seed must belong to the requested community; a singular seed with a
different auction slug throws a TypeError. Later seed prop changes do not
replace live data. The hook does not mutate the supplied snapshot.
The first browser request still runs, and loading remains true while it is
pending. Render available data during loading; show an initial skeleton only
when data is null. A failed refresh retains the seed or last successful data.
Keep checkout mounted during refresh and errors. refreshOnReturn remains
available in the same argument. The named UseLockerverseAuctionOptions and
UseLockerverseAuctionsOptions types are exported from auction-data; the
plural options type is also exported from auctions.
Keep the default cards, change selected parts
The built-in card supports showDescription, showMetrics, and showTiming (all default to true), plus className and style. Use renderItem to change these without copying card markup:
import {
LockerverseAuction,
LockerverseAuctionItemCard,
} from "@lockerverse/react/auction";
<LockerverseAuction
auction={auction}
onSelectItem={openItem}
renderItem={(context) => (
<LockerverseAuctionItemCard
{...context}
showDescription={false}
showTiming={false}
/>
)}
/>;
The card also works by itself in a host-owned list:
<LockerverseAuctionItemCard
auction={auction}
item={item}
onSelect={() => openItem(auction, item.id)}
theme="light"
showDescription={false}
/>;
It supplies a lightweight theme scope. Its className and style apply to that outer scope. Import @lockerverse/react/auction.css once for the host list.
Or return your own card. The renderer receives auction, item, the effective status, onSelect, theme, and inherited theme variables in style. Spread this context onto the default card to retain branding. It renders inside an SDK-owned list item; do not return another <li>. Keep a keyboard-accessible button or link connected to the supplied action. Render hooks inside a custom React component, not directly inside the render callback. Returning null intentionally renders no card.
A custom card can still open LockerverseAuctionItem for the built-in item, closed-state, bid, checkout, and recovery flows. Presentation options do not bypass availability or payment rules. Keep uncertainty and recovery information visible. Fully custom flows can continue to use the unchanged headless SDK.
Host styling and layout
Auction components have a transparent outer background and no outer padding or maximum width. Put page padding and width limits on your host container. Card, form, and receipt surfaces still use the shared theme variables.
Font family, font size, and date styling are configurable defaults. They are not
fixed branding rules. Pass variables through style or set them on the component
with a host stylesheet loaded after the SDK stylesheet:
<LockerverseAuction
auction={auction}
getItemHref={(auction, item) => `/auctions/${auction.path}/items/${item.path}`}
style={{
"--lockerverse-font-family": "var(--site-font, system-ui)",
"--lockerverse-font-size": "16px",
"--lockerverse-auction-title-size": "32px",
"--lockerverse-auction-card-title-size": "22px",
"--lockerverse-auction-date-size": "13px",
"--lockerverse-auction-date-transform": "none",
"--lockerverse-auction-date-letter-spacing": "normal",
}}
/>
The item title uses --lockerverse-auction-item-title-size; the result title uses
--lockerverse-auction-result-title-size. The receipt item title uses
--lockerverse-auction-result-receipt-title-size, with the general subheading size as a fallback.
General headings use
--lockerverse-auction-heading-size and --lockerverse-auction-subheading-size.
Existing color, border, radius, and font-family variables remain available.
Catalog photos are static by default. Set autoRotateImages on the catalog or
card to opt into rotation. Reduced-motion, focus, and hover behavior still apply.
Descriptions keep a short card preview; use showDescription={false} to hide it.
The full description remains available on the item page.
Host routes and filters
Use getItemHref for real item links. It preserves open-in-new-tab and ordinary
browser navigation. A host router can also handle unmodified clicks with
onSelectItem; modified clicks still follow the link.
Use filter, onFilterChange, and getFilterHref to keep the selected filter in
the URL. Omitting these props keeps the internal filter behavior. The exported
LockerverseAuctionItemFilter type is all | active | draft | finished.
For the community auction list, getAuctionHref supplies auction links and
onSelectAuction can connect an application router. Hiding filters still shows
all items. The host must keep controlled values in sync with its URL.
Public pages and search engines
For a public auction website, use getItemHref on the catalog and backHref on
item pages. Each URL must open the correct content on a direct visit, without
prior browser state. Use getAuctionHref when the site has a community auction
list. LockerverseAuction also accepts backHref for its Auctions control.
LockerverseAuctions passes backHref and itemOrder to its selected catalog.
Checkout controls that return to an earlier payment step stay buttons. Return
links in the item view stay hidden while checkout has an interaction lock.
Set itemOrder="availability" to show live items, then upcoming items, then
closed items. This uses the effective auction and item status, including elapsed
closing dates. Configured position and creation time still set the order within
each group. The default, itemOrder="position", keeps the configured item order.
Fetch public data on the server with createLockerverseAuctionClient().load().
Pass the complete result as initialAuction to useLockerverseAuction. Render
the available auction during refresh; do not replace server content with a
loading screen. The following Next.js example serves a catalog at /auctions:
// app/auctions/page.tsx — server component
import { createLockerverseAuctionClient } from "@lockerverse/sdk/auctions";
import { AuctionCatalog } from "./AuctionCatalog";
export const dynamic = "force-dynamic";
export default async function AuctionsPage() {
const initialAuction = await createLockerverseAuctionClient({
communitySlug: "your-community",
}).load("your-auction");
return <AuctionCatalog initialAuction={initialAuction} />;
}
// app/auctions/AuctionCatalog.tsx — rendered on the server, then hydrated
"use client";
import type { LockerverseAuction as Auction } from "@lockerverse/sdk/auctions";
import { LockerverseAuction } from "@lockerverse/react/auction";
import { useLockerverseAuction } from "@lockerverse/react/auction-data";
import "@lockerverse/react/auction.css";
export function AuctionCatalog({ initialAuction }: { initialAuction: Auction }) {
const { auction, error } = useLockerverseAuction(
{ communitySlug: "your-community" },
initialAuction.slug,
{ initialAuction }
);
return (
<>
<h1>Auctions and experiences</h1>
{error ? <p role="status">Auction updates are temporarily unavailable.</p> : null}
<LockerverseAuction
auction={auction ?? initialAuction}
getItemHref={(_, item) => `/auctions/items/${encodeURIComponent(item.slug)}`}
itemOrder="availability"
showHeader={false}
/>
</>
);
}
Create the matching item route with server data too. Resolve the item from the
auction before its first render, then pass backHref="/auctions" and its own
returnToItemHref to LockerverseAuctionItem. Keep the mounted item during
refresh and payment, as described in Initial server data. Use a real 404
response for unknown items. Do not include unlisted preview items in public
catalogs or sitemaps.
The host website owns document metadata and HTTP routes. For every public auction
and item route, the host must provide a unique title and description, an absolute
canonical URL, and server-rendered content. Publish /sitemap.xml with the public
canonical URLs, reference it from /robots.txt, and submit it in Search Console.
The SDK cannot select the host’s domain, router, indexing policy, or page title.
Use verified organization and breadcrumb data for structured data. Add product
and offer data only when it matches the visible item and sale terms; a current
bid is not a fixed purchase price.
Shared results
The item component shows the shared result after a confirmed bid submission or paid purchase. Completion callbacks remain available for host routing and data refresh. The result is also available separately:
import { LockerverseAuctionResult } from "@lockerverse/react/auction-result";
import "@lockerverse/react/auction-result.css";
Use the purchase confirmation only after the server reports a paid purchase. Receipt amounts alone do not establish payment status. A submitted bid is not a winning bid or a payment. Keep unknown and pending transactions mounted until their result is resolved.
Icons and bundle boundaries
Auction UI uses the same Lucide icon definitions as the original Lockerverse app. Each component uses static named imports. There is no dynamic icon-name registry, and text characters are not used as navigation icons.
Import the smallest public entry you need. The core @lockerverse/sdk/auctions entry has no React, icons, or UI styles. The React data hook also has no UI imports. The single-auction view does not import the multi-auction browser or Stripe. Item details do not import the catalog; they include their gallery and checkout dependencies. CSS is opt-in through the matching stylesheet above.
A prop such as showFilters={false} removes the controls at runtime; it is not a promise that a bundler removes all filter code. Use separate entries for bundle isolation, and use a custom card or the headless API for a substantially different interface.
Custom UI
import { createLockerverseAuctionClient } from "@lockerverse/sdk/auctions";
const client = createLockerverseAuctionClient({ communitySlug: "auburn" });
const auctions = await client.list();
const auction = await client.load("auburn-auction");
The auction includes its items, bidding and quantity rules, fee policy, and payment configuration. Read prices and availability from this response. All amounts are integer USD cents. The server validates the final bid and purchase.
The core methods createBid and createPurchase accept a Stripe confirmation token created on the returned payment account. Bid card collection uses Stripe setup mode and off-session use. Buy-now checkout uses payment mode. The ready-made component handles these steps for card payments, including billing and required shipping addresses.
For custom card-only buy-now Elements, set paymentMethodTypes: ["card"] both on Elements and in the createPurchase submission. Omit the submission field for automatic payment methods. Include params.return_url when creating the confirmation token. The ready-made component handles this configuration.
Host navigation and submission locks
Connect onInteractionLockChange(locked) to every host control that can remove or replace checkout: back links, community selection, router navigation, and reset buttons. true covers preparation, a sent operation, and unresolved bid or purchase recovery. The SDK sends the lock before starting submission and releases it when safe; its own back controls follow the same lock.
<LockerverseAuctionItem
auction={auction}
client={client}
itemId={itemId}
onInteractionLockChange={setCheckoutLocked}
onBack={checkoutLocked ? undefined : closeItem}
onUncertain={(kind) => setMessage(`The ${kind} result is unknown. Keep this flow open.`)}
/>
The host owns its router. Disabling the SDK back button alone cannot block an external route change. If checkout is unexpectedly removed after sending, the SDK still reports a known completion or uncertainty once for that operation. It does not start a new Stripe action after removal, and it never automatically retries a bid. Keep callback state above checkout. Full page reload, browser shutdown, or process termination cannot guarantee callback delivery.
If the host combines the lock with recovery and uncertainty flags, update those flags synchronously in a ref before computing the combined lock. Completion can clear recovery and then release the lock in the same turn.
Simulated review
The State Lab includes Auction previews for a live bid, an unknown bid result, and purchase recovery. It uses the actual SDK components with a local synthetic transport and Stripe adapter. No API or Stripe network calls are made. The response control pauses a request for inspection; the unexpected-removal control deliberately bypasses navigation only inside this labelled simulation. A preflight pause verifies that removal before sending creates no bid. Simulation reset discards synthetic state only.
Completion and recovery
onBidSubmitted means the bid request was submitted. It does not mean the bidder won or a payment was made. If a bid result is unknown, keep the uncertainty visible and do not retry the bid automatically: the bid API has no deduplication key.
onPurchaseComplete runs only when Lockerverse reports paid. Pending payments remain in checkout, with a status action that does not create another payment. The core equivalent is:
const purchase = await client.getPurchaseStatus(auctionSlug, itemId, clientRequestId);
A null result means no matching purchase is currently recorded. It does not prove an earlier request has stopped. Retry only the original purchase details with the same clientRequestId.
Keep onPurchaseRecoveryChange records private. They contain customer data and a Stripe token, plus the original payment account, item, and amounts. A host can retain the record and pass it as resumePurchase when remounting the same item and environment. Remove resumePurchase when the callback returns null; remount before starting a new purchase after a resolved recovery. The SDK does not store these records in browser storage automatically.
getPurchaseReceipt returns receipt amounts. Use getPurchaseStatus to establish whether payment succeeded.
Release order
Deploy auction payment configuration and the purchase-status endpoint before publishing this SDK version. Older auction responses can still be browsed; the default checkout requires the new payment configuration.
Availability while a page stays open
Cards, filters, counts and item controls update at the auction’s known start/end boundaries, using one shared timer and a check when the tab becomes visible. There is no network polling for these clock changes. Server draft and finished states remain authoritative. Time changes never discard an active checkout or purchase recovery. Buy-now cards say Preview item before opening, Buy now while available, and View item after closing.
Motion in embedded views
Automatic card rotation and gallery autoplay pause when the component is outside the viewport, hidden by its host, or in a background tab. Existing user pause, reduced-motion, hover, focus and drag behavior still applies. Manual image navigation remains available. A hidden mounted gallery retains its selected image.
The State Lab also includes loading, failed loading, upcoming, live, closed, sold-out and timed start/end examples. Switch among a single auction, standalone card and community browser, open item details, or hide the preview. Its labelled images are local simulation data; the preview sends no auction or Stripe requests.
Auction descriptions render backend-provided rich HTML through React dangerouslySetInnerHTML. The SDK does not sanitize this HTML. Supply trusted or upstream-sanitized descriptions. Plain descriptions retain escaped text and line breaks.
Direct result review
The auction review page can show submitted bids, paid purchases, and unconfirmed receipts without completing checkout. All outcomes are local sample data, rendered by the actual result component. Use Standard SDK to check the default theme or Website style to check the approved host decoration. The photo backdrop, glass badge, and receipt finish belong to the example wrapper, not the SDK defaults. Resize the browser to check mobile layouts.
External host navigation
Use getAuctionHref and getItemHref for native links, or connect the same URLs to the host’s existing router. Give LockerverseAuctionItem a returnToItemHref so a completed result can open the original item again. Its backHref must point to the auction even after direct item entry. An optional onBack can handle ordinary clicks before checkout completes. Do not use history Back as the only return action.
The complete external example retains the mounted item through refresh, errors, and removal from fresh data. Errors and retry stay beside that item. Its pending-only link guard, unload warning, and cancelable Navigation API guard are best effort; forced navigation or browser shutdown can still discard in-memory recovery. The example uses production; use local result review and State Lab for safe completion checks.
Saved auction host integration
Keep the existing framework, router, page structure, and surrounding design.
Mount one integration for the configured auction. Load it directly with
useLockerverseAuction or client.load(auctionPath); never load the community
list and filter it. Keep live item settings authoritative. Preserve draft,
closed, sold-out, shipping, and service-fee behavior. Use the built-in styled
catalog, gallery, checkout, and results. Use supported theme props and tokens;
use headless only when explicitly requested. Do not add a second checkout,
iframe, unrelated Stripe account, or external-site redirect.
Use item slug/path, with stable item ID as fallback, for encoded host URLs.
Never use item names or list positions. Keep the saved auction identity fixed;
route parameters must not select another auction or community. The URL is the
item-selection source. Support direct entry, reload, sharing, Back/Forward,
and unknown-item handling. Preserve unrelated host query parameters. Supply
getItemHref, backHref, and returnToItemHref, and connect ordinary clicks
to the existing router as needed. Do not use history Back as the only return
control or silently select the first item for an unknown URL.
Keep checkout in a stable mounted route boundary. Pending state includes the
SDK interaction lock, unresolved purchase recovery, and an uncertain bid.
Connect it to existing router blockers for item links, site navigation, and
Back/Forward. Use a pending-only beforeunload warning as a best effort, never
as a promise of durable recovery. Keep normal navigation when not pending.
Show refresh errors and retry beside the mounted item. Do not replace checkout
with a loading/error/not-found branch or add a normal manual refresh button.
Pass fresh same-auction data with the last valid snapshot as fallback.
Keep auction recovery private and in memory by default. It contains contact
data and a Stripe token. Do not log or persist it as part of a new integration.
If an existing host already restores recovery, read browser storage in an
effect, never in server rendering. Render public item content initially inert
until that read completes. Remount once with resumePurchase only for a valid
record matching the auction, item, client, and environment. Live recovery
callbacks must not change the item key or remount checkout. When the callback
returns null, clear the stored record and resume prop while keeping the key
stable. Never serialize recovery into loader data, URLs, or metadata.
TanStack Start server routes
On an existing TanStack Start SSR site, put the public SDK load in a GET server function and call it from each file-route loader. A shared loader also runs on client navigation, so do not treat the loader itself as server-only code.
import { createServerFn } from "@tanstack/react-start";
import { createLockerverseAuctionClient } from "@lockerverse/sdk/auctions";
const auctionOptions = { communitySlug: "your-community" };
const auctionPath = "your-auction";
export const getSavedAuction = createServerFn({ method: "GET" }).handler(
() => createLockerverseAuctionClient(auctionOptions).load(auctionPath)
);
// File route: loader: () => getSavedAuction()
// const initialAuction = Route.useLoaderData();
// const resource = useLockerverseAuction(auctionOptions, auctionPath, { initialAuction });
Resolve the item from the same route’s params and loader data. Set head title
from the item and auction names, description from that item’s description or
an item-specific fallback, and og:image from its image when present. Render
resource.auction ?? initialAuction outside ClientOnly; gallery, text, and
status must be in the first response. Stripe initialization stays in the
browser. Include public read data only in loader results.
For static Vite sites, preserve client loading and report that current item-specific first-response metadata needs an SSR response or another static build. Do not add a per-site server solely for this integration. For SSR, verify raw first-response names and metadata, hydration, direct entry, routing, and live refresh. Check desktop and 390 by 844 layouts, unavailable states, quantity and bid validation, gallery, and both result return controls. Use the SDK simulated result preview. Open checkout to inspect saved fees and shipping, but do not submit a live bid or payment.