Latch

Playing

Photos, stamps and recap cards

The gallery, the five stamped-overlay layouts, the session recap card, what the overlay says (and when it says it), and what is stripped on the way out.

On this page

Every photo you put into Latch โ€” a check-in, a verification shot for training โ€” lands in one content-addressed store under your data folder and shows in the Gallery. Voice memos live in the same store but are not gallery tiles: audio has no pixels.

/gallery shows every photo, newest first, with the task it verified if it was one. Each tile has a stamp-layout picker, a download of the stamped version, and a ๐Ÿ“ค share button.

Stamped photos

A stamped photo is your picture with an overlay of stats, re-encoded as a fresh JPEG. Five layouts, plus auto, which picks by aspect ratio:

Layout Name in the app Shape
bar Hairline one thin line of facts along an edge
hero Collar a bold band with the headline number
badge Tag a compact corner tag
dossier Case File a grid of labelled values
rail Strip a footer strip, suits wide photos

Sizes: 1080, 1600 (default) or 2048 px on the long edge. The default layout and which stats appear are yours to set โ€” see Customise โ†’ Stamps for the full token list (streak, day N, time locked, tasks per week, rank, and about forty others).

The overlay is as-of the shutter

Every value on a stamped photo is computed from the log at the photo's timestamp: the clock as it stood, the streak as it was, the training count up to that moment. A photo from three weeks ago does not wear today's streak. One deliberate exception: an event undone after the photo was taken still appears on that photo's overlay โ€” otherwise every undo would silently recaption every picture already in your gallery.

EXIF and GPS are stripped by construction. The stamped file is rendered from pixels and saved as a new JPEG; there is no metadata to copy. The original stays in your store untouched.

Hidden timer: while a hidden lock is running, no overlay prints the sentence or the time remaining โ€” either one plus the start time would give the end away. Once the lock ends, they return.

Recap cards

Every finished (or in-progress) session has a recap card at /session/<id>/recap.jpg, linked from the Last lock card and the Sessions list. Two shapes: story (1080 ร— 1920, for a phone screen) and square. The card shows the verdict (clean / early / in progress), the headline time, a grid of stats, your rank and level, and a strip of the session's photos.

Which stats sit in the grid is a token list (Settings โ†’ Stamps โ†’ Session recap card). The session's private note is not printed unless you add ?note=1 to the URL โ€” private prose on a share object has to be opt-in.

Share cards

A recap card is about one finished lock. A share card is whatever you point it at โ€” at Share in the nav, or /share.

Pick a kind, a theme, a shape, and optionally a photo; then download it or hand it to the share sheet. Every choice lives in the link, so the picture you are looking at and the file you download are the same URL.

Three kinds

Is about Its clock
Right now the live state โ€” locked or not, how long, the streak this moment
The last stretch a span: 7, 14, 30 or 90 days, and what happened in it the two ends of the span
One badge one thing you earned, and where things stood then the badge's own moment

The last stretch prints the span's actual dates rather than calling itself "this week". That is deliberate: a card headed THIS WEEK on a Wednesday is a claim about three days wearing the name of a week, which is the same thing badges refuse to do when they wait for a month to end before deciding its winner.

One badge is a record, not a snapshot with a trophy on it. Every number on it is as it stood when the badge was earned โ€” so a card about something you did in August shows August's streak, not today's. The date in the corner is that moment, and the whole card agrees with it. It appears as an option once you have earned a badge.

Themes

Seven palettes, and six of them are the badge metals: Steel, Moss, Sapphire, Amethyst and Gold are the five rarities the badge art uses, and Plate is the cream plate a badge sits on. Midnight is the app's own colours โ€” what every card looked like before themes existed, and still the default.

Badges drawn on a card wear their own metal, so a legendary badge is gold on any theme.

Stats

The grid holds six (three if the card carries a photo, three on the wide shape). The Share page can add, remove and reorder them for one card without changing any setting โ€” the choice travels in the link. To change what a card starts with, edit the token lists in Settings โ†’ Stamps & recap.

A stat with nothing to say at this moment is left out rather than printed as a zero, so the card lays out what resolved, never what you asked for.

What fills the lower half

Never nothing. In order: the photo if you picked one, then the badges โ€” the ones earned in the span on a week card, the rest of your collection on a milestone card, or all of them on a right now card if you ask โ€” and otherwise the events that moved the clock most, which is the same log the numbers above it come from.

A badge's icon is never printed, because the icons are emoji and the card's font has no emoji in it. A badge is drawn instead โ€” the same hexagon-and-metal-ring shape the badge art uses.

The card has two moments in it, and says so

This is the one thing worth understanding about a share card that carries a photograph. The stats describe the card's own moment. The photograph describes whenever its shutter fired โ€” possibly weeks ago. So the card keeps them visibly apart rather than blending them:

The caption is not optional, and it lives inside the image rather than in the card's margin โ€” a card gets cropped, re-shared and screenshotted, and a date that lives in the surrounding chrome survives none of that.

Why a milestone card takes no photograph

Its numbers are already as-of the day the badge was earned. Adding a picture would put a third moment on one card โ€” the badge's, the shutter's, and the reader's assumption that a card they were just handed is about today. Two is already the most anyone can keep straight, so that kind refuses a photo and says so on the page.

Location on photos

Latch can record roughly where a photo was taken and print it on a card or a stamped export. Two separate switches, because they are two different decisions:

Setting Default
Record a coarse location with new photos photo.place_capture on
Print it on an image nothing โ€” every export asks explicitly off

The rounding happens when the photo is saved, not when it is printed. The exact coordinate is never written to disk, so it is not in the database, not in your backups and not in the export bundle โ€” and a card cannot be sharpened back later, by you or by anyone who gets a copy of your data.

How coarse is photo.place_dp:

Grid Reads as
0 ~111 km region
1 ~11 km city
2 ~1.1 km neighbourhood โ€” the default
3 ~110 m street

Where it comes from, in order:

  1. The photo's own EXIF โ€” what the camera recorded, so it stays correct however late you log the photo.
  2. Your browser, but only for a photo you are logging now. A photo backdated to last Tuesday will not take today's position: that would put where you are standing onto a picture taken somewhere else.
  3. A label you type ("the park", "hotel, Chicago"). A typed label replaces the coordinate entirely rather than appearing next to it.

A photo whose camera recorded nothing simply has no location, and the Share page says so instead of offering a switch that would do nothing.

What rounding does and does not buy you

A 1 km cell is a neighbourhood, not a doorway. But the grid is fixed, so every photo taken at home lands in the same cell โ€” and over a long log, the cell you appear in most is home, to within a kilometre. Coarsening limits the blast radius of one image; it is not a disguise. If that matters for a particular card, use a typed label, or leave the location off.

Sharing

The ๐Ÿ“ค button uses the phone's share sheet (the Web Share API). It needs a secure origin โ€” https://, through your reverse proxy โ€” and a browser that supports it. Anywhere else it downloads the JPEG instead. Nothing in Latch posts anywhere; sharing is you handing a file to another app.

Limits and formats

Picking one

Two doors, deliberately different:

That the thumbnail is of the uploaded file matters more than it sounds: a HEIC is converted and a clip becomes a single frame before anything is sent, and the preview shows the result of that, not the thing you tapped. If a preview appears with no picture in it, the file is being sent as-is because this browser could not decode it โ€” the line underneath says so, and the server's refusal will name the real format.

Where the bytes are

<data dir>/media/YYYY/MM/<sha256>.<ext> with thumbnails under media/thumbs/. The export bundle carries originals and thumbnails (Export). Media is not in the SQLite file, so a database-only backup is not a full backup.


This page also ships inside the app, at /guide โ€” so your own instance always serves the guide for the version you are running, with the internet unplugged. Get Latch ยท Something wrong here? Tell me.