3DigitalForge
A 3D printing shop that sells finished products and prints from files its customers upload.
Context & problem
A print shop sells two things through one checkout. One is a catalogue product with a price. The other is a file the customer uploads — STL, 3MF or STEP — which has no price at all until something has read its geometry. So the store parses the uploaded model, quotes from what it finds, and shows the customer their own part in a 3D viewer before they order it.
Role
Sole developer.
Constraints
- Self-hosted, with no open ports — the whole stack sits behind a Cloudflare Tunnel.
- Two languages, English default and Portuguese secondary, across the whole site and backoffice.
- Portuguese payment methods are not optional: card, Multibanco and MB Way.
- Three roles — customer, staff, admin — with the backoffice sealed off at the middleware.
Decisions & why
- The uploaded file is parsed in the application, not sent away to be quoted.
- Pricing is the whole transaction. A quote that depends on a third party is a quote that fails when the third party does.
- Docker Compose behind a Cloudflare Tunnel instead of a host with open ports.
- Nothing is exposed to be scanned. The tunnel is the only way in, and it is the same shape of deployment used everywhere else here.
- Object storage is S3-compatible: MinIO in development, Cloudflare R2 in production.
- Customer uploads are the one thing that cannot be recreated from a migration. Same interface both sides means the code that handles them never changes between environments.
Stack
- Next.js 15
- React 19
- TypeScript
- Tailwind
- react-three-fiber
- PostgreSQL 16
- Prisma
- Auth.js
- Stripe
- Cloudflare R2
- Docker