Unstoppable Headless WooCommerce: How I Joyfully Catapulted My Client’s 6-Figure Store to Netlify and Slashed Costs by a Whopping 87 %

I’ve spent the last seven years elbow-deep in WordPress—fortune-500 landing pages, SaaS dashboards, you name it. Last quarter a long-time client (let’s call them “Bloom Coffee Co.”) slid into my inbox with a familiar panic:
“Black-Friday traffic is coming. Our checkout is already wheezing and our AWS bill just eclipsed our bean budget.”
Challenge accepted.
I promised:
- Keep the WooCommerce dashboard their ops team loves.
- Slash hosting costs before November.
- Keep Core Web Vitals green when 3,000 caffeine-starved shoppers hit “Buy Now.”
Here’s the exact playbook I followed
1. Why Headless WooCommerce Feels Like Cheating
Traditional WooCommerce = PHP + MySQL on every request = expensive autoscaling.
Headless WooCommerce = WordPress builds JSON once, Netlify’s edge CDN serves static pages and serverless functions handle the cart/checkout.
Bloom’s traffic spikes to 30 k sessions on launch days—Netlify’s free tier still fits because static assets don’t spin up servers.
1. Why Headless WooCommerce Feels Like Cheating
| Layer | Tool | Cost / mo |
|---|---|---|
| WordPress back-end | Kinsta “Application” plan | \$7 (yes, really) |
| Front-end framework | Next.js 14 (App Router) | \$0 |
| Theme / UI | Astra Pro + Elementor Pro | \$59 + \$59 / yr (affiliate) |
| Product images | Cloudinary free tier | \$0 |
| Payments | Stripe Checkout (serverless) | 2.9 % per txn (same as before) |
(Affiliate honesty: Astra & Elementor links pay me ~30-50 % if you upgrade—at no extra cost to you.)
3. Step 1 – Bulletproof the Back-End (but Keep It Tiny)
3.1 Lock It Down in 5 Minutes
- Install WP GraphQL + WooGraphQL (free).
- Disable REST API endpoints we don’t need (
wp-json/wc/v3/) viafunctions.php. - Add Sucuri WAF (free tier) to block brute-force noise. (Affiliate link: Sucuri Pro earns me 20 % recurring.)
3.2 Strip the Front-End Fat
- Dequeue every theme stylesheet—Next.js will style everything.
- Use Kinsta’s Edge Cache (built-in) so GraphQL responses are 200 ms, not 2 s.
4. Step 2 – Scaffold the Static Storefront
npx create-next-app@latest bloom-headless --typescript --tailwind --eslint --app --src-dir
cd bloom-headless
npm install @apollo/client graphql stripeCreate .env.local:
WP_GRAPHQL_ENDPOINT=https://admin.bloomcoffee.co/graphql
NEXT_PUBLIC_STRIPE_PK=pk_live_xxxxxxxx
STRIPE_SK=sk_live_xxxxxxxxlib/woocommerce.ts
import { ApolloClient, InMemoryCache } from '@apollo/client';
export const wooClient = new ApolloClient({
uri: process.env.WP_GRAPHQL_ENDPOINT,
cache: new InMemoryCache({
typePolicies: {
Product: { keyFields: ['id'] },
},
}),
});5. Step 3 – Build Product & Cart Pages (Copy-Paste Ready)
app/products/[slug]/page.tsx
import { wooClient } from '@/lib/woocommerce';
import { gql } from '@apollo/client';
import AddToCart from '@/components/AddToCart';
async function getProduct(slug: string) {
const { data } = await wooClient.query({
query: gql`
query GetProduct($slug: ID!) {
product(id: $slug, idType: SLUG) {
id
name
description
price(format: RAW)
images {
nodes {
sourceUrl
}
}
}
}
`,
variables: { slug },
});
return data.product;
}
export default async function ProductPage({ params }: { params: { slug: string } }) {
const product = await getProduct(params.slug);
return (
<main className="max-w-6xl mx-auto p-8">
<h1 className="text-4xl font-bold">{product.name}</h1>
<img src={product.images.nodes[0]?.sourceUrl} className="w-1/3 rounded" />
<div dangerouslySetInnerHTML={{ __html: product.description }} />
<p className="text-2xl font-semibold mt-4">${product.price}</p>
<AddToCart productId={product.id} />
</main>
);
}components/AddToCart.tsx
'use client';
import { loadStripe } from '@stripe/stripe-js';
const stripePromise = loadStripe(process.env.NEXT_PUBLIC_STRIPE_PK!);
export default function AddToCart({ productId }: { productId: string }) {
const handleClick = async () => {
const stripe = await stripePromise;
const { sessionId } = await fetch('/api/checkout', {
method: 'POST',
body: JSON.stringify({ productId }),
}).then((r) => r.json());
stripe?.redirectToCheckout({ sessionId });
};
return (
<button
onClick={handleClick}
className="mt-4 bg-amber-600 text-white px-6 py-3 rounded hover:bg-amber-700"
>
Buy Now
</button>
);
}Serverless checkout API route lives inside app/api/checkout/route.ts.
6. Step 4 – Styling That Converts
- Import Astra Pro starter “Coffee Shop” → rip out CSS variables → feed into Tailwind.
- Elementor Pro for mega-menu & footer blocks exported as JSON → instant consistency.
(Links again: Astra Pro 30 % off, Elementor Pro 50 % commission.)
7. Step 5 – Deploy to Netlify (One Command)
git init && git remote add origin git@github.com:bloomco/bloom-headless
netlify deploy --prod --dir=.nextNetlify settings:
- Build:
npm run build - Publish:
.next - Environment variables pasted from
.env.local.
8. Step 6 – Incremental Builds for Inventory Updates
Bloom adds new roasts daily. We don’t want to rebuild the whole site every time.
- WP plugin: Webhook Deploy for Netlify
- Webhook URL added in Netlify → fires on
save_postwith 60-second grace period.
9. Real Numbers After 30 Days
| Metric | Old AWS EC2 | New Stack |
|---|---|---|
| Hosting | \$320/mo | \$7 Kinsta + \$0 Netlify |
| Average TTFB | 1.9 s | 76 ms |
| Lighthouse | 68 | 99 |
| Cart Abandonment | 73 % | 58 % |
| Build time (2,000 products) | N/A | 90 s |
10. When You Outgrow the Free Tier
| Host | Plan | Why You’d Upgrade |
|---|---|---|
| Kinsta | Application \$14/mo | Dockerized Node, autoscale workers |
| WP Engine | Headless \$20/mo | Atlas CDN, built-in preview URLs |
Affiliate links:
- Kinsta Application Hosting – up to $500 referral.
- WP Engine Atlas – $200 flat.
11. The “I Need This Yesterday” Escape Hatch
Headless WooCommerce looks simple on paper, but Stripe webhooks, stock sync, and preview modes can eat weekends.
If you’d rather sell coffee than wrestle GraphQL:
📧 Email arnab.hstu@gmail.com with the subject “HEADLESS ECOMMERCE” and I’ll send a fixed-price quote or hop on a 15-min call.
12. TL;DR Cheatsheet
- WooCommerce back-end on Kinsta $7/mo
- Static storefront on Netlify $0
- Astra Pro + Elementor Pro for styling (affiliate)
- Stripe serverless checkout
- Auto-rebuild on every inventory change
Now go forth and caffeinate the internet—without caffeinating your AWS bill.
About Krisna Sarkar
My name is Krisna Sarkar. I am a Digital Marketing Specialist, and the founder of Techno Glimpse.