Computer vision & 3D · Gold Coast & Brisbane · 2026

  • My own product
  • In development

Phone photos in, a 3D model out, with a GPU that runs only while a job needs it

A web service that turns a handful of photos into a 3D model you can spin around in the browser. The heavy computer-vision work runs on a GPU that starts per job and scales to zero when idle.

This is my own product, not a client engagement.

It's in development. Screenshots show the real interface with its storage and GPU services stubbed and a generated sample object, so the model shown is a sample file, not a live reconstruction.

Product
Photogrammetry Service (my own)
Industry
Computer vision & 3D
Location
Gold Coast & Brisbane
My role
Design and build
Year
2026
Status
In development

By · Updated

Reconstruction page with every stage ticked and a 3D viewer showing a textured sample boulder on a patch of grass
The finished model in an interactive 3D viewer, with a .glb download. Sample data, not a live run.View full size: The finished model in an interactive 3D viewer, with a .glb download.

The brief

Modern vision models can rebuild a 3D scene from a set of ordinary photos, but they need a GPU, a Python environment and some patience to run. I wanted that capability behind a simple upload page that my other web projects could call: drop in photos, get back a standard 3D file.

Vercel, where my sites run, can't host GPU inference, so the design had to split the work without turning it into two separate products to maintain.

What I built, and why

  1. One repository, two runtimes

    I kept it as one repository. The Next.js app deploys to Vercel and handles uploads, job tracking and the 3D viewer, while a modal/ folder holds the Python GPU service, which deploys separately to Modal. There's one codebase to maintain, even though it runs in two places.

  2. Uploads that skip the web server

    Photos upload straight from the browser to a storage bucket, so large photo sets never pass through the web server. The API then creates a job record and hands it to the GPU service, authenticated with a shared secret.

    Upload form with 24 sample photos of a boulder selected and a Reconstruct 24 photos button
    24 photos selected, taken in two rings around the object. Sample data, not a live run.View full size: 24 photos selected, taken in two rings around the object.
  3. Structure from motion on a GPU

    On an A10G GPU, the service downloads the photos and runs MASt3R-SfM: structure from motion, which works out where each photo was taken and the 3D shape it shows. It exports a .glb mesh sized to the number of images and uploads it, with a 30-minute cap per job.

    I designed the model as one swappable piece, so newer fine-tuned weights can drop in when they're published without rebuilding the rest. The build also includes fixes to work with MASt3R's current alignment and export APIs.

  4. Live status, then a viewer

    Each job moves through queued, downloading, reconstructing, exporting, uploading and done, and the browser watches those status changes live through Supabase Realtime. When it's done, the model opens in <model-viewer>, ready to rotate and zoom.

    Reconstruction page with a stage timeline: submitted, queued and image fetch complete, GPU reconstruction in progress
    Live job status, stage by stage. Sample data, not a live run.View full size: Live job status, stage by stage.
  5. No surprise GPU bills

    The GPU scales to zero when idle, and there are deliberately no automatic retries, so a failed job can't quietly run up GPU time.

    A Settings page doubles as a setup and health check: it tests every environment variable, pings the GPU service and the database, and shows copyable deploy commands for anything missing.

    Settings page with an Everything looks good banner, five environment variables marked set and two service health checks marked OK
    The built-in health check: every variable and service, checked in one place. Sample data, not a live run.View full size: The built-in health check: every variable and service, checked in one place.

What shipped

  • Built on 17 May 2026 (6 commits).
  • Drag-and-drop upload of 2 to 50 photos, direct to storage.
  • GPU reconstruction with MASt3R-SfM on Modal (A10G), with a 30-minute cap per job.
  • Live job status from queued to done, and an in-browser <model-viewer> for the resulting .glb.
  • Settings diagnostics with a setup wizard.
  • Runs inside an existing Supabase project, using prefixed tables and buckets.

In development. Per-job running costs aren't quoted here until I have measured figures.

I can build something like this for your business.

Contact me

Questions about this project

How many photos do I need for a 3D model?

The service accepts between 2 and 50 per job. Generally, more photos taken from different angles, with plenty of overlap between them, give a more complete model than a few shots from the same spot.

What do I get back?

A .glb file, a standard 3D format that opens in the browser viewer on the job page. It also imports into common 3D tools and web viewers, so you can use it elsewhere.

What does it cost to run when nobody's using it?

No GPU time at all. The GPU is billed by the second, starts when a job arrives and scales to zero when it's idle, and a failed job isn't retried automatically, so it can't quietly run up GPU time. There's no always-on server costing money in the background.

Why not run everything on one web host?

Standard web hosting doesn't provide GPUs, and 3D reconstruction needs one. So the website runs on Vercel, and only the reconstruction step runs on a GPU platform that starts on demand. It's still one codebase, so there's one thing to maintain.

Could this plug into my own website or app?

Yes, that's what I designed it for. The flow is upload photos, create a job, watch its status and show the model, and any web app can do that against the same service. Property, product or site-capture tools are the obvious places it could fit.

Will the 3D quality get better over time?

It can. The reconstruction model is one swappable piece. I set it up so newer fine-tuned weights can drop in when they're published, without rebuilding the rest of the service.

Want heavy AI behind a simple upload page?

If a model needs a GPU but your users just need a button, I'll build the split: a normal web app up front, and a GPU only while a job runs.

Related case studies

All work