Your data lives where you are allowed to write
Why ratings, edits and thumbnails sit in a folder next to your photos instead of in a database, and how the permission rules of a browser made that decision for me.
Update, October 13, 2026: LightPhotos now has catalogs, named lists of folders. Everything below still holds: a catalog keeps only a copy of ratings, flags and labels, and your work stays next to your photos.
You moved the folder to an external drive. Your work went with it.
LightPhotos has no database. When you give a photo four stars, the app
writes a small JSON file called IMG_4471.jpg.xmp into a
hidden .lightphotos folder, next to
IMG_4471.jpg. That is the whole system for saving your work. Two problems pushed me
into this design.
My first attempt
I started with one catalog for the whole app, in the usual folder where
Mac apps keep their data. It recorded each photo by its full
path on disk. This fails in exactly the way people use a photo tool,
because people move folders. You import a card into ~/Desktop/import and
cull for an hour. Then you drag the folder to an external drive, and
every path in the catalog points to nothing.
Putting it next to the photos
Now your ratings and edits move when you move the folder, copy it to a friend or back it up. I did not write any code for that. Some details:
- The app makes the folder only when you save something. If you only look through someone else's photos, the app leaves nothing behind.
- The app writes each file to a temporary copy, then renames it. On all common disk formats, a rename is atomic: it happens in one step. So if the app crashes partway through, you keep the previous version, not a half-written file.
- The app never changes your original photo. This app is for deciding which photos to keep. So it must not change them.
Then the browser made the decision for me
Thumbnails take time to make, so the app saves them to disk. On the
Mac, that cache lived in ~/Library/Caches, where Apple
tells you to put it. Then I made the app run in a browser tab. A tab can
read and write only inside the folder you picked. With the cache
anywhere else, the browser version would rebuild every thumbnail each
time you opened the page.
So I moved the thumbnail cache into .lightphotos. The old
cache worked and nobody complained, so I would never have found
this design on my own. But the result was better on the Mac too.
When you plug the drive into another computer, the grid fills
instantly. The app does not spend a minute rebuilding every thumbnail.
The lesson: design for the strictest platform early.
The Mac and browser versions share one cache, and that needed one deliberate compromise. The app recognises a cached thumbnail by the file size of the photo and the time it was last changed. A browser gives that time only to the millisecond, and the Mac gives it to the nanosecond. So the app rounds to the millisecond. Without the rounding, the two versions would label the same untouched photo differently and never find each other's thumbnails.
There is one cached thumbnail per photo. So the cache of a folder can never have more entries than the folder has photos, and I need no eviction rules. When a folder opens, I only remove leftovers for deleted photos. If the app cannot write to a folder, it makes fresh thumbnails every time and does not bother you about it. It is a little slower there, and I decided that was not worth an error message.
What it cost me
The app keys everything by the filename of the photo alone, because the location of the file already gives the folder. This makes work across folders risky. If you switch folders while a background job runs, a late result could be saved against a photo with the same name in the new folder. I wrote that warning on the code that handles those results. You can change folders at any time. This is what happens to each job:
- Exports keep running. Each export knows the full location of the photo and its edits, so it finishes no matter which folder is open.
- The app saves your current edits first. If you moved a slider and did not leave the photo yet, I save that change before the new folder opens.
- Thumbnails keep running, and the app drops late results. If a result for the old folder finishes after you leave it, the app drops it, so it cannot land on a photo with the same name.
- Auto Adjust stops. Photos that it already finished keep their changes. The app skips the rest.
- Bulk delete stops. It finishes the photo that it is moving to the trash at that moment, then stops.
I plan to fix those last two. Each job would carry the full location of its photo, as exports do, so the open folder would no longer matter when the job finishes. Then you would not wait for Auto Adjust on a big shoot before you look at another folder.
There is also no quick search across every folder you ever opened. "Show me everything I rated five stars this year" means a visit to each folder. A central database could answer that in a millisecond. If that kind of search was central to LightPhotos, this would be the wrong design.
The cost that worries me most is renaming. The sidecar file finds its
photo only by filename. Rename IMG_4471.jpg to
iceland-sunset.jpg in Finder, and the sidecar is still
IMG_4471.jpg.xmp. LightPhotos no longer knows that the two
files belong together, so your rating and edits seem to disappear.
Renaming is normal, so this design is fragile.
I have not fixed this yet, but I know how. Each sidecar would also store a fingerprint (a hash) that the app calculates from the contents of the photo. When a folder has sidecars that match no photo, the app would calculate the fingerprints of the photos in that folder. If one matches, the photo was only renamed, so the app renames the sidecar to match its new name, and your ratings and edits come back.