Case study 06 · AI-assisted 3D model generation and printing

Stemini

A multi-service platform that turns a prompt into a printable 3D model, with a person approving the concept before the paid mesh step, a token ledger and delivery all the way to a printer.

Status: PrototypeDeployed pre-launch; development slowed since late June 2026
Role
Product and architecture, and every service from frontend to printer bridge
Timeline
Mar 2026 to present
Context
Own product, sharing identity and infrastructure with USS X
Layers
AI · Backend · Web
Links
Private repositories (frontend, core API, AI worker, slicing worker, bridge)

01Overview

Stemini turns an idea into a physical object. A user describes a model, the system proposes a concept image, and once the user approves it, a 3D mesh is generated, converted, sliced and delivered to a printer.

Why it exists. Designing printable 3D models is a skill most people, including students, do not have. Stemini puts AI generation in front of a real printing workflow, with a person approving each step that costs money.

Where it stands. The services are built and deployed as a pre-launch prototype. Its own architecture reviews list what must be fixed before real users arrive, and those items are tracked openly.

Specification

Services
Next.js frontend, NestJS core API, AI worker, slicing worker, bridge
Generation
LLM prompt rewrite, image model concept, image-to-3D mesh
Human in loop
Concept approval before the paid mesh step, up to 3 attempts
Metering
Token ledger: reserve, then charge or release, idempotent
Slicing
OrcaSlicer CLI in a sandbox per job, .gcode.3mf and estimates
Printers
OctoPrint, Moonraker, PrusaLink, Bambu LAN, drop folder
Data
PostgreSQL stemini schema (40 tables) in the shared database
  • The expensive mesh generation only runs after a person approves a cheap concept image.
  • Tokens are reserved before work starts and settle exactly once, whether the job succeeds, fails or is cancelled.
  • The printer bridge only makes outbound calls, so nothing opens a port on a home or school network.

02What I built

Generation pipeline

  • A server-enforced request state machine with 11 statuses and only legal transitions.
  • A concept phase (prompt rewrite and subject classification, then a concept image) that pauses for approval, and a mesh phase that runs only after it.
  • Dispatch to the AI worker over internal HTTP or a BullMQ queue, with deterministic job ids so the same job cannot be queued twice.
  • A dependency-free GLB to binary STL converter, used when the mesh provider returns no STL, that walks the glTF scene graph and applies world transforms.

Metering and platform

  • A token ledger with reserved and available balances, row locks, idempotency keys and an audit event for every movement.
  • Roles and 27 capability keys enforced by a guard, an audit log and S3-compatible storage behind presigned URLs.
  • Sign-in through the shared USS One single sign-on on the deployed branch, with a personal workspace per user.

Printing

  • A slicing worker that runs the OrcaSlicer CLI in a sandbox directory per job and caches sliced output.
  • Delivery lanes decided on the server (download, operator queue, LAN printing and a deferred cloud lane), with the client only able to hint.
  • A local bridge agent with five printer adapters that polls for commands, claims them under a lease and reports back.

03Architecture

The frontend never talks to the workers. Everything goes through the Core API, which owns tenancy, capabilities, the token ledger and the audit trail, and hands work to separate AI and slicing workers.

Fig. 06.1

From prompt to printer

Generation

  • ClientPrompt

    text, or an image upload (in progress)

    • connects to Prompt optimiser
    • connects to Core API · request
  • ModelPrompt optimiser

    LLM rewrite and subject classification

    • connects to Concept image
  • ModelConcept image

    image model, private storage

    • connects to Human approval
  • ClientHuman approval

    approve or regenerate, up to 3 attempts

    • connects to Mesh generation
  • ModelMesh generation

    image-to-3D API, polled until done

    • connects to GLB to STL
  • ServiceGLB to STL

    in-house converter, no dependencies

    • connects to Slicing worker · STL

Platform

  • ServiceCore API

    11-state request machine, capabilities, audit, lanes

    • connects to Token ledger
    • connects to Download
    • connects to Operator queue
    • connects to LAN lane
    • connects to Cloud lane
  • StoreToken ledger

    reserve, then charge or release; row locks

  • WorkerSlicing worker

    sandboxed OrcaSlicer CLI, time and filament estimates

    • connects to Core API · sliced .3mf

Delivery lanes

  • StageDownload

    signed URL

  • StageOperator queue

    claim, start, complete, fail

  • StageLAN lane

    via the local bridge agent

    • connects to 3D printers · outbound only
  • Deferred shellCloud lane

    records a deferred attempt only

  • Hardware3D printers

    OctoPrint, Moonraker, PrusaLink, Bambu FTPS

Generation runs in two dispatches with a person in between: the cheap concept image must be approved before the paid mesh step runs. Every request reserves tokens up front and settles exactly once. After slicing, the server alone picks the delivery lane; the cloud lane records a deferred attempt and never reports a fake success.

04Interface

Stemini brand art in which a human hand and a robotic hand touch inside a glowing ring framing a 3D printer nozzle, above the Stemini wordmark.
Stemini's brand key art, from the product frontend.

05Hard problems

  1. One correct money path across asynchronous workers

    Problem

    Worker callbacks advance a request's status, and the token settlement must happen exactly once, in the same transaction as the status change, including for older requests that never had a reservation.

    What I did

    Settlement uses deterministic idempotency keys and locks the account row, so a retried or duplicated callback cannot charge twice or drive a balance negative.

  2. Three AI providers with a human pause in the middle

    Problem

    A prompt model, an image model and a 3D model run across two separate dispatches, with a person deciding in between.

    What I did

    The concept image stays in private storage and reaches the mesh provider through a presigned URL. The subject is fixed on the first attempt so storage keys stay consistent across regenerations.

  3. Many printer ecosystems behind one protocol

    Problem

    OctoPrint, Moonraker, PrusaLink and Bambu printers all speak differently, and the operator's network should not accept inbound connections.

    What I did

    One bridge command protocol with claim leasing and five adapters. Remote print start on Bambu printers is deliberately deferred until bed-clear and camera checks exist.

  4. Changing frameworks under a working system

    Problem

    The core API was moving from NestJS to Express to match the rest of the platform, without freezing the generation and printing path.

    What I did

    A strangler migration with shared read and write helpers, and parity tests that compare response bodies and recorded SQL between the two implementations.

06Decisions

Split generation into a cheap concept phase and an expensive mesh phase.
The user can reject or regenerate the idea before the paid 3D call, and every attempt is kept as history.
The server alone picks the delivery lane.
School, printer and capabilities decide how a file may reach a machine, which keeps behaviour safe across tenants.
A deferred cloud lane instead of a fake success.
The cloud adapter validates and records the attempt but makes no vendor call until the integration is real.
Default models chosen for latency and cost, overridable per environment.
The higher-fidelity image preview model timed out during testing, so the faster model is the default.

07Status

Works today

  • The services are on Railway as a pre-launch prototype, sharing identity, PostgreSQL and Redis with USS X Academy. The public frontend is currently asleep.
  • Text-to-model generation, approval, metering, slicing, the printer catalog and the bridge exist in code.
  • Development slowed after late June 2026 while USS X Academy took priority.

Not built yet

  • Finishing the tenancy migration from schools to personal workspaces and organisations.
  • Image-upload generation end to end, and a checkout for buying tokens.
  • A live cloud printing integration and remote print start behind an audited capability.
  • Row-level security and a shared rate limiter, as recommended by its own architecture reviews.

Stemini began as a platform for schools and moved to a consumer-first model in June 2026. It shares its auth service, database and Railway project with USS X Academy, but it is a separate product.

08What I learned

  • Put the human decision before the expensive step. It is better for cost, and better for the result.
  • Anything that touches money needs idempotency designed in from the first migration, not added after a double charge.
  • Dated architecture reviews of the codebase are worth the time. They made the gap between "deployed" and "ready for users" explicit.

09Stack

  • TypeScript
  • Next.js
  • React
  • Node.js
  • NestJS
  • PostgreSQL
  • Redis
  • BullMQ
  • OpenAI API
  • Gemini
  • Meshy 3D API
  • OrcaSlicer CLI
  • Vitest
  • Railway