Stamps — Domain Spec¶
A stamp is curated artwork for a place, earned by genuine visits.
Every stamp carries a guide — a curated list of entries (landmarks,
cities, regions, or countries depending on scope). Visit minimum_visits
of them and the stamp lands in the user's Passport.
Mental model¶
Stamps are exclusively about places — never about activity volume, social actions, or recurrence (those belong to challenges + curios).
One earn shape across all stamps: "visit X of Y guide entries." What
"an entry" is depends on the stamp's scope.
Scope → entry shape¶
| Scope | Guide entries are… | A visit satisfies an entry when… |
|---|---|---|
landmark |
A single location_id (the iconic place itself) |
travel_log.location_id matches |
district |
location_id list (landmarks within the district) |
location_id matches |
city |
location_id list (landmarks within the city) |
location_id matches |
region |
Mix of city and/or region entries |
travel_log.city or travel_log.region matches |
country |
Mix of region and/or city entries |
travel_log.region or travel_log.city matches |
multi_country |
country entries (ISO-2 codes) |
travel_log.country matches |
A region stamp like "Tuscany Highlights" can list specific cities (Florence, Siena, Lucca) AND broader regions (Tuscany) — visiting any place in Florence satisfies the Florence entry; visiting any place in Tuscany satisfies the Tuscany entry. Country stamps for, say, France can mix region entries (Île-de-France, Provence) with city entries (Lyon, Marseille).
Guide content¶
Each entry is also user-facing content. On the stamp's detail screen, the guide renders as a card list — a small travel guide:
StampGuideEntry
├── title — "Pike Place Market" / "Florence" / "Tuscany" / "Japan"
├── description — short blurb / why it matters
├── photo_key — REQUIRED for every entry; surfaces the visual hook
├── recommendations — optional tips (what to do, when to go)
└── sort_order — admin-controlled ordering in the guide
Pre-earn: the guide is a discovery surface — places worth visiting. Post-earn: shows which entries you satisfied and which you skipped.
Minimum visits¶
minimum_visits defaults to the total entry count at admin save time — "visit all" is the default. Admin can lower it to make an "X of Y" stamp (e.g., a 12-temple guide where visiting any 5 earns the stamp).
Lifecycle¶
| Phase | Entered when | Exit |
|---|---|---|
draft |
Admin saves | Admin publishes |
published |
Admin publishes | Admin archives |
archived |
Admin archives | (terminal) |
Stamps don't have time-bounded windows like challenges — they're always-on once published.
Earn flow¶
The engine's stampResolver runs on every TravelLogRecorded signal. For the row's geography, it queries candidate stamps (published + not already earned by the user + at least one guide entry that this row's geography matches). For each candidate, it determines which entries the row satisfies, appends new entry IDs to user_stamp_progress.matched_ids, bumps current_count. When current_count >= minimum_visits, sets earned_at.
matched_ids tracks satisfied entries, not raw location IDs. Revisiting a place that satisfies an already-matched entry is a no-op.
Retroactive evaluation on stamp publish (so users with qualifying prior visits earn the stamp on publish day) is admin-triggered; see the Retroactive replay section below.
Retroactive replay¶
Admin can trigger retroactive evaluation on a published stamp. All stamps are eligible (no opt-in or cadence). The engine walks every user's historical travel-log rows that match any of the stamp's guide entries and credits matches accordingly. Idempotent — re-running is safe because matched_ids dedup prevents double-counts. Auto-enqueue on publish is off; admin clicks Replay explicitly.
What stamps don't do¶
- No rule trees — fixed guide-entry semantics
- No opt-in — a published stamp evaluates passively for every user
- No reward chain — a stamp doesn't grant a curio; the stamp IS the reward
- No time-bounded expiry — stamps live forever once published
See also¶
- Stamps narrative
- Content service: the curated stamp + guide catalog
- Passport — where earned stamps live
- Game Engine service — resolver internals