Bridging the gap between mobile culling and local file management without uploading 1TB of data.
As a developer and photographer, I faced a unique bottleneck. I wanted to select my best photos while sitting on the couch using my phone, but my 50MB RAW files lived on a massive hard drive in my office. I didn't want to pay for expensive cloud culling software, and I certainly didn't want to upload terabytes of data just to select 50 images.
My solution? A Hybrid Workflow using Google Sheets as a lightweight frontend and Python as the heavy-lifting backend.
The Architecture
1. The Cloud Interface (Google Apps Script)
I utilized Google Sheets not as a spreadsheet, but as a hosting platform for a custom HTML5 Web App.
Why Sheets? It handles authentication and hosting for free.
The UI: I built a responsive, mobile-first grid using the IBM Plex Sans design system. It allows for "Start/End" range input (e.g., IMG_8100 to IMG_8500) and renders clickable tiles.
The Output: Instead of saving data to a database, it generates a "Recipe" โ a PDF file containing only the IDs of the selected photos.
2. The Local Engine (Python & Flask)
Once the "Recipe PDF" is generated, the local work begins.
The Stack: I wrapped a Python script in a Flask web server to provide a modern UI, but used Tkinter for native Windows folder dialogs (because browser file pickers are too restrictive).
The Logic:
The app parses the PDF using pypdf to extract IDs (e.g., 8104).
It scans a local source directory for matches, handling multiple file extensions (.CR2, .JPG, .NEF).
It performs a safe copy (not cut) to a destination folder.
Technical Challenges & Solutions
The "WinError 32" Lock
The Problem: On Windows, reading a PDF via Flask kept the file handle open. When I tried to move or delete the file later, the app crashed with PermissionDenied.
The Fix: I implemented a strict file.seek(0) and explicit stream closure pattern in Python to release the file handle immediately after parsing the text.
Mobile UX on Sheets
The Problem: Scrolling through 2,000 grid items on a phone was sluggish, and the interface felt like... well, a spreadsheet.
The Fix: I wrote custom CSS media queries to switch from a flexible grid to a strict 2-column layout on mobile, with increased touch targets and a sticky footer, making it feel like a native app.
The Result
This tool reduced a 2-hour workflow to 15 minutes. I can cull photos on my phone, AirDrop the PDF to my PC, and have Python extract the files instantly.
Future Plans
I am looking into packaging this as an Electron app for easier distribution and adding AI-based blur detection.
Built with ๐ by Ray Basweti. Check out the code on my Github.



Top comments (1)
This is a clever workaround for a very real pain point, nicely thought through from end to end. Using Google Sheets as a lightweight, authenticated frontend is a great example of bending familiar tools instead of overengineering ๐
The โrecipe PDFโ idea is especially clean, it keeps the cloud side dumb and the local side in control, which feels right for huge RAW libraries.
Small extra thought: if you ever take this further, adding simple batching or progress feedback on the Python side could make long copy jobs feel a lot more transparent. Overall, solid engineering and very practical.