[{"data":1,"prerenderedAt":142},["ShallowReactive",2],{"work-shopify-bff":3},{"id":4,"title":5,"body":6,"category":102,"challenge":103,"codeSnippet":104,"description":108,"extension":109,"featured":110,"finalScreenshot":111,"gridOrder":112,"isDemo":110,"isDemoURL":95,"liveUrl":113,"meta":114,"mockupImage":115,"navigation":116,"nextProject":117,"order":120,"path":121,"results":113,"schneiderFeatured":110,"schneiderOrder":113,"seo":122,"solution":123,"stem":124,"subtitle":125,"tags":126,"techStack":132,"thumbnail":139,"thumbnailVideo":113,"year":140,"__hash__":141},"works/works/shopify-bff.md","Store Bridge",{"type":7,"value":8,"toc":94},"minimark",[9,14,18,21,25,47,53,59,65,69,75,81,87,91],[10,11,13],"h2",{"id":12},"the-problem","The Problem",[15,16,17],"p",{},"Shopify's API surface is fragmented by design: the Storefront API is public and optimized for customer-facing reads, the Admin API requires private authentication and provides full CRUD, and custom apps add their own endpoints. A headless frontend that needs product data with real-time inventory, custom pricing, and metafields must juggle 2-3 different API clients with different auth mechanisms.",[15,19,20],{},"This complexity bleeds into the frontend: multiple API clients, inconsistent error handling, no shared caching strategy, and TypeScript types that don't compose well across APIs.",[10,22,24],{"id":23},"architecture","Architecture",[15,26,27,31,32,36,37,36,40,36,43,46],{},[28,29,30],"strong",{},"tRPC Router"," — The BFF exposes a tRPC router with procedures organized by domain: ",[33,34,35],"code",{},"product",", ",[33,38,39],{},"collection",[33,41,42],{},"cart",[33,44,45],{},"customer",". Each procedure fetches from whichever Shopify APIs it needs and returns a unified shape.",[15,48,49,52],{},[28,50,51],{},"Dual API Client"," — The server maintains authenticated clients for both Storefront and Admin APIs. Storefront API handles the bulk of read operations; Admin API fills in gaps (inventory levels, metafield writes, custom data).",[15,54,55,58],{},[28,56,57],{},"Edge Deployment"," — Runs on Cloudflare Workers via Hono. Product data caches at the edge with stale-while-revalidate strategy. Cache invalidation triggers from Shopify webhooks (product/update, inventory_levels/update).",[15,60,61,64],{},[28,62,63],{},"Type Safety End-to-End"," — tRPC generates client types automatically. The frontend imports the router type and gets full autocomplete for every procedure, input, and response shape. No API documentation needed.",[10,66,68],{"id":67},"key-technical-decisions","Key Technical Decisions",[15,70,71,74],{},[28,72,73],{},"Why tRPC over GraphQL federation?"," The frontend doesn't need a generic query language — it needs specific data shapes for specific pages. tRPC's procedure-based approach maps cleanly to page data requirements and avoids the complexity of schema stitching.",[15,76,77,80],{},[28,78,79],{},"Why Cloudflare Workers over a traditional server?"," Edge deployment puts the BFF physically closer to customers. For Shopify storefronts where the Storefront API is already globally distributed, the BFF at the edge means the aggregation overhead is minimal.",[15,82,83,86],{},[28,84,85],{},"Why merge APIs on the server?"," Client-side API orchestration means multiple round trips and exposing Admin API credentials. Server-side merging does one round trip to the BFF and keeps all Shopify credentials server-side.",[10,88,90],{"id":89},"outcome","Outcome",[15,92,93],{},"Frontend API code was reduced by 60% across the projects using the BFF. Response times improved by an average of 200ms due to edge caching and parallel API fetches. The type-safe interface eliminated an entire category of integration bugs.",{"title":95,"searchDepth":96,"depth":96,"links":97},"",2,[98,99,100,101],{"id":12,"depth":96,"text":13},{"id":23,"depth":96,"text":24},{"id":67,"depth":96,"text":68},{"id":89,"depth":96,"text":90},"Backend Architecture","Headless Shopify storefronts need data from multiple Shopify APIs: product data from Storefront API, inventory from Admin API, metafields from both, and custom logic for pricing rules. Frontend code becomes a tangled web of different API clients, authentication schemes, and error handling patterns.",{"language":105,"filename":106,"code":107},"typescript","src/routers/product.ts","export const productRouter = router({\n  getByHandle: publicProcedure\n    .input(z.object({ handle: z.string() }))\n    .query(async ({ input, ctx }) => {\n      // Parallel fetch from both APIs\n      const [storefrontData, adminData] = await Promise.all([\n        ctx.storefront.query(PRODUCT_QUERY, {\n          variables: { handle: input.handle },\n        }),\n        ctx.admin.query(INVENTORY_QUERY, {\n          variables: { handle: input.handle },\n        }),\n      ])\n\n      const product = storefrontData.product\n      const inventory = adminData.productByHandle\n\n      return {\n        ...product,\n        variants: product.variants.nodes.map(variant => ({\n          ...variant,\n          inventoryQuantity: inventory?.variants.nodes\n            .find(v => v.id === variant.id)\n            ?.inventoryQuantity ?? null,\n          // Custom pricing logic\n          finalPrice: applyPricingRules(variant, ctx.customerTags),\n        })),\n      }\n    }),\n})\n","A Backend-for-Frontend layer that unifies Shopify's Storefront and Admin APIs behind a single, type-safe tRPC interface — reducing client complexity and enabling edge caching.","md",false,"/images/projects/shopify-bff-final.jpg",9,null,{},"/images/projects/shopify-bff-mockup.jpg",true,{"title":118,"slug":119},"Theme Launch","shopify-deploy-pipeline",7,"/works/shopify-bff",{"title":5,"description":108},"Built a tRPC-based BFF that sits between the frontend and Shopify. It merges data from multiple Shopify APIs into unified response shapes, handles all authentication, implements edge caching strategies, and exposes a single type-safe interface that frontends consume.","works/shopify-bff","Unified API Layer for Headless Shopify",[127,128,129,130,131],"tRPC","Node.js","Storefront API","Admin API","Edge",[127,128,133,134,135,136,137,138],"Hono","Cloudflare Workers","Shopify Storefront API","Shopify Admin API","TypeScript","Zod","/images/projects/shopify-bff.jpg","2026","d4CDX1U6-nLMjE2TSZVhKtlN4CDXk7L9CmJ31_xiosY",1773700381234]