Your images and compositions, kept with your account. Open any of them in the editor.

Catalogue

The catalogue is where Photo Slop keeps what a signed-in user has made: the images they dropped into the editor, the renders they saved from it, and whole compositions ("projects") that can be opened again. It lives at /catalog and needs an account; signed-out visitors are shown the sign-in card.

What is kept

original file is stored (converted to PNG or JPEG for the browser when it arrived as TIFF, HEIC or another format a browser cannot show), with a thumbnail for the catalogue grid.

with "Keep in my catalogue" ticked) stores the PNG render AND the document JSON (the photo-canvas/1 document: artboard size, every layer with its position, text, effects and crop), the way an .excalidraw file travels beside its PNG. Download gives you the image; Open in editor loads the document so you pick up exactly where you left off (/editor?project=<id>).

dest: catalog and no document). It can be placed on the current canvas with /editor?add=<id>, as can an upload.

Anonymous visitors can still use the editor; nothing they make is kept between visits, and their uploads go to a shared, uncatalogued prefix.

Where it lives, and who can read it

Each user's files are stored under one key prefix in the asset backend, users/<owner-id>/…, together with a small index file that lists the items. The backend is whatever PHOTO_STORAGE_BACKEND selects — a local directory or a Cloudflare R2 bucket in production — so the catalogue needs no database.

Access is decided per file. A request for a key under users/<owner>/ is served only when the request's signed-in user is that owner; anyone else receives 404, so the existence of a file is not disclosed even to someone who guesses its URL. The identity comes from Clerk (dash-clerk-auth) and is read on the server for every request; the browser is never asked who it is. When the R2 backend is configured without a public domain (R2_PUBLIC_BASE unset) the app answers a file request with a short-lived signed URL after the ownership check; with a public domain set, bucket URLs are reachable by anyone who has them, so leave it unset for private catalogues.

The API behind the page

The page is a thin view over a small JSON API, also used by the editor's Catalogue tab:

document field for a project). From the editor that is the export.render command with {"dest": "catalog", "name": "…", "project": true}.

Every endpoint answers 401 to a request with no signed-in user.

Limits

A catalogue holds up to 2000 items. The index is one file per user and is written last-writer-wins, so saving from two tabs in the same instant can lose one entry. Deleting an item deletes its files.

Note for AI agents: This is the static, prerendered view of an interactive Dash application served because we detected a non-JS user agent. Full prose docs: