Latch

Customise

Customise your experience

Everything adjustable lives on one Settings page — the clock, the stamps, each module's rules and editors — plus a handful of environment variables for the instance itself.

On this page

/settings is the one place every rule and every editor lives. The play pages stay clean and carry a ⚙ that jumps to the right section. Each section here has a 📖 back to this page.

Clock

Hygiene

When the cage comes off to be cleaned. The dashboard's 🛁 card does it in one tap: out, then 🔐 Locked back up.

A Handler can dictate it. Grant your AI Handler or a pack's Handler Schedule maintenance on Consent and they can set the slots and the maintenance window (10–60 min, at most 6 slots, once a day by default). The section here says who set them. They can never change the emergency window or refuse one. Saving the section takes the schedule back, and so does revoking the grant or the safeword, which stops further changes.

The clock stops while you are out, like a freeze: you serve those minutes later. And the window is not locked time. Total and longest lock, the weekly bars, share and stamp figures, the badges built on them and the cage's worn hours all leave it out. A finish logged inside a window is not a caged one.

If the window runs out before you relock, the clock starts again. It never waits forever. The window stays open, though, because the app does not know the cage is back on. The card asks locked back up?, and ⏱ relocked earlier? lets you say when it really happened.

Stamps

There is no theme setting for share cards any more (0.14 retired the old Share card: theme, which nothing ever read). The look a card starts in — theme, layout, stats, post style — is a preset, kept and chosen on the Share page itself.

A token that has no value at that moment (a session token on a photo taken while unlocked, a rate on a one-day-old log, a window token on a card that has no window) is simply dropped, so a list can be generous.

Token reference

Group Token Prints
moment date_long · time_hm · datetime_full · weekday when the photo was taken
moment place where the photo was taken, coarse — opt-in: never in a default list, never in post text, and only on a surface that carries the photo
session status LOCKED / FROZEN / TIME SERVED / UNLOCKED at that moment
session time_locked · time_locked_d elapsed in the lock (short / with days)
session day_n · day_n_cal day N of the lock (by 24 h / by calendar day)
session time_remaining · pct_served to go · percent served
session base_seconds the sentence — hidden while a hidden lock runs
session adjust_seconds · frozen_seconds net adjustments · time frozen
session session_id · session_task lock number · the task this photo verified — or, for an answer to a challenge, its word (proof · OTTER 47)
session sess_tasks · sess_spins · sess_photos · sess_xp counts inside this lock
lifetime total_locked · sessions_n · longest_lock lifetime locked · locks · longest
lifetime tasks_verified · tasks_failed training done / failed
lifetime reflections_n · checkins_n · spins_n · photos_n counts
lifetime time_added · time_removed totals
streak streak_current · streak_best days
rate tasks_per_week · task_fails_per_week · spins_per_week · locks_per_week per week
rate reflect_days_per_week · checkin_days_per_week · reflect_compliance days per week · % of locked days reflected
rate locked_hours_per_week · locked_pct_28d hours per week · % of the last 28 days
game level · rank · xp as of that moment
game standing your Mischief standing word at that moment — 🐾 Good boy · 👀 Watched · 🦮 Short leash · 🏠 In the doghouse — opt-in: in no default list; never the marks, their kinds or counts; nothing while Mischief is off
window win_days · win_locked · win_locked_pct the span · locked in it · % of it
window win_active_days · win_sessions days with something logged · locks begun
window win_tasks · win_task_fails · win_spins counts inside the span
window win_photos · win_reflections · win_checkins · win_badges counts inside the span
window win_xp · win_added · win_removed xp earned · time added · time removed
event event_name · event_day the event you were in — LOCKTOBER · LOCKTOBER · DAY 12/31
event event_photo_days days of the event so far with a check-in or verification photo, over the day — 12/12 is every day

Every value is computed as of the photo's timestamp — see the overlay is as-of the shutter.

The window group is the exception, and the only one that reads two moments: it counts what happened between them. Those tokens only mean anything on a week share card, so everywhere else they say nothing and are left out — the same treatment as a stat that has no value yet, rather than a zero that would claim a quiet week.

The event group says nothing outside an event you joined. Like everything else it is as of the photo: a photo from day 12 says DAY 12 however long after it is exported, and event_photo_days counts local calendar days, so a 23:30 photo and a 00:30 photo are two days.

Every id in this table (except place) also works as a {field} in a share card's post text — see Share cards.

Activities

An activity is a thing you want to count — reflections, sits, walkies, anything. Latch ships with a starter set and you can add your own at the bottom of Settings.

The important part: an activity selects events you already have. It is a lens over your log, not a second log. Add one today and it is filled in from your whole history immediately — and removing one deletes nothing, because it never owned any of those events in the first place.

Each activity has:

Tracking something Latch already does? Put that module's kind in match kind and untick one-tap button. Tracking something of your own? Leave match module as activity, set match kind to your slug, tick one-tap button, and set time from to habit if minutes matter — or just add it from the Habits page, which fills those in for you.

The five stats every activity gets

Saving an activity adds five ids to the token lists above, with no restart:

id prints absent when
since_<slug> how long since the last one it has never happened — never 0s, which would read as just now
days_<slug> days you have done it — (a genuine 0 is printed)
streak_<slug> the current run its cadence is none
total_<slug> time spent doing it it declares no time from
count_<slug> how many altogether —

So a new activity is shareable the moment it exists: put streak_walkies in the share-card list and it appears. The full list of ids your instance has right now is at the bottom of the Activities section in Settings.

Handler

The name, the reflection minimums, the check-in cadence, the missed-day penalty, and the whole prompt library. Full detail on The Handler. Three presets, if you want a starting point:

Gentle Firm (default) Strict
Minimum reflection 60 chars 120 300
Check-in every 8 h 4 h 2 h
Missed-reflection penalty 0 min 30 120
Minimum spoken reflection 15 s 30 60

Then rewrite the prompts in the voice you want. The seeded lines are firm but clean; the library is where the Handler's personality lives.

Wheel

The cooldown (minutes; 0 while testing) and the segment table — label, weight, effect, value, colour, enabled. See Wheel of Fortune.

Training

The default deadline for a task that has none (hours, default 24) and the task library — rewards, penalties, XP, photo required, per-task deadline, enabled. See Training.

Display name and other instance settings

These are environment variables on the container, not fields on the page:

Variable Meaning Default
LATCH_APP_NAME the name in the header, the tab title, the footer Latch
LATCH_TZ the timezone every date is shown in and every when is typed in (events are stored as UTC epochs) America/Detroit
LATCH_API_TOKEN the bearer token for /api/v1. Empty means the API is off. (empty)
LATCH_TICK_SECONDS how often the scheduler sweeps freezes and deadlines 30
LATCH_DATA_DIR where the database and media live /data in the container
LATCH_DOCS_DIR where this guide's markdown lives /app/docs in the container
LATCH_ALLOWED_HOSTS the names this box answers to besides IP addresses and localhost — see the names it answers to (empty)
LATCH_WORKERS whether background workers may start (later features — pack sync, the AI Handler — run in them). 0 = none; the test suite runs with 0 1

Set them in .env next to docker-compose.yml and recreate the container. Renaming the app is a one-line change: LATCH_APP_NAME=Kennel.

Themes

There is one look — dark, game-like, no build pipeline. app/latch/web/static/style.css is a single file with CSS variables at the top (--accent, --accent2, --cyan, --bg) if you want to fork the palette. A theme system and a curated gallery look are on the roadmap.


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.