npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@spree/next

v0.6.4

Published

Next.js integration for Spree Commerce — server actions, caching, and cookie-based auth

Readme

@spree/next

Next.js integration for Spree Commerce — server actions, caching, and cookie-based auth.

Installation

npm install @spree/next @spree/sdk
# or
yarn add @spree/next @spree/sdk
# or
pnpm add @spree/next @spree/sdk

Quick Start

1. Set environment variables

SPREE_API_URL=https://api.mystore.com
SPREE_API_KEY=your-publishable-api-key

The client auto-initializes from these env vars. Alternatively, initialize explicitly:

// lib/storefront.ts
import { initSpreeNext } from '@spree/next';

initSpreeNext({
  baseUrl: process.env.SPREE_API_URL!,
  apiKey: process.env.SPREE_API_KEY!,
});

2. Fetch data in Server Components

import { listProducts, getProduct, listTaxons } from '@spree/next';

export default async function ProductsPage() {
  const products = await listProducts({ per_page: 12 });
  const categories = await listTaxons({ depth_eq: 1 });

  return (
    <div>
      {products.data.map((product) => (
        <div key={product.id}>{product.name}</div>
      ))}
    </div>
  );
}

3. Use server actions for mutations

import { addItem, removeItem, getCart } from '@spree/next';

export default async function CartPage() {
  const cart = await getCart();

  async function handleAddItem(formData: FormData) {
    'use server';
    await addItem(formData.get('variantId') as string, 1);
  }

  return <form action={handleAddItem}>...</form>;
}

Configuration

import { initSpreeNext } from '@spree/next';

initSpreeNext({
  baseUrl: 'https://api.mystore.com',
  apiKey: 'your-publishable-api-key',
  cartCookieName: '_spree_cart_token',     // default
  accessTokenCookieName: '_spree_jwt',     // default
  defaultLocale: 'en',
  defaultCurrency: 'USD',
});

Data Functions

Plain async functions for reading data in Server Components. Wrap with "use cache" in your app for caching.

Products

import { listProducts, getProduct, getProductFilters } from '@spree/next';

const products = await listProducts({ per_page: 25, includes: 'variants,images' });
const product = await getProduct('spree-tote');
const filters = await getProductFilters({ taxon_id: 'txn_123' });

Categories

import { listTaxons, getTaxon, listTaxonProducts } from '@spree/next';
import { listTaxonomies, getTaxonomy } from '@spree/next';

const taxons = await listTaxons({ depth_eq: 1 });
const taxon = await getTaxon('categories/clothing');
const products = await listTaxonProducts('categories/clothing', { per_page: 12 });

const taxonomies = await listTaxonomies({ includes: 'taxons' });
const taxonomy = await getTaxonomy('tax_123');

Store & Geography

import { getStore, listCountries, getCountry } from '@spree/next';

const store = await getStore();
const countries = await listCountries();
const usa = await getCountry('US');

Server Actions

Server actions handle mutations and auth-dependent reads. They automatically manage cookies for cart tokens and JWT authentication.

Cart

import { getCart, getOrCreateCart, addItem, updateItem, removeItem, clearCart } from '@spree/next';

const cart = await getCart();
const cart = await getOrCreateCart();
await addItem(variantId, quantity, { gift_message: 'Happy Birthday!' });
await updateItem(lineItemId, { quantity: 3 });
await updateItem(lineItemId, { metadata: { engraving: 'J.D.' } });
await removeItem(lineItemId);
await clearCart();

Checkout

import {
  getCheckout,
  updateAddresses,
  advance,
  next,
  getShipments,
  selectShippingRate,
  applyCoupon,
  removeCoupon,
  complete,
} from '@spree/next';

const checkout = await getCheckout();
await updateAddresses({ ship_address: { ... }, bill_address: { ... } });
await advance();
await next();
const shipments = await getShipments();
await selectShippingRate(shipmentId, rateId);
await applyCoupon('SAVE20');
await removeCoupon(promoId);
await complete();

Authentication

import { login, register, logout, getCustomer, updateCustomer } from '@spree/next';

await login(email, password);
await register({ email, password, password_confirmation, first_name, last_name });
await logout();
const customer = await getCustomer();
await updateCustomer({ first_name: 'John' });

Addresses

import { listAddresses, getAddress, createAddress, updateAddress, deleteAddress } from '@spree/next';

const addresses = await listAddresses();
const address = await getAddress(addressId);
await createAddress({ firstname: 'John', address1: '123 Main St', ... });
await updateAddress(addressId, { city: 'Brooklyn' });
await deleteAddress(addressId);

Orders

import { listOrders, getOrder } from '@spree/next';

const orders = await listOrders();
const order = await getOrder(orderId);

Payment Sessions

import {
  createPaymentSession,
  getPaymentSession,
  updatePaymentSession,
  completePaymentSession,
} from '@spree/next';

// Create a payment session (initializes provider-specific session)
const session = await createPaymentSession(orderId, { payment_method_id: 'pm_123' });

// Access provider data (e.g., Stripe client secret)
const clientSecret = session.external_data.client_secret;

// Get a payment session
const session = await getPaymentSession(orderId, sessionId);

// Update a payment session
await updatePaymentSession(orderId, sessionId, { amount: '50.00' });

// Complete a payment session (confirms payment with provider)
await completePaymentSession(orderId, sessionId, { session_result: 'success' });

Credit Cards & Gift Cards

import { listCreditCards, deleteCreditCard } from '@spree/next';
import { listGiftCards, getGiftCard } from '@spree/next';

const cards = await listCreditCards();
await deleteCreditCard(cardId);

const giftCards = await listGiftCards();
const giftCard = await getGiftCard(giftCardId);

Localization

Automatic (recommended)

Data functions automatically read locale and country from cookies. Use the included middleware to handle URL-based routing and cookie persistence:

// middleware.ts
import { createSpreeMiddleware } from '@spree/next/middleware';

export default createSpreeMiddleware({
  defaultCountry: 'us',
  defaultLocale: 'en',
});

export const config = {
  matcher: ['/((?!_next/static|_next/image|favicon.ico|.*\\..*$).*)'],
};

Data functions work without any locale arguments:

const products = await listProducts({ per_page: 10 });
const taxon = await getTaxon('categories/clothing');

Use the setLocale server action in country/language switchers:

import { setLocale } from '@spree/next';

await setLocale({ country: 'de', locale: 'de' });

Manual override

You can still pass locale options explicitly — they override auto-detected values:

const products = await listProducts({ per_page: 10 }, { locale: 'fr', country: 'FR' });

TypeScript

All types are re-exported from @spree/sdk for convenience:

import type {
  StoreProduct,
  StoreOrder,
  StoreLineItem,
  StorePaymentSession,
  StoreTaxon,
  PaginatedResponse,
  SpreeError,
} from '@spree/next';

Development

cd packages/next
pnpm install
pnpm dev         # Build in watch mode
pnpm typecheck   # Type-check
pnpm test        # Run tests
pnpm build       # Production build

Releasing

This package uses Changesets for version management.

npx changeset           # Add a changeset after making changes
npx changeset version   # Bump version and update CHANGELOG
pnpm release            # Build and publish to npm

License

MIT