Best Stack for an E-Commerce Site

A lean, fast e-commerce stack for small stores and digital product shops. Stripe-first billing, headless content, zero server management.

Confidence8/10Maintenance7/10$ · low costE-commerce / digital product storeReviewed Mar 2026

Quick Verdict

This stack is for stores with under a few hundred SKUs that want to ship fast and not operate a Shopify alternative. It separates the two concerns of e-commerce cleanly: product content (Sanity) and transactional data (Neon + Stripe). The architecture is sound; the complexity is in getting Stripe webhooks right.

If you're selling globally and don't want to deal with VAT, use Lemon Squeezy instead of Stripe.

Best For

  • Digital product stores — SaaS, templates, courses, ebooks, under a few hundred SKUs
  • Non-developer content management — Sanity gives your team a visual editor for products
  • SEO-critical storefronts — ISR means product pages load from CDN instantly
  • Founders who want PCI-compliant checkout without building it — Stripe Checkout handles this

Avoid If

  • Selling globally without wanting to manage VAT/sales tax — use Lemon Squeezy
  • You need a full inventory management system
  • You have 1000+ SKUs with complex filtering needs
  • Non-developers need to manage orders (Sanity manages product content, not order data)

Why These Tools Belong Together

E-commerce has two distinct data domains: product content and transactional data. This stack keeps them separate deliberately.

Sanity handles product content (names, descriptions, images, variants) with a visual editor. Neon handles orders and customers with relational integrity. Stripe handles checkout and billing. Vercel stitches it together with ISR.

What It Optimizes For

  • Zero PCI compliance work (Stripe Checkout handles cards)
  • Fast product pages (ISR served from CDN)
  • Non-developer content management (Sanity)
  • Zero infrastructure management

What It Sacrifices

  • Tax compliance (you handle VAT yourself)
  • Full inventory system
  • Advanced product variants and filtering at scale

Implementation Order

  1. npx create-next-app@latest --typescript --tailwind --app
  2. Set up Sanity + define product schema — build product listing pages with ISR first
  3. Set up Neon + Drizzle — orders, line_items, customers tables
  4. Implement Stripe Checkout (product → session → success page)
  5. Handle checkout.session.completed webhook → create order record in Neon
  6. Add Resend for order confirmation email
  7. Add Clerk for customer accounts if users need order history

Do Now / Do Later

Do now: Stripe webhook handler with idempotency, order email confirmation, Sanity product schema. Get these right before your first sale.

Do later: Customer accounts, inventory tracking, advanced filtering. Add when customers ask for them.

What Breaks First

  1. Stripe webhook failures — if a webhook fails after payment, your order won't be recorded. Always log raw webhook events to a table and process idempotently. Replay failed events manually.
  2. Sanity/Neon data consistency — keep product IDs consistent between Sanity (content source) and Neon (order data). Don't duplicate product fields — just store the Sanity document ID in your orders table.
  3. ISR staleness — when you update product prices in Sanity, Vercel's ISR cache needs to revalidate. Configure revalidatePath() in your Sanity webhook handler.

AI Coding Notes

Stripe + Next.js is extremely well-covered in AI training data. The most common generation error is webhook handling — AI often generates handlers that parse the body as JSON before signature verification. The raw body must be used for stripe.webhooks.constructEvent().

Common AI Mistakes

  • Storing order data in Sanity — CMS is not a database. Orders go in Neon.
  • Using req.json() body in Stripe webhook — must pass raw body to stripe.webhooks.constructEvent()
  • Missing idempotency in webhook — causes duplicate orders when Stripe retries delivery
  • Fetching Sanity data in a client component on every render — use server-side ISR with generateStaticParams()

Migration Warning

Moderate. Stripe's data model gets embedded in your order schema (Stripe priceId, customerId as foreign keys). Moving away from Stripe later requires migrating this data. Sanity is more portable — you own the content schema. Neon is standard Postgres, easy to migrate.

Confidence Score — Why

8/10. Solid for small-to-medium storefronts. Deducted 2 points for webhook reliability complexity and the dual-CMS architecture that requires discipline to keep consistent.

Starter Config Files

# My E-Commerce Stack

- Framework: **Next.js 15** (App Router, TypeScript, ISR for product pages)
- Styling: **Tailwind CSS** + shadcn/ui
- Product content: **Sanity CMS** (GROQ queries, ISR revalidation)
- Payments: **Stripe Checkout** (hosted, no custom card form)
- Orders database: **Neon** (serverless PostgreSQL)
- ORM: **Drizzle ORM** (@neondatabase/serverless driver)

Unlock full config files

Copy, download as .zip, and see all 5 complete files for this stack.