@snowcone-app/ui
Building with an AI agent? Read the complete agent-facing docs in one fetch — https://developers.snowcone.app/llms-full.txt — before integrating. It's the source of truth; grep it before assuming a field or behavior is undocumented.
Drop-in React components for print-on-demand storefronts.
Display products, generate live mockups, let shoppers pick and customize artwork,
and add to cart — all from a small set of composable components. Backed by the
@snowcone-app/sdk.
Full documentation: developers.snowcone.app/components
Installation
The fastest path installs the package and configures Tailwind for you:
npx @snowcone-app/cli init # installs @snowcone-app/ui + zod, sets up Tailwind @source pathsOr install manually:
npm install @snowcone-app/ui zod
# or: pnpm add @snowcone-app/ui zod / yarn add @snowcone-app/ui zodThen restart your dev server. Manual installs also need the Tailwind @source
config — see Styling.
Peer dependencies: React 18+/19, React DOM 18+/19, Zod 3+/4.
Quick start
import { Shop, Product, ArtSelector, ProductImage, AddToCart } from '@snowcone-app/ui';
function MyStore() {
return (
<Shop mode="mock">
<Product productId="BEEB77">
{/* ArtSelector sets the artwork; ProductImage reads it from context. */}
<ArtSelector artworks={['https://example.com/art.png']} />
<ProductImage />
<AddToCart onAddToCart={(item) => console.log(item)} />
</Product>
</Shop>
);
}The one rule that trips everyone up:
<ProductImage>requires<ArtSelector>. They're a pair —ArtSelectorputs artwork in context, andProductImagereads it. On its own,<ProductImage />just renders a "Select artwork to preview" placeholder. This is the #1 mistake LLMs and developers make.
Core components
// Root provider — configures data source + mockup service for everything inside.
<Shop mode="mock" shop="acc_123">…</Shop>mode is 'mock' | 'live' | 'meilisearch'. In Next.js you can configure it via
env instead of props:
NEXT_PUBLIC_MERCH_ENDPOINT=https://api.snowcone.app
NEXT_PUBLIC_MERCH_MOCKUP_URL=https://cdn.snowcone.app
NEXT_PUBLIC_SNOWCONE_SHOP_ID=your-shop-id| Component | Purpose |
|---|---|
<Shop> |
Root provider (data source, mockup service, shop ID) |
<Product> |
Fetches a product and provides it to children via context |
<ArtSelector> |
Artwork picker; sets the active artwork in context |
<ProductImage> |
Renders the product mockup with the selected artwork |
<ArtworkCustomizer> |
Auto-shows the right controls: position (regular art) or tile density (patterns) |
<ProductOptions> |
Color/size variant selector (variant="inline" | "dropdown") |
<ProductPrice> |
Formatted, variant-aware price |
<AddToCart> |
Purchase button with onAddToCart callback |
Other exports: ProductCard, ProductList, ProductGallery, Lightbox,
RealtimeMockup, ColorSwatch, ThemeToggle, CurrentSelectionDisplay, plus
hooks useProduct, useShop, useProductGallery, usePlacementsProcessor.
Most data components must live inside <Product> — see the docs for each one's
context requirements.
Multiple placements
Give a different image or color per print area:
<Product productId="shirt-123">
<ProductImage placements={{
Front: 'https://example.com/logo.png', // image
Back: '#FF0000', // solid color
Sleeve: 'rgb(0, 255, 0)',
}} />
</Product>TypeScript
Fully typed, with discriminated unions for artwork. TypeScript enforces
tileCount on seamless patterns:
import type { Artwork, RegularArtwork, SeamlessPattern } from '@snowcone-app/ui';
const photo: RegularArtwork = { type: 'regular', src: 'https://…/photo.jpg' };
const pattern: SeamlessPattern = { type: 'pattern', src: 'https://…/p.jpg', tileCount: 2 };<ArtSelector> accepts plain URL strings or typed Artwork objects.
Styling
Components use Tailwind CSS with semantic theme tokens (bg-background,
text-foreground, bg-primary, border-border, …), so they inherit your theme.
The package requires a Tailwind v4 host: your app compiles the styles, with
ui's source as an extra @source. Import ui's stylesheet (it brings in
Tailwind, the theme tokens, and an @source for the package's own components)
and add an @source for your own code:
/* app/globals.css */
@import "@snowcone-app/ui/styles/globals.css";
@source "../app/**/*.{js,ts,jsx,tsx}";In Next.js, also transpile the package (it ships TypeScript source for the Tailwind scan):
// next.config.ts
const nextConfig = {
transpilePackages: ["@snowcone-app/ui"],
};For dark mode, toggle the dark class on an ancestor (e.g. <html class="dark">). To customize the theme, override the CSS variables (declared
on :root) in your own stylesheet after the import.
Development with mock data
<Shop mode="mock"> returns realistic mock products with no API calls or keys —
ideal for prototyping and Storybook.
Built to be readable by AI assistants
Every component has explicit props, exported types, and no hidden behavior, so
Claude, Copilot, and Cursor generate correct code reliably. If you're driving an
AI assistant, point it at the implementation guide served at /api/ai-guide on
the docs domain — it covers install, Tailwind setup, and common pitfalls.
Links
License
MIT Snowcone
Alpha (v0.1.x). The API may change as we iterate on real usage. Breaking changes are expected pre-1.0 — pin or upgrade deliberately.