โ How it works ๐ผ Screenshots
01 Overview
PhotoDrop is a small utility that solves an everyday clinic annoyance: getting a good intraoral or clinical photo off a cell phone and onto the operatory computer's imaging system without cables, an email round-trip, or a cloud account. Run one Python file on the PC โ it starts a local web server and opens a dashboard showing a QR code. Scan it from a phone on the same WiFi, tap-select photos, and they upload straight into a folder the imaging software watches. It also doubles as the intake front door for the SmileVision and dental-narrative apps.
The whole thing is a single Python file: the entire responsive web UI โ both desktop and mobile modes โ is embedded as one string in the source and renders with no internet, its one small dependency (segno) generating the pairing QR locally instead of calling a web service. A per-session access token rides inside that QR, so only a device that scanned this screen can reach the gallery or upload.
Desktop dashboard
A QR pairing card, a photos-received counter with the save path, and a live gallery that re-renders as new photos arrive.
Mobile uploader
The same page in its mobile branch: a tap-to-select dropzone, multi-file upload with per-file progress, and a "sent N photos" confirmation.
02 Why I built it
In practice, the phone is often the best camera in the room โ but there's no friction-free way to move a photo from it onto the operatory PC's imaging system. Cables get lost, email adds a cloud hop and a compression step, and installed transfer apps are one more thing to manage on shared clinic hardware. I wanted the shortest possible path: point the phone at a QR on the screen, pick the photos, and have them appear in a folder the X-ray software can already import. Keeping it a single self-contained file was part of the point โ it should be close to double-click-and-go on any clinic machine, work with no internet, and the images should never leave the local network.
03 What I built & how it works
One process, one file: an HTTP server on the PC and a single page that renders two different UIs โ one per device.
Fig. 1 โ the desktop and mobile experiences are the same page, which reads a ?mode= query parameter to render the right UI on each device. The upload sends the raw file body with the name in the query string, sidestepping multipart parsing.
- Start โ run the single file; it autodetects the LAN IP (a connectionless UDP-route trick, no traffic sent), binds the server, and auto-opens the desktop dashboard with a QR of its own URL.
- Pair โ scan the QR on the clinic screen; the phone loads the same page's mobile branch on the same LAN.
- Select โ tap-pick one or more photos; each POSTs its raw bytes with the filename in the query string.
- Land โ the PC writes them into
dropped_photos/, sanitizing the name and suffixing a timestamp on collisions. - Import โ the desktop gallery re-renders within about two seconds, and the imaging software picks the files up from the folder.
04 ๐ Skills & tech used
05 Notable challenges & decisions
Raw bytes instead of multipart
The stdlib http.server has no multipart parser, so rather than pull one in, the client POSTs the raw file body with the filename in the query string. The server writes the bytes straight to disk after an os.path.basename sanitize and a timestamp suffix on name collisions โ a deliberately small protocol that kept file handling on the standard library.
Three templating syntaxes in one string
The whole UI lives as one embedded string, which is convenient until placeholders collide. The one recorded bugfix: a ${UPLOAD_DIR} token looked like a JavaScript template literal but sat inside a Python string served verbatim, so it rendered literally. The fix was a {{UPLOAD_DIR}} placeholder injected server-side with .replace() โ a reminder that Python, JS, and mustache-style tokens all coexist inside that one string.
A single blocking server, on purpose
It uses one blocking TCP server with no threading โ fine for a single uploader on a LAN, where large simultaneous uploads would simply serialize. Keeping it single-threaded kept the whole tool readable in one file.
Hardened for clinical use. The first pass leaned on the open internet โ it pulled its UI (CSS, icons, a font) and even the pairing QR from third-party CDNs, and ran over plain HTTP with no authentication, so anyone on the network could upload or browse the received folder. Fine for a personal utility, not for anything near patient data. The shipped version closes all of that: the UI is inlined and the QR is generated locally, so it makes no third-party calls and works with no internet; a per-session access token gates every page and data request; and a built-in --https mode serves it over TLS. Same tool and the same flow โ just self-contained and access-controlled.
06 Results
Sources: the single photodrop_secure.py file and its on-disk dropped_photos/ folder.
07 Screenshots
PhotoDrop is a LAN tool by design: open it on the clinic PC, scan the QR with a phone on the same Wi-Fi, and the photos you pick land in the desktop gallery within about two seconds. The captures below are from the shipped, self-contained version โ the desktop dashboard just after a few clinical photos have arrived, and the phone's uploader.
08 Honest status
PhotoDrop was built with an LLM in January 2026 and verified working end to end โ the server starts, serves the desktop and mobile pages, requires the access token on every page and data request, and accepts, lists, and serves an upload back. It is a single-file personal utility, not a deployed product: no git history, and it has only been exercised on a couple of machines. The offline UI, locally-generated QR, per-session access token, and optional self-signed TLS cover the basics for a trusted operatory LAN โ but the TLS is self-signed rather than CA-trusted, so a fully warning-free, audited clinical deployment would still want a proper certificate and a security review. As it stands, it does one small thing well: getting phone photos onto the operatory PC with as little friction as possible, without them ever leaving the local network.
PhotoDrop โ Run Guide
A zero-cable LAN photo-transfer tool. Run it on the computer you want photos on; it shows a QR code; a phone on the same Wi-Fi scans it and taps to upload photos, which land in a local folder and appear in a live desktop gallery. It is self-contained and access-controlled: the interface is inlined (no CDN), the QR is generated locally, and a per-session token gates every page and data request.
Clinical use case: capture high-quality intraoral/clinical photos on a phone and get them onto the operatory computer's imaging folder with no cables, no email, no app โ the photos land in a local directory the imaging software can import, and nothing leaves the local network.
Status: โ Verified โ the whole server-side flow was exercised end-to-end: the server starts, serves the desktop and mobile pages, refuses page and data requests without the access token (403), accepts a raw-binary upload (
POST /api/uploadโSuccess), lists it (/api/list), and serves the image back (HTTP 200) โ with a locally-generated QR and zero CDN refs confirmed. The one part that can't be automated is the physical phone QR-scan โ that's a manual check.Sensitive data: none. No secrets, no accounts, no config. Uploaded photos land in a local
./dropped_photos/next to the script.
What it is
A single ~330-line Python file (photodrop_secure.py) โ Python standard library plus one small
pure-Python dependency, segno, used to generate the pairing QR locally. The entire responsive web
UI (desktop + mobile) is embedded as a string, with hand-written CSS and emoji icons, so it renders
with no internet. It auto-detects the machine's LAN IP, serves on port 8000, and opens the
desktop view in your browser. Every request carries a per-session access token (it rides inside the
QR); a request without it gets a 403.
Prerequisites
Python 3.8+ and one small package:
pip install segno
(New machine? Install Python per ../SETUP.md.) No virtualenv or Docker needed.
Run it โ this is the whole recipe
python photodrop_secure.py # add --https for TLS (see Encryption below)
It prints the Desktop URL (which carries the access token), opens your browser to it, and shows a
QR code. On your phone (same Wi-Fi): scan the QR โ Tap to Select Photos โ they upload and appear in
the desktop gallery, saved to ./dropped_photos/. Ctrl-C to stop.
- Pin a fixed token instead of a random per-session one:
PHOTODROP_TOKEN=some-token python photodrop_secure.py. - Change the port with
--port 9000; change the save folder by editingUPLOAD_DIRat the top of the file.
Why there's no prebuilt-image / Docker tier
Deliberately omitted โ it would add friction for zero benefit ("if it isn't needed, don't include
it"). PhotoDrop must present the host's LAN IP and be reachable from phones on the LAN, so a
container would need host networking and still gain nothing over python photodrop_secure.py. One
file, one command is the distribution.
Verify
pip install segno
PHOTODROP_TOKEN=testtok python photodrop_secure.py & # start it; token pinned for this check
curl -s "http://localhost:8000/?token=testtok" | grep PhotoDrop # desktop page
curl -s "http://localhost:8000/?mode=mobile&token=testtok" | grep "Tap to" # mobile upload page
curl -s -o /dev/null -w '%{http_code}\n' http://localhost:8000/ # โ 403 (no token = denied)
curl -s -X POST "http://localhost:8000/api/upload?name=t.png&token=testtok" --data-binary @some.png # โ Success
curl -s "http://localhost:8000/api/list?token=testtok" # โ the file appears
Then the real acceptance test: open the desktop page, scan the QR with a phone, and upload a photo.
Encryption โ --https (built in)
The token blocks other devices, but plain HTTP means someone sniffing the same Wi-Fi could still capture the token/photos. There is a built-in self-signed TLS mode:
pip install cryptography # (or just have `openssl` on PATH) โ used to generate the cert
python photodrop_secure.py --https # auto-creates cert.pem/key.pem, serves over https://
On first run it generates a self-signed cert for your LAN IP (reused afterward), wraps the socket with
stdlib ssl, and the QR switches to https://. Real encryption โ the one cost is a one-time
"not private" warning on the phone (self-signed isn't CA-trusted); tap through. Bring your own cert
with --cert / --key.
Warning-free alternative: use mkcert / your own CA to issue a cert for the LAN IP and install the
CA root on each device once โ green-lock HTTPS, no warnings, but per-device setup. A public CA
(Let's Encrypt) is impractical for a bare LAN IP (needs a public domain name).
Caveats & clinical notes
- Plain HTTP unless you pass
--https. The access token stops other devices on the Wi-Fi from viewing or uploading, but without TLS a determined sniffer on the same network could still capture traffic. Use--httpsfor anything sensitive. - Self-signed TLS is real encryption but not CA-trusted โ expect a one-time "not private" warning on the phone (or install your own CA root; see above).
- Single-machine, single-uploader scope. One blocking server; it's a personal utility, not an audited product.
- Port 8000 must be free (
--portto change).
Earlier version
The repo also keeps photodrop.py โ the original quick pass. Same tool, same flow, but it loaded its UI
(Tailwind, icons, a font) and the QR image from CDNs (so it needed internet and sent the LAN URL to a
third party) and ran open over HTTP with no token. photodrop_secure.py supersedes it; run the
secure one โ photodrop.py is kept only for reference.
Provenance
No datasets, no model, no training, no external accounts, no secrets โ a self-contained stdlib script
plus one small pure-python dependency (segno, for the offline QR). Built with an LLM, Jan 2026.