Case studyDelivered
3dfilamentci
An e-commerce platform for 3D printers, filament, resin and spare parts — built from scratch for a specialist shop.
- Role
- Sole engineer — architecture, backend, storefront, admin, infra
- When
- 2026
- Backend
- DevOps
- Full-stack
Built for a client’s shop and handed over; the public launch is theirs to schedule, so there is no live link yet. The source is private.
Who it’s for
- A specialist 3D-printing shop moving off a generic e-commerce package that could not model its catalogue.
- Shoppers who search for an exact material and colour — “PLA matte black” — and expect to land on that variant.
- The shop’s staff, who manage thousands of variants, stock and orders, and live in Excel.
What I built
- Designed and built the whole platform alone: a NestJS API and background worker, a Next.js storefront, a React admin panel, and a typed client generated from OpenAPI.
- Catalogue with a variant matrix, SEO-aware variant URLs and redirects, Excel import/export, a stock ledger with reservations, card payments (PayTR) and bank transfer.
- Admin security — argon2, Redis sessions, TOTP 2FA, lockout, rate limits, roles, audit log — and the Turkish legal records: order snapshots, consent history, distance-sales contract acceptance.
- The infrastructure as code: Docker Compose behind Caddy, CI against real PostgreSQL and Redis, images to GHCR, tag-based production deploys with a written rollback.
How it works
1Import the catalogue
Staff upload an Excel file; every row is validated and reported first, then applied in one transaction. Exports re-import unchanged.
2Find the product
Turkish-aware search or filtered categories lead to a variant page: each colour has its own indexable URL, weight and diameter are parameters.
3Cart & checkout
Prices, stock, shipping threshold and VAT are recalculated on the server every time; the contract version and consent are stored with time and IP.
4Pay
Card (PayTR iFrame) or bank transfer. Stock is reserved when the order is placed and committed when the hash-verified payment callback arrives.
5Fulfil
Staff move the order from preparing to shipped (tracking number required) to delivered; refunds return stock automatically.
Key decisions
01
Build the commerce core instead of adopting a framework
Instead of: Vendure — evaluated and documented, not chosen.
Why: The admin was being designed separately and the data model had to be ready for a marketplace from day one. A set of focused NestJS modules was cheaper to own than bending a framework around both.
02
Hybrid variant URLs
Instead of: One page per variant, or one page for all of them.
Why: Each variant axis gets a role: colour is a page axis with its own canonical, indexable URL; weight and diameter are parameters on the same page. Colour searches are where traffic is; “1 kg vs 250 g” pages would be thin duplicates. When a product moves, old URLs 301 to the right colour and redirect chains are flattened.
03
A transactional outbox and a worker
Instead of: Revalidate storefront pages from the request handler.
Why: Every catalogue write emits an event in the same transaction; a BullMQ worker batches them into storefront revalidation. Nothing is lost or announced twice if a request fails halfway — and the same stream will feed the marketplace sync.
04
Reserve stock at order time, commit on payment
Instead of: Decrement stock only when the payment succeeds.
Why: A movement ledger with locked rows that never goes negative. Two shoppers can’t buy the last spool, reservations expire on their own, and a payment that arrives late re-reserves the stock or flags the order for a person.
Architecture
Docker Compose on a single server: production and staging run as separate projects on a shared edge network. Everything here is mine.
Numbers
- typed API endpoints (generated client)
- 91
- test files across API, storefront and admin
- 200+
- mobile Lighthouse performance, product pages
- 90 → 95
- review findings fixed, each with a regression test
- 30+
Tech stack
Backend
- NestJS 12
- TypeScript
- TypeORM
- PostgreSQL 18
- Redis
- BullMQ
- OpenAPI
Frontend
- Next.js (App Router)
- React
- Vite
- Playwright
Infrastructure
- Docker Compose
- Caddy
- imgproxy
- GitHub Actions
- GHCR
- Turborepo
- pnpm
Commerce
- PayTR
- Bank transfer
- Excel import
- JSON-LD ProductGroup
Want the longer version — the code, the pipeline, the trade-offs?
Email me