Inspiration
Small 3D-print shops lose jobs to slow quoting. A customer emails an STL, the maker opens a slicer, estimates the time, does the math, and replies hours or days later. The big marketplaces quote instantly, but they send the job to someone else's factory. PlateQuote gives the maker who owns the printers the same instant quote and a way to get paid on the spot, without letting an AI make up a price.
What it does
PlateQuote is a quote-and-checkout page for a one-person 3D-print shop.
- Shop setup. The owner sets the shop name, bed size, materials (PLA, PETG, ASA, TPU) with their own $/gram and $/machine-hour, a minimum order, and a rush fee. A demo shop, Northline Print, is seeded.
- Quote page. The customer uploads an STL or 3MF (25 MB cap) or picks a sample part, sees a three.js preview, and chooses material, color, quantity, rush, and what the part is for.
- Real slicing. A separate worker runs PrusaSlicer 2.8.1 headless and returns filament grams, print time, and whether supports were generated. Trimesh adds bed fit, watertightness, overhang share, and a thin-wall flag.
- Deterministic price. Material and machine time times the shop's own rates, times quantity. The shop minimum replaces a smaller total, and rush is a flat fee added at the end. The quote shows the shop's tolerance.
- AI printability review and material advice. The reviewer reads only the mesh facts and slicer data and returns plain-English print notes, an orientation note, and a fit rating per material. The AI never sets the price. Any dollar amount it writes is stripped, and the pricing engine attaches comparison prices afterward. One click switches material and re-quotes.
- PayPal checkout (sandbox). PayPal JS SDK v6 one-time payment session with Orders v2. The server creates the order from the stored quote total, so the browser cannot change the amount, and the server captures it. An order is marked paid only if the captured amount matches the quote.
- Webhooks as the backup path.
CHECKOUT.ORDER.APPROVEDmakes the server capture,PAYMENT.CAPTURE.COMPLETEDmarks the order paid. Signatures are verified with PayPal's verify-webhook-signature API. - Shop orders board. Quoted, paid, printing, shipped, behind a password-gated admin.
How PayPal is central
Checkout is the last step and the only payment path. Without PayPal the product is a calculator.
POST /api/paypal/orderscreates an Orders v2 order (intent CAPTURE, USD) from the quote total in the database, with the PlateQuote order id ascustom_id.- The browser loads PayPal JS SDK v6 and starts a one-time payment session.
- On approval the server captures through
POST /api/paypal/orders/{id}/capture. If PayPal answersORDER_ALREADY_CAPTURED, it reads the order instead. The order is paid only if the amount matches. POST /api/paypal/webhookis signature-verified and handles the two events above.- The build refuses any PayPal environment other than sandbox.
How we built it
- Web: Next.js 15 (App Router, TypeScript, React 19), Tailwind CSS 4, three.js through @react-three/fiber and drei, zod, Prisma 6 on PostgreSQL.
- Slicer worker: Python FastAPI in Docker. It runs the PrusaSlicer 2.8.1 CLI as a separate process (AGPL-3.0, downloaded at image build time, not linked) and uses trimesh for mesh analysis. The worker's
/sliceroute is protected by a shared token. - PayPal: OAuth2 client credentials, Orders v2 create and capture, webhook signature verification, JS SDK v6 on the client. Sandbox only.
- AI: a provider switch (
LLM_PROVIDER). The OpenAI-compatible path defaults togpt-4o-miniand the Anthropic Messages API path defaults toclaude-sonnet-4-5;LLM_MODELoverrides either. Output is schema-validated. With no key, or if the provider fails, a built-in rule-based reviewer writes the notes from the same facts, so quotes never break. The hosted demo currently runs that built-in reviewer. - Hosting: a Render Blueprint (
render.yaml) with two web services (the Next.js app and the Docker slicer) and Render Postgres. Docker Compose runs the same three pieces locally. - AI tools used to build it: a Cursor coding agent wrote most of the code from milestones planned in Grok Bot (xAI); Claude Code handled the GitHub migration, the Render deploy, the security review, and this submission. Every change was reviewed by a person.
- Tests: Vitest for pricing, slicer parsing, the built-in reviewer (no prices allowed), webhook handling, the admin session gate, and rate limits. Pytest for G-code summary parsing and the worker token check.
Challenges we ran into
- Keeping AI away from money. The slicer and the shop's rates set every number, and the model only writes words. Dollar amounts are stripped from its output and comparison prices are recomputed by the engine.
- Headless slicing in a container. Recent official Linux slicer builds are Flatpak-only, so the worker pins the 2.8.1 AppImage, extracts it, and runs it offscreen.
- Paying exactly what was quoted. The server builds the order from the stored quote, never from the browser, checks the captured amount, handles a double capture when the browser and the webhook race, and refuses to mark a mismatched payment as paid.
- Shipping a public demo safely. Admin is locked until a real password is set, the dev password is refused on the host, quote creation and admin login are rate-limited, and the slicer only answers the web app.
- Free-tier hosting. Services sleep and disks are ephemeral, so uploads live in
/tmpand the slicer runs as its own service.
Accomplishments that we're proud of
- An end-to-end path from an uploaded mesh to real sliced grams and print time, then a deterministic price and a PayPal sandbox capture, verified with a real sandbox payment on the hosted demo.
- AI that does useful work and is structurally unable to set a price.
- Server-side amount checks and verified webhooks, not just a pay button.
- It runs with zero keys: quotes, slicing and the review all work, and checkout says clearly when PayPal is not configured.
What we learned
- A deterministic core with AI on top builds trust faster than "AI pricing".
- PayPal's v6 SDK plus server-side Orders v2 keeps the payment logic where it can be checked.
- Webhooks matter when a buyer closes the tab after approving.
- The first real sandbox checkout surfaced more usability questions than any test did.
What's next for PlateQuote
Stubbed in the repo, not working yet: a shop ops chat on PayPal's Agent Toolkit (invoices, shipment tracking, refunds for failed prints, weekly sales insights), and an MCP endpoint with get_quote and create_checkout, where checkout returns a PayPal approval link so a person always approves. After that: email receipts, multi-shop accounts, and live PayPal. PlateQuote never controls printers.
Built With
- cursor
- docker
- fastapi
- nextjs
- paypal
- postgresql
- prisma
- prusaslicer
- python
- react
- render
- tailwindcss
- three.js
- typescript
Log in or sign up for Devpost to join the conversation.