I co-founded TapCraft Studio and built its headless Shopify storefront for 3D-printed NFC keychains. The 3D viewer switched colour variants in real time with Three.js material updates, affiliate tracking worked without a native theme, and I led the move from consumer sales to B2B. The store is still up.
Co-founder, Feb–Oct 2026. TapCraft sells 3D-printed NFC keychains: tap one to a phone and it opens a link. The product is physical, but the hard part was digital: showing people exactly what their custom keychain would look like before they ordered. I built the whole frontend, solved the two headless problems below, and led the pivot to B2B.
Timeline
Feb 2026
Headless from day one
Ruled out WordPress and a stock Shopify theme. Built the headless Shopify + Next.js 16 frontend from scratch for full control over layout, the 3D viewer and checkout.
Feb 2026
3D product viewer
A React Three Fiber viewer for the keychains. Colour variants changed the material on the loaded model, so there was no GLB swap and no reload.
Mar 2026
Affiliate tracking, headless
UpPromote hooks into the native Shopify checkout, and headless mode removes those hooks. Web Pixel and cart context events got attribution working again.
Mar 2026
B2C to B2B
Restructured the catalogue, mapped 301 redirects and turned the 3D customiser into a bulk-quote tool. Affiliate tracking carried over.
Oct 2026
Ended
My co-founder role ended in October 2026. The store is still up at tapcraft.shop.
Key technical decisions
three.js material update over GLB swap per variant
Swapping GLB files on every colour change means fetching and parsing geometry each click. Setting the material colour is one property assignment, with no network request.
web pixel + cart events over native Shopify affiliate hooks
A headless checkout breaks UpPromote's default hooks. Shopify Web Pixel runs sandboxed with access to cart context, which made it the reliable way to attribute referrals.
storefront API (GraphQL) over admin REST API
The Storefront API is the public, read-optimised surface for headless frontends: products, variants, cart mutations and checkout. The Admin API is for back-office work.
cloudflare R2 over S3 for 3D assets
R2 has no egress fees. The 3D models are large and load on every product page, so S3 egress would have added up.
3D variant switching
colour variant switchts
1// colour variant switch, no GLB reload
2functionapplyVariant(scene, hex) {
3 scene.traverse(obj => {
4if (obj.isMesh && obj.material) {
5 obj.material.color.set(hex)
6 obj.material.needsUpdate = true
7 }
8 })
9}
Walk the scene graph, find every mesh, set the material colour. No file fetch, no geometry parse, no loading state. The viewer also rendered on demand (frameloop="demand") instead of every frame, to keep GPU load down.
The store at 390px.
Stack
FrontendNext.js 16 · React Three Fiber · Tailwind v4