Skip to content

Quick Start

Hydrogen example

1. Server-side token exchange (loader)

In your root loader or layout loader, exchange the customer’s Shopify session for a wishlist JWT:

// app/root.tsx (Hydrogen/Remix)
export async function loader({ context }: LoaderFunctionArgs) {
const customer = await context.customerAccount.query(CUSTOMER_QUERY);
let wishlistToken: string | undefined;
if (customer?.id) {
// Extract numeric ID from Shopify GID
const customerId = customer.id.split("/").pop()!;
const res = await fetch(`${process.env.PUBLIC_WISHLIST_API}/auth/token`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
api_key: process.env.WISHLIST_API_KEY,
api_secret: process.env.WISHLIST_API_SECRET,
customer_id: customerId,
}),
});
if (res.ok) {
const data = await res.json();
wishlistToken = data.data.token;
}
}
return { wishlistToken };
}

2. Add the Provider (root layout)

app/root.tsx
import { WishlistProvider } from "@simplersuite/wishlist-react";
export default function App() {
const { wishlistToken } = useLoaderData<typeof loader>();
return (
<html>
<body>
<WishlistProvider
apiBase={import.meta.env.PUBLIC_WISHLIST_API}
storefrontKey={import.meta.env.PUBLIC_WISHLIST_STOREFRONT_KEY}
customerToken={wishlistToken}
>
<Outlet />
</WishlistProvider>
</body>
</html>
);
}

3. Add a wishlist button to products

app/components/ProductCard.tsx
import { WishlistButton } from "@simplersuite/wishlist-react";
export function ProductCard({ product }) {
return (
<div>
<img src={product.image.url} alt={product.title} />
<h3>{product.title}</h3>
<span>{product.price}</span>
<WishlistButton productId={product.id.split("/").pop()!} />
</div>
);
}

4. Add a wishlist page

app/routes/wishlist.tsx
import { useWishlist, WishlistGrid } from "@simplersuite/wishlist-react";
export default function WishlistPage() {
const { loading, count } = useWishlist();
return (
<div>
<h1>My Wishlist ({count})</h1>
<WishlistGrid
columns={3}
renderItem={(item) => <ProductCard productId={item.productId} />}
emptyState={<p>Your wishlist is empty.</p>}
/>
</div>
);
}

Next.js example

The setup is similar — exchange the token in a Server Component or API route, then pass it to the client-side Provider:

// app/layout.tsx (Server Component)
import { WishlistProviderWrapper } from "./wishlist-provider";
export default async function RootLayout({ children }) {
const session = await getSession(); // your auth
let wishlistToken: string | undefined;
if (session?.customerId) {
const res = await fetch(`${process.env.PUBLIC_WISHLIST_API}/auth/token`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
api_key: process.env.WISHLIST_API_KEY,
api_secret: process.env.WISHLIST_API_SECRET,
customer_id: session.customerId,
}),
});
if (res.ok) {
const data = await res.json();
wishlistToken = data.data.token;
}
}
return (
<html>
<body>
<WishlistProviderWrapper token={wishlistToken}>
{children}
</WishlistProviderWrapper>
</body>
</html>
);
}
// app/wishlist-provider.tsx ("use client")
"use client";
import { WishlistProvider } from "@simplersuite/wishlist-react";
export function WishlistProviderWrapper({ token, children }) {
return (
<WishlistProvider
apiBase={process.env.NEXT_PUBLIC_WISHLIST_API!}
storefrontKey={process.env.NEXT_PUBLIC_WISHLIST_STOREFRONT_KEY!}
customerToken={token}
>
{children}
</WishlistProvider>
);
}