Doplax.Dev
← Back to projects
MakerUp

Capabilities

  • Payment gateway
  • Invoicing
  • Web, iOS and Android
  • Real-time chat

Frontend

AngularAngular
TypeScriptTypeScript
IonicIonic
CapacitorCapacitor

Backend

NestJSNestJS
Node.jsNode.js
TypeScriptTypeScript
PostgreSQLPostgreSQL
StripeStripe

MakerUp

Completed

MakerUp is a marketplace where makers publish their 3D printing projects, manage their printers and filaments, and sell with Stripe handling the money. The platform takes a cut of every sale. It ships as a cross-platform app (Angular 20 + Ionic 8) on top of a NestJS backend with TypeORM and PostgreSQL.

The challenge

The hard part wasn't listing products, it was closing the money loop: charging on behalf of third parties, keeping a commission, never double-recording a sale even when Stripe retries a webhook, and issuing legal invoices with sequential numbering that hold up to an audit.

Implementation

  • Stripe Connect end to end

    Express account onboarding for makers, PaymentIntents carrying a platform application fee and transfer_data to the seller, and the Stripe Payment Element with 3DS confirmation on the front. Buying only unlocks once the maker has passed KYC and charges are enabled.

  • The amount is derived server-side

    The PaymentIntent takes amount, currency and recipient from the project row in the database and never trusts the client. A deliberate decision after finding that trusting the browser's currency could desync amount and currency.

  • Idempotent webhook as source of truth

    A sale is only recorded from the Stripe webhook, with verified signature and a unique key per paymentIntentId: a redelivery never duplicates the purchase or resends emails. It also covers refunds, disputes and cancelled payments.

  • Legal invoices kept apart from quotes

    Two paths that never mix: a real invoice can only be issued from a closed sale, numbered sequentially per maker and year, VAT included and persisted as a PDF; a quote is a client-side PDF that numbers and persists nothing.

  • httpOnly cookie session, chat included

    No token in localStorage: the session lives in an httpOnly cookie and that same cookie authenticates the 1-to-1 chat WebSocket between buyer and maker. Each message's sender is set server-side, so it can't be spoofed.

  • Catalogs with bulk import

    Filaments, printers and brands with non-destructive upsert import from Excel, brand normalisation by slug and aliases, and duplicate merging from the admin panel.

  • Genuinely cross-platform

    One Angular 20 codebase with standalone components, zoneless change detection and signals-based state, packaged through Ionic + Capacitor for web, iOS and Android, and installable as a PWA.

  • Testing where it hurts

    Jest (backend) and Karma (frontend) suites are mandatory on the critical flows — file uploads, sign-up/login, payments and invoices — plus a Puppeteer E2E smoke run against a local environment with Stripe in test mode.

Frontend