Mouthguard Clinic
Apr 2026
Overview
End-to-end web application for a dental specialist who designs and manufactures custom mouthguards for combat-sports athletes. Clients register, place orders, upload medical documents and 3D jaw scans, pick a dentist location or have their scans picked up, and chat with the clinic directly. The admin side is a full operations tool — client management, order lifecycle, location network, file handling with 3D scan previews, and a built-in messaging thread on every order.
Key features
Client Registration & Password Setup Flow
Self-service sign-up with email verification, plus an admin-initiated flow where the clinic creates a client account and the user receives a set-password email — both backed by signed tokens and rate-limited endpoints.
Guided Order Creation
Multi-step order form — contact details, delivery (courier or InPost parcel locker), dentist location picker (or 'I'll deliver scans myself'), and batch upload of medical documents and 3D jaw scans.
3D Jaw Scan Handling
Clients upload STL/OBJ scans alongside X-rays and photos. Admin can preview, download individually, or grab the whole bundle as a single ZIP per order.
Order Lifecycle Tracking
Seven-stage status pipeline (pending → confirmed → in production → shipped → delivered → completed, with cancellation) and a full audit trail of every status change, who made it, and why.
Two-Way Messaging
Every order has its own thread between the client and the clinic. Unread indicators on both sides so nothing gets missed between production steps.
Dentist Location Network
Admin manages the network of partner dentist offices where scans can be dropped off. Clients pick from active locations during checkout; admin can add, edit, or deactivate them anytime.
Full Admin Panel
Clients, orders, locations, file management, messaging — everything the clinic needs to run day-to-day, with an admin-only client creation flow and role-based access (CLIENT / ADMIN / SUPER_ADMIN).
Transactional Emails
Resend-powered notifications for verification, password reset, admin-created accounts, order updates, and new-message pings — with a no-op fallback in local dev so flows never break.
Screenshots
The Problem
The client is a dental specialist who makes custom mouthguards for martial-arts athletes — MMA, boxing, BJJ. The process is document-heavy: medical forms, X-rays, photos, 3D jaw scans, delivery details, back-and-forth about fit and timing.
Before the app, everything happened over email and messengers. Files got lost, statuses lived in his head, and clients kept asking the same questions between production stages.
He needed a single system where a fighter can register, send all the medical material at once, pick where to drop off the scan (or ship it), and message him about the order — and where he can run the whole operation from one admin panel.
Design
I designed the app from the ground up around the actual production workflow, not a generic e-commerce template. Two separate experiences share the same codebase: a clean client portal focused on placing and tracking a single order, and a dense admin panel built for someone managing dozens of orders in parallel. Approved before development started.
Approach
Two apps, one codebase. Next.js App Router with route groups — (client) for the fighter-facing portal, admin/ for the clinic. Middleware gates everything by role; clients can’t even see admin routes exist.
Orders as the core entity. Every order carries its client, its dentist location (or an “I’ll deliver scans myself” flag), its delivery method (courier or InPost paczkomat), its documents, its status history, and its message thread. One record, one page, everything.
File handling built for medical workflows. UploadThing handles the uploads — medical documents, X-rays, photos, and 3D jaw scans (STL/OBJ). Admin can preview, download, add files on behalf of the client, or grab the full package as a ZIP via JSZip for the lab.
Auth that matches the business. NextAuth with credentials provider, email verification for self-registered users, and a separate admin-initiated flow: the clinic creates the account, the client gets a signed set-password link by email. Password resets, resend-verification, and resend-set-password all run through rate-limited endpoints.
Status history, not status updates. Every status change writes a StatusChange row with the previous state, the new state, who did it, and an optional note. The client sees a clean timeline; the admin has full auditability.
Messaging as part of the order, not a separate inbox. Each order has its own thread. Unread flags flip per recipient, so both sides see exactly what’s new without hunting through a global inbox.
Locations as first-class data. The dentist office network is its own model — the admin manages it from the panel, deactivates offices that aren’t taking scans, and only active ones show up in the client’s checkout picker.
Prisma + PostgreSQL. Strongly-typed schema across the whole stack — users, orders, documents, status changes, notes, locations — with indexes on the fields that actually get queried (email, order number, status, unread messages).
Challenges
Two completely different user experiences. A fighter placing one order has different needs from an admin processing twenty. Same codebase, shared components where they made sense, entirely separate UX where they didn’t — the client flow is guided and minimal, the admin side is table-dense and keyboard-friendly.
Scan delivery logistics. Not every client uses the same path. Some ship via courier, some use InPost parcel lockers (with a point number), some drop scans off at a partner dentist, some deliver them personally. The order model and UI both had to cover all four without turning into a mess.
Admin-created accounts without passwords. When the clinic creates a client on their behalf, that user doesn’t exist yet in any meaningful sense — no password, no verification. The set-password flow uses signed tokens with expiry, a dedicated email template, a resend endpoint, and rate limiting, so an admin can onboard a fighter with just an email address and a phone number.
File volume per order. A single mouthguard order can carry a dozen files including large 3D scans. The admin needs to preview them, add more on the client’s behalf, and hand the whole bundle to the lab — which is why every order has a one-click ZIP export.
Secure-by-default flows. Every auth endpoint — register, forgot-password, reset-password, resend-verification, resend-set-password — is rate-limited. Tokens are signed and time-bound. Uploads are scoped to the authenticated user’s own orders. No shortcuts for “internal” endpoints.
Results
→ Fully digital intake — medical docs, scans, addresses, and communication all live in one system instead of scattered emails and messengers
→ Admin handles the entire order lifecycle from a single panel — no spreadsheets, no external trackers
→ Single source of truth for every order: files, status history, notes, and client data bundled together
→ Role-based auth with rate-limited auth endpoints and signed tokens for every sensitive flow
Need a site, a custom tool, or full e-commerce build?
Send scope, budget range, and timeline. I will reply with a realistic plan.