Building a Headless Shopify Storefront with NextJS — Live API Data in One Day
Building a Headless Shopify Storefront with NextJS — Live API Data in One Day
Yesterday I shipped the salon site in one session. Today was the project I'd been nervous about: connecting a NextJS frontend to Shopify's Storefront API, pulling real product data via GraphQL, and building a functional cart — all for a brand called That's G.
It's Thursday, March 27th. The store is live. Eight products across three collections, variant selection, cart state management, and an editorial design language inspired by Symbol Audio. All fetched from a real Shopify development store.
This one was supposed to take three days. It took one.
I'm starting to think the 10-day plan was wildly overestimated.
Live site: mockup-store-thatsg.vercel.app Source: github.com/byronPantoja/mockup-store
The Setup Nobody Tells You About
Here's the thing about headless Shopify that tutorials bury: the actual API integration is simple. The setup is the hard part.
You need a Shopify Partner account, a development store, a custom app with the right API scopes, a Storefront API access token, AND an Admin API token (for seeding products). None of that is difficult, but it's 10 minutes of clicking through admin panels that no amount of AI can skip.
Once the tokens were in my .env.local, I had Claude generate a product seeding script. Eight products — four coffee bags with size variants (250g/500g/1kg), two merch items with color variants, and two gift sets. The script populated my Shopify dev store via the Admin API in about a minute. Real products, real images, real variant pricing.
The Storefront API client is almost disappointingly simple:
export async function shopifyFetch({ query, variables }) {
const res = await fetch(
`https://${domain}/api/2025-01/graphql.json`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Shopify-Storefront-Access-Token': storefrontToken,
},
body: JSON.stringify({ query, variables }),
}
);
return res.json();
}
No Shopify SDK. No Hydrogen. Just fetch and GraphQL. That's the entire backend integration.
The Design Study That Changed Everything
Before writing any frontend code, I studied Symbol Audio's website — a furniture company with one of the most beautiful e-commerce sites I've seen. Their design language is warm, editorial, and product-forward: cream backgrounds, bold serif typography, asymmetric grids, and full-bleed photography.
I adapted that aesthetic for a coffee brand:
- Warm cream palette (
#FAF7F2) with deep maroon and blue contrast sections - Playfair Display for massive lowercase headings ("shop collections", not "Shop Collections")
- Asymmetric collection grids — 60/40 splits, full-width atmospheric banners
- Sharp-cornered buttons. No border-radius anywhere. This was critical to the editorial feel.
The result doesn't look like a typical Shopify store. It looks like a coffee table book that happens to sell coffee. That distinction matters when employers are evaluating design sensibility alongside technical skill.
The Branding Decision
The brand is "That's G" — short, punchy, memorable. The full legal name is "That's G — Coffee Roastery," but "Coffee Roastery" only appears in the footer and billing copy. Everywhere the customer sees — logo, hero, nav, product pages — it's just "That's G."
This mirrors how real brands work. Symbol Audio doesn't put "audio equipment manufacturer" in their header. Apple doesn't write "consumer electronics" next to the logo. The short name leads. The descriptor lives in the fine print.
Cart State Management
The cart is managed with React Context and useReducer. Adding an item dispatches an ADD_ITEM action with the product, variant, and quantity. The reducer handles deduplication (adding the same variant twice increments quantity). Derived values — cart total and item count — compute from the items array.
The cart drawer slides in from the right with quantity controls, line totals, and a subtotal. The "Checkout" button shows a "This is a portfolio mockup" message. I considered wiring it to Shopify's real checkout flow, but that's production work — not portfolio work.
What I Learned About Headless Commerce
The Shopify Storefront API is almost too easy to work with. No rate limits for normal usage, clean GraphQL schema, good documentation. The hardest part wasn't the API integration — it was the editorial design system.
Getting asymmetric grids to feel intentional rather than broken takes iteration. Making contrast sections (cream → maroon → cream → blue) flow as a coherent scroll rather than jarring blocks requires careful spacing and typography choices. The AI could scaffold the components, but the design taste had to come from me.
That's the thing about AI-assisted development that I keep rediscovering: it doesn't replace judgment. It removes the friction between having a judgment call and executing it.
The Sprint So Far
Three days in. Two projects shipped. Both ahead of schedule.
| Day | Planned | Actual | |-----|---------|--------| | Mar 25 | Start salon (Day 1 of 3) | Planned sprint, started salon | | Mar 26 | Continue salon (Day 2 of 3) | Salon shipped. Done. | | Mar 27 | Finish salon (Day 3 of 3) | Shopify store shipped. Done. |
Tomorrow I'm starting the dashboard. The original plan said Days 7–9. I'm starting on Day 4. If the dashboard ships in one day too, I could have the entire portfolio — all three projects plus byronpantoja.com — done by Saturday.
A 10-day sprint in 5 days. We'll see.
This is Part 3 of a 4-part series. Next: Day 4 — The Dashboard Became a Full-Stack Supabase App.