My phone has backed up about six thousand photos and videos from 2025 alone. On my PC, I run a local browser tool — pick_yeju.py — that lets me scroll through them, pick the ones worth keeping, and copy them into my daughter’s media library on our NAS.

The files are sorted oldest-first. Six thousand of them. That’s about ninety pages at sixty per page.

The problem: every time I restarted the tool, it opened at page one. I’d have to scroll back through to wherever I’d left off the previous session. Ten, twenty, thirty pages — just to find my place again.

I wanted it to open directly to the last file I’d copied. Seems simple enough.

It took ninety minutes and fourteen attempts.


What I Was Trying to Do

The tool already knew which files had been copied — it kept a log. I just needed it to look up the most recently copied file, find it in the page list, and jump there on startup.

Straightforward. I asked my AI coding assistant to add it. First version was ready in a few minutes.

I refreshed the browser. First page.


What Kept Going Wrong

Over the next ninety minutes, here’s what I typed fourteen times, in various forms:

“Still first page.”

Each time, something different was broken.

Attempt 1–3: The feature wasn’t running at all.

The JavaScript was supposed to fetch the last-copied file ID from the server, then navigate to that page. But the fetch was being called before the file list finished loading — so by the time it tried to navigate, the page list was empty and findIndex returned -1. No error. Just nothing happened.

Attempts 4–6: Two servers were running at the same time.

I kept restarting the server to pick up code changes. But Python’s HTTP server sets allow_reuse_address = True, which means a new server can bind to the same port even if the old one is still running. I was getting the old server, which had none of the new code.

I killed both processes, restarted once, and confirmed only one was running. Refresh. Still first page.

Attempt 7: The file count dropped from 5,684 to 144.

While I was debugging, the tool’s background scan ran and came back with far fewer files than before. It saved this to disk cache. I deleted the cache to force a full rescan — but now startup was slow again (scanning six thousand files over a network share takes a while). I also added a safety check: if the fresh scan returns less than 80% of the previous count, ignore it and keep the old cache.

Attempts 8–10: Debug messages weren’t appearing.

I added a pop-up notification to show whether the feature was finding anything. It never appeared. Eventually I realized the browser was still showing the old cached HTML from before the server restart. Hard refresh fixed that. The debug message appeared — but it showed the feature was working correctly. The file ID was found. The page was calculated. Yet still: first page.

Attempts 11–12: The async timing issue.

The real problem: the file list loaded from the server asynchronously. The JavaScript tried to navigate after the list loaded. But “after” was fuzzy — sometimes the navigation code ran before filtered was actually populated. It worked in testing (the server was fast) but broke inconsistently on page load.

The fix was to stop using a fetch call at all. Instead of the browser asking the server “which file was last copied?” after load, I had the server embed the answer directly into the HTML when it served the page. No async, no timing, no race condition. The page arrives already knowing where to go.

Attempt 13: A renamed file broke the matching logic.

My fallback — for when there’s no saved log yet — was to scan the destination folder for the most recently modified file, then match its filename stem against the source list. Simple enough, except one of the files in the destination had been renamed. I’d given it a personal title by hand months ago — something like “Mom loves her daughter.”

That file had no match in the source folder (where everything is still named 20250518_201918.mp4). The stem matching failed silently. The server embedded an empty list. The page went to page one.

The fix: only consider files whose names start with eight digits — the camera’s automatic naming format. Renamed files get skipped.

Attempt 14: It worked.

“Yes, it finally moved there.”

11:54 AM. About ninety minutes after I’d started.


What It Does Now

When I restart the tool and refresh the browser, it opens directly to the page containing the last file I copied. That file is pre-selected — highlighted in pink, checkbox ticked.

If I’ve been working in a session and already know where I am, I ignore it. If I’m picking up after a break, I’m exactly where I left off.


Why Bother

The short answer: my wife doesn’t want to scroll through ninety pages.

She’s the one who will eventually use this tool to curate our daughter’s growth records. She has the memories; I have the time to build the tools. The goal is that she can sit down, pick what she wants to keep, and not feel like she’s operating a database.

Getting “resume from where you left off” right is part of that. It’s not a flashy feature. It’s the kind of thing that matters when you’re doing tedious work and don’t want the computer making it harder.


The Cost

No money. I use Claude Code on a flat monthly subscription, so there’s no per-session API cost — this ninety-minute debugging session cost the same as a two-minute one. $0 on top of what I already pay.

The main cost was patience. Fourteen “still first page” messages over ninety minutes.

Worth it.