Why Composable Commerce
Traditional e-commerce platforms lock you into their ecosystem. Every feature you need must exist within their walled garden. Customization means working around platform limitations. Scaling means accepting their architectural decisions.
Composable commerce flips this model. Instead of a single platform, you assemble best-of-breed services. Content management, payments, search, shipping, and analytics become independent components that communicate through APIs. You control the composition.
The Modern Stack
Sanity CMS: Structured content that adapts to any channel. Products, collections, pages, and promotional content managed in one place, delivered everywhere. Real-time collaboration and powerful querying through GROQ. Stripe Payments: Payment processing that handles complexity. Support for multiple payment methods, currencies, and regions. Built-in fraud protection, subscription management, and compliance handling. Next.js Frontend: Fast, SEO-friendly storefronts with modern developer experience. Server-side rendering for performance, API routes for backend logic, and React for interactive experiences.
Key Advantages
This stack delivers flexibility without sacrificing capability. Need to add a new sales channel? Your content and payment infrastructure remain unchanged. Want to experiment with a different frontend framework? Your backend services continue working. Need to customize the checkout flow? You control the entire experience. Each component excels at its specific function. Sanity provides superior content management. Stripe handles payment complexity. Next.js delivers performance and developer experience. Together, they create commerce experiences that monolithic platforms can't match.
Content Architecture with Sanity
Modeling Your Commerce Data
Sanity's flexibility is its strength, but structure is essential for commerce. Start with core schemas: products, variants, collections, and categories. Each schema should capture both content (descriptions, images) and commerce data (prices, inventory, SKUs). Products need rich content capabilities. Multiple images with different crops for various layouts. Long-form descriptions with embedded media. Specification tables. Size guides. Related products. Sanity's portable text and references enable this complexity without losing structure.
Variants and Options
Product variants (size, color, material) require careful modeling. Create option schemas that define available choices. Products reference these options. Variants combine specific option values with unique data like SKU, price, and inventory. This approach enables powerful queries. Find all products available in blue. Show products with inventory below threshold. Filter by price range across variants. Sanity's GROQ query language makes these queries straightforward.
Content Personalization
Structure content for personalization from the start. Tag products by customer segment, season, or promotional campaign. Create collection documents that define merchandising rules rather than static product lists. This enables dynamic collections that update automatically. Sanity's real-time capabilities shine here. Editors can preview changes instantly. A/B test different product descriptions. Update promotional banners without developer intervention. Content becomes a growth lever, not a bottleneck.
Multi-channel Content
One content model serves all channels. Your web storefront queries Sanity for products. Mobile apps use the same data. Email campaigns pull from the same source. In-store displays reference the same content. Changes propagate everywhere automatically. This eliminates content synchronization problems. Product information stays consistent across touchpoints. Launches happen simultaneously everywhere. Content management becomes centralized while delivery remains distributed.
Payment Infrastructure with Stripe
Building Secure Checkout
Stripe handles payment security so you don't have to. Use Stripe Elements for card collection. Payment information never touches your servers. Stripe returns tokens that you use to charge customers. This keeps you out of PCI compliance scope while maintaining control over checkout experience. The checkout flow requires coordination. Customer adds items to cart (stored client-side or in your database). They proceed to checkout. You create a Stripe payment intent with the order total. Customer completes payment using Stripe Elements. Stripe confirms payment. You fulfill the order.
Handling Multiple Currencies
Global commerce requires multi-currency support. Store prices in your base currency in Sanity. Use Stripe's currency conversion at checkout, or maintain separate price points for different markets. Consider payment method availability by region (iDEAL in Netherlands, Alipay in China). Stripe simplifies this complexity. It handles settlement in different currencies, manages exchange rate fluctuations, and supports local payment methods. You focus on product and customer experience.
Subscription Commerce
Stripe's subscription engine enables recurring revenue models. Create subscription products. Define billing intervals. Handle trial periods. Manage upgrades and downgrades. Stripe automates billing cycles, retry logic for failed payments, and prorated charges. Model subscription products in Sanity just like physical products. Link them to Stripe subscription prices. Your frontend presents subscription options. Stripe handles the recurring billing. Your fulfillment logic processes each billing cycle.
Webhooks and Order Processing
Stripe webhooks notify you of payment events. Payment succeeded, payment failed, refund processed. Build webhook handlers in your Next.js API routes. Verify webhook signatures. Process events idempotently (same event might arrive multiple times). Use webhooks to trigger order fulfillment. Create order records in your database. Send confirmation emails. Update inventory in Sanity. Notify shipping services. Webhooks make your system event-driven and reliable.
Frontend Experience with Next.js
Performance Through Server Rendering
Next.js enables fast, SEO-friendly storefronts through server-side rendering and static generation. Product pages can be statically generated at build time for instant loading. Collection pages can use incremental static regeneration to balance freshness and performance. Cart and checkout remain client-side for interactivity. This hybrid approach delivers the best of both worlds. Static pages load instantly and rank well in search. Dynamic pages provide personalized experiences. Next.js handles the complexity of choosing the right rendering strategy.
API Routes as Backend
Next.js API routes provide serverless backend functionality. Use them for operations that require secrets or server-side logic: creating Stripe payment intents, verifying webhooks, sending emails, updating inventory, managing sessions. This eliminates the need for a separate backend service for many use cases. Your Next.js application handles both frontend and lightweight backend needs. As you scale, extract complex operations into dedicated services, but start simple.
State Management and Cart
Shopping cart state can live in client storage (localStorage) for simplicity or in a database for persistence across devices. Start client-side. Move to database-backed carts when you need cross-device support or want to recover abandoned carts. Use React Context or state management libraries to share cart state across components. When cart changes, update both local state and storage. Validate cart contents against current product data before checkout to handle price or availability changes.
Search and Discovery
Product discovery makes or breaks commerce experiences. Start with GROQ queries for filtering and sorting. Add Algolia or similar search service when you need fuzzy matching, typo tolerance, and instant results. Sanity integrates cleanly with search services through webhooks. Build faceted search using product attributes. Filter by category, price, color, size. Show result counts for each filter option. Update results instantly as filters change. This guided discovery helps customers find products efficiently.
Going to Production
Deployment Architecture
Deploy Next.js to Vercel for optimal performance and developer experience. Vercel's edge network serves static pages globally. Serverless functions handle API routes. Automatic preview deployments for every git push enable easy testing. Sanity runs as a managed service. No infrastructure to manage. Stripe handles payment processing infrastructure. Your deployment complexity focuses entirely on your storefront. This managed services approach reduces operational overhead significantly.
Content Preview and Publishing
Sanity's draft system enables content preview before publishing. Implement preview mode in Next.js that shows draft content. Editors preview changes in production-like environment. Approve and publish with confidence. Use webhooks to trigger rebuilds when content publishes. Incremental static regeneration keeps pages fresh without full site rebuilds. This workflow balances editorial flexibility with frontend performance.
Monitoring and Analytics
Instrument everything from day one. Track page views, product views, add to cart, checkout initiation, and purchase completion. Use this funnel to identify drop-off points. Google Analytics, Segment, or similar platforms provide the tracking infrastructure. Monitor technical metrics alongside business metrics. Page load times, API response times, error rates, and checkout success rates. Stripe dashboard shows payment metrics. Sanity shows API usage. Vercel shows deployment and performance data.
Inventory and Order Management
For simple operations, manage inventory in Sanity and orders in your database. For complex needs, integrate specialized services. ShipStation for shipping. Shopify for inventory sync. Your composable architecture makes these integrations straightforward. The key is starting simple and adding complexity only when needed. Many businesses can launch with basic inventory tracking. Add sophisticated systems as volume demands them.
Scaling Your Commerce System
Growing Beyond Launch
Composable architecture shines as you scale. Each component scales independently. Sanity handles increasing content volume through its distributed architecture. Stripe scales to any payment volume automatically. Next.js applications scale through Vercel's edge network. Focus optimization on actual bottlenecks. Monitor performance metrics. Profile slow pages. Optimize database queries. Add caching strategically. Don't prematurely optimize. Let data guide your efforts.
International Expansion
Launching in new markets becomes straightforward with composable systems. Add localized content in Sanity. Stripe handles local payment methods and currencies. Next.js internationalization provides localized routes and content. Deploy region-specific edge functions for optimal performance. Structure content for internationalization early. Separate translatable content from code. Use locale-specific assets. Consider regional regulations and payment method preferences. The technical foundation supports global growth.
Adding New Capabilities
The composable approach makes adding capabilities incremental. Need reviews? Add a review service. Want personalization? Integrate recommendation engine. Require advanced search? Add Algolia. Each addition is independent. Existing functionality remains unaffected. This is the core advantage of composable commerce. Your system evolves through addition, not modification. New channels, new features, new integrations all connect through APIs. The architecture supports continuous innovation.
The Composable Advantage
Sanity, Stripe, and Next.js provide a foundation that grows with your business. Start simple. Launch fast. Add complexity as needed. Each component handles what it does best. You focus on customer experience and business logic. The future of commerce is composable. Flexible systems that adapt to business needs rather than forcing business to adapt to platform constraints. Build your commerce platform the modern way. Start with Sanity, Stripe, and Next.js today.
Keep order, payment, and delivery state distinct
Trace one order through separate authorities
A fictional store creates an order while payment is pending. A browser returning from checkout can tell the interface where the person navigated; it cannot alone establish that funds settled. Payment state needs verification and reconciliation with the provider’s authoritative records. Fulfillment has its own availability and delivery constraints. The lifecycle figure is a reference model. Refunds are a separate process that must reconcile payment and order ledgers; they are not simply another success-page state.
The order lifecycle
Payment confirmation, fulfillment, delivery exceptions, and refunds have distinct authorities that must be reconciled with the order.
Illustrative framework · Graphic by Nick JensenRead the diagram as text
Reference order flow from pending payment through verified payment and fulfillment, with cancellation, delivery exceptions, and a separate refund reconciliation process. Payment confirmation, fulfillment, delivery exceptions, and refunds have distinct authorities that must be reconciled with the order.
Receive notifications as repeatable input
A signed payment notification can arrive more than once or in an unexpected order. Verify the raw payload signature, atomically claim its event identity, and persist the relevant state before treating processing as durable. Keep expensive fulfillment out of a fragile request path by recording work for a retry-safe worker. The sequence figure shows this handoff. A stable order identity should also protect fulfillment, because deduplicating a provider event does not prevent two different events from requesting the same delivery. Consult the provider’s webhook contract before implementing these transitions: https://docs.stripe.com/webhooks.
Payment events across system boundaries
Verify signed events, commit identity and state durably, then fulfill through a retry-safe worker keyed by order identity.
Illustrative framework · Graphic by Nick JensenRead the diagram as text
Sequence: Provider to Handler: signed payment event; Handler to Handler: verify raw body signature; Handler to Database: atomic event id claim and state update; Database to Handler: committed or already processed; Handler to Provider: successful acknowledgement after durable commit; Worker to Database: claim pending fulfillment; Worker to Fulfillment: retry-safe delivery keyed by order. Verify signed events, commit identity and state durably, then fulfill through a retry-safe worker keyed by order identity.
| Input or interruption | Required decision |
|---|---|
| Duplicate signed event | Return the durable prior result; do not repeat fulfillment. |
| Older event arrives later | Reconcile current authority; avoid regressing state by arrival order alone. |
| Checkout success redirect | Show pending until authoritative payment state is confirmed. |
| Worker times out after delivery | Investigate the external outcome by stable order identity before repeating the action. |
| Payment confirmed, stock unavailable | Assign an exception owner and reconcile refund or alternative delivery. |
Rehearse the awkward states
Use fake provider payloads and a synthetic order. Deliver the same event twice, deliver an older event after a newer one, and interrupt the worker after an external action but before local acknowledgement. Define how each case is reconciled without a repeated shipment or a false paid state. A state machine drawn on a page does not enforce those invariants. They need storage constraints, idempotent provider operations where supported, and explicit reconciliation for ambiguous outcomes. A timeout does not prove that the external action failed.
Make exceptions owned and visible
When payment is confirmed but stock is unavailable, put the order into an owned exception path. Tell the customer what is known without claiming fulfillment happened. Reconcile refund or alternative-delivery decisions through the relevant authority. The tradeoff is additional state and operational work. Collapsing every stage into one paid flag makes the happy path look simple while hiding the recovery cost. Begin with a transition table naming the event, authority, invariant, and owner. The duplicate-safe workflow and migration articles supply complementary identity and recovery models.