Guides · 20 min
A storefront with Next.js
This builds a real storefront: a grid of products from the public catalog, each rendered as a live mockup, each linking to checkout. It uses the SDK for ergonomics, but everything underneath is the same img/buy URL you can build by hand.
Install & configure
Add the SDK (and the optional UI components for later). Then set your public Shop ID — it’s safe in a NEXT_PUBLIC_ var.
pnpm add @snowcone-app/sdk @snowcone-app/ui# .env.local — the Shop ID is public, so NEXT_PUBLIC_ is fine.
NEXT_PUBLIC_SNOWCONE_SHOP=YOUR_SHOP_IDList the catalog
The catalog is a public Meilisearch index, so a Server Component can fetch it directly — no SDK required to read it. Cache it; the catalog changes rarely.
// app/page.tsx — a Server Component. Read the catalog at request time.
// The catalog is a public Meilisearch index; the search key is public.
const SEARCH = "https://search.snowcone.app/indexes/snowcone";
const KEY = "eee819b849798ad9091228c486ec05d0931e5292";
async function getProducts() {
const res = await fetch(`${SEARCH}/search`, {
method: "POST",
headers: { Authorization: `Bearer ${KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({ limit: 24 }),
next: { revalidate: 3600 }, // cache the catalog for an hour
});
const { hits } = await res.json();
return hits as { id: string; name: string; price: number }[];
}
export default async function Storefront() {
const products = await getProducts();
return (
<ul className="grid grid-cols-3 gap-6">
{products.map((p) => (
<ProductCard key={p.id} product={p} />
))}
</ul>
);
}q, filters, or facets to the body and you have search and category pages for free. See the catalog reference.Render & sell each product
For each product, getMockupUrl builds the image URL and the buy link is the same values with img → buy. In a real app, SAMPLE_ART is whatever artwork your shopper picked or uploaded.
import { getMockupUrl } from "@snowcone-app/sdk";
const SHOP = process.env.NEXT_PUBLIC_SNOWCONE_SHOP!;
const SAMPLE_ART = "https://cdn.example.com/art.png"; // your shopper's artwork
function ProductCard({ product }: { product: { id: string; name: string; price: number } }) {
const mockup = getMockupUrl(product.id, { shop: SHOP, asset: SAMPLE_ART, width: 800 });
const buy = `https://buy.snowcone.app/${product.id}?asset=${encodeURIComponent(SAMPLE_ART)}&shop=${SHOP}`;
return (
<li>
<a href={buy} className="block">
<div className="aspect-square overflow-hidden rounded-xl">
{/* eslint-disable-next-line @next/next/no-img-element */}
<img src={mockup} alt={product.name} className="h-full w-full object-cover" />
</div>
<p className="mt-2 font-medium">
{product.name} — ${(product.price / 100).toFixed(2)}
</p>
</a>
</li>
);
}Optional: the React layer
If you’d rather not wire URLs by hand, the @snowcone-app/ui components wrap the exact same calls. Drop a <Shop> provider at the top and compose.
// Prefer components? The same storefront with the optional React layer.
import { Shop, Product, ProductImage, ProductPrice, AddToCart } from "@snowcone-app/ui";
export default function Card({ id }: { id: string }) {
return (
<Shop>
<Product productId={id}>
<ProductImage artwork="https://cdn.example.com/art.png" />
<ProductPrice />
<AddToCart />
</Product>
</Shop>
);
}Run the full example
A complete working storefront — this guide, assembled — lives in the examples/next-ecommerce directory of the Snowcone monorepo. It uses pnpm; from the repo root:
Install workspace dependencies (run once, from the repo root).
Start the storefront in development mode.
The React layer is styled by your app’s Tailwind v4 build — import ui’s stylesheet, add an @source for your own code, and transpile the package:
/* app/globals.css — your Tailwind v4 entry compiles ui's styles.
* ui's stylesheet brings in Tailwind, the theme tokens, and an @source
* for the package's own components; add an @source for your code. */
@import "@snowcone-app/ui/styles/globals.css";
@source "../app/**/*.{js,ts,jsx,tsx}";
/* next.config.ts also needs: transpilePackages: ['@snowcone-app/ui']
* For dark mode, toggle the "dark" class on an ancestor (e.g. <html>). */You now have a storefront that lists, renders, and sells. To go further: add size & color options, let shoppers design their own art with the Canvas editor, or take payment yourself with the Orders API.

