ImpressãoMais3D
On-demand 3D printing e-commerce

Context
A 3D printing store sells two very different things through the same cart: a catalogue part, and a part that does not exist yet, uploaded by the customer as a 3D file. Both run through quoting, production, delivery and in-store pickup.
The challenge
Selling a part nobody has seen yet. The customer must trust the result before production starts — and once printed, there is no undo. Add an order that crosses quoting, artwork, payment, production and delivery, each with its own rules, and the real risk stops being technical and becomes commercial: printing the wrong thing costs material and time.
The architecture
A 3D visual proof generated automatically from the uploaded file and rendered in the browser, which the customer approves before anything reaches the printer — approval is an explicit gate in the flow, not a notice. Underneath, a modular monolith of twenty bounded contexts where module boundaries are enforced by tooling, not by convention.
How the code is organised
Modular monolith organised by bounded context under src/modules/, with twenty contexts — among them catalogue, pricing, cart, order, payment, artwork, visual proof, fulfilment, coupons, campaigns, CRM and the AI knowledge base.
Architecture flow
Order
- Catalogue part
- STL, OBJ or 3MF upload
3D visual proof
- Generated from the uploaded file
- React Three Fiber
Customer approval
- An explicit gate in the flow
- Auditable record
Production
- Locked until approval
- FDM, resin and SLS
Delivery
- Shipping or in-store pickup
Engineering decisions
Visual proof before production
The uploaded file (STL, OBJ or 3MF) is rendered in the browser with React Three Fiber and becomes a proof the customer approves or rejects. Production stays locked until approval — turning a conversation about expectations into an auditable record.
Boundaries the linter enforces
Each module has domain / application / infrastructure / presentation layers, and the domain layer imports no Supabase, Next or React — enforced by an ESLint rule (no-restricted-imports), not by discipline. Modules only talk through the application layer.
Authorisation lives in the database
Permissions are Row Level Security policies in Postgres, not checks scattered across the UI. The screen can be wrong; the database row stays protected.
Deliberately refusing complexity
No microservices, no event bus, no queues — and that is written down in the architecture, with the reasoning. Knowing when not to distribute is as real a design decision as knowing how to.
Tested where it hurts
Vitest on business rules and a Playwright suite covering the money and production paths: payment, visual proof, artwork, fulfilment and the reseller panel.