Getting started
Install the React package and connect a host site to a Lockerverse widget.
Install catalog or signup
pnpm add @lockerverse/react react react-dom
Use narrow entry points to keep Stripe out of catalog-only pages.
Install payment
pnpm add @lockerverse/react @stripe/react-stripe-js @stripe/stripe-js react react-dom
The Stripe packages are optional peers. Install them when you use payment UI.
Load a catalog
import { useLockerverseWidget } from "@lockerverse/react/widget";
const widget = {
communitySlug: "your-community",
widgetSlug: "your-widget",
};
export function Catalog() {
const { catalog, error, loading } = useLockerverseWidget(widget);
if (loading) {
return <p>Loading products…</p>;
}
if (error) {
return <p>{error.message}</p>;
}
if (!catalog) {
return null;
}
return catalog.products.map((product) => (
<button key={product.id} type="button">
{product.name}
</button>
));
}Render payment
import {
LockerversePayment,
type LockerversePaymentCompletion,
} from "@lockerverse/react/payment";
import "@lockerverse/react/payment.css";
import { useLockerverseWidget } from "@lockerverse/react/widget";
const handlePaymentComplete = (result: LockerversePaymentCompletion) => {
const query = new URLSearchParams({ checkout: result.checkoutId });
if (result.email) {
query.set("email", result.email);
}
if (result.lineItems) {
const itemCount = result.lineItems.reduce(
(total, item) => total + item.quantity,
0
);
query.set("items", String(itemCount));
}
window.location.assign(`/complete?${query}`);
};
export function Checkout() {
const widget = useLockerverseWidget({
communitySlug: "your-community",
widgetSlug: "your-widget",
});
return (
<LockerversePayment
onPaymentComplete={handlePaymentComplete}
selection={[
{ productSlug: "ticket", quantity: 2 },
{ amountCents: 2500, productSlug: "donation" },
]}
widget={widget}
/>
);
}DEV configuration
Production is the default. DEV requires both values:
const development = {
apiBaseUrl: "https://portal-dev.lockerverse.com/api",
environment: "development" as const,
};
The SDK uses public widget identifiers. Do not add private API keys.