LightPhotos

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.

Keep data in Then
WHERE THE DATA IS ~/Library/ Nothing from LightPhotos. /Volumes/Drive/Iceland/ IMG_4471.jpg .lightphotos/ IMG_4471.jpg.xmp ratings, edits, one thumbnail per photo RESULT Ratings and edits They move with the folder. The app needs no extra code. Thumbnails They move too. On another computer, the grid fills instantly.

You moved the folder to an external drive. Your work went with it.

Pick where the app keeps your data. Then pick what you do with the folder.

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:

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:

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.