Developer journal
On This Day, Then & Now, and Passport Stamps
On This Day, Then & Now, and Passport Stamps use different techniques—calendar joins, spatial bucketing, and OCR—but follow the same rule: find something useful, explain it, and leave the final decision with the traveler.
Three ways to bring the past back
Most travel software is optimized for the next trip. Mapsake also needs to be good at returning someone to a trip that happened five, ten, or twenty years ago.
This update adds three different paths into that past. On This Day finds a calendar connection. Then & Now finds a place connection. Passport Stamps preserves a physical artifact and uses it to improve the atlas.
They share a design principle: start with data the user already owns, do the interesting work on the device, and ask for confirmation whenever an inference might be wrong.
There is a retention idea behind the release, but it is not “send more notifications.” A lifetime atlas becomes useful when it creates new reasons to revisit old data. The best reason is a real connection the user did not have to curate manually.
On This Day, Then & Now, and Stamps all create those connections differently. That made them a good test of whether Mapsake's growing set of features could share photo loading, place resolution, rendering, navigation, and privacy rules without collapsing into one giant memory engine.
On This Day uses dates from more than photos
The obvious implementation would search the photo library for the current month and day. Mapsake goes a step further because photos are only one kind of travel evidence.
Each place in the atlas can carry presence days from manual entries, imports, flights, and photo history. On This Day combines those dates with cached photo metadata, groups the result by year, and orders the most specific places first. A city or airport can headline the memory while its region and country remain part of the same story.
The photo filtering runs away from the main interface because a large library is still a large library, even when the query sounds simple. Results are grouped newest-first and shown as calm year cards. Opening one reveals its gallery and links back to the relevant place stories.
There is also a nearest-memory fallback for quiet days. If July 9 has nothing, Mapsake can point toward the closest date that does rather than presenting a dead end.
Calendar matching has more edge cases than it appears
“Same month and day” sounds like a trivial predicate until time zones and incomplete records enter the picture. Photo dates come from captured media, while manual and imported place dates can represent a day rather than an exact instant. The feature therefore works in calendar components instead of asking whether timestamps are exactly 365 days apart.
Places are ordered finest-first for presentation. If the atlas knows the airport, city, region, and country for one day, the airport or city should headline the card; listing all four as separate memories would exaggerate one piece of evidence. The full hierarchy remains available as place chips and contributes to the surrounding story.
The photo side uses the metadata cache Mapsake already built during import. It does not ask PhotoKit to rescan the entire library every time Profile opens. The per-day filter runs in a detached task, then the interface receives a small collection of asset references it can load lazily.
The first entry point lived on the Atlas. Testing showed that a calendar button made the most visually important screen busier even on days with no memories. Moving the entry into Profile let it appear conditionally, pair naturally with other personal features, and carry an unread state without competing with map controls.
Notification taps needed their own routing work. A local notification does not arrive through the same path as tapping an ordinary universal link. Mapsake writes a memory deep link into the notification payload, catches the response in the app delegate, and forwards it into the same navigation state used by other deep links. The visible feature is a sentence; the reliable tap requires the whole route.
The reminder is deliberately opt-in
On This Day can schedule a gentle notification, but only after the user enables it. Mapsake prepares upcoming memory dates from local data and attaches a deep link so tapping the notification opens the right surface.
No server decides which memory is important, and no photo has to leave the device to make the reminder work. The Profile tile appears only when today actually has something to show, with a small unread dot that clears after opening it.
The notification copy can summarize more than one year or place because the local calculation already knows the grouped result. A reminder might say that the traveler was in Redmond, Rome, and Tokyo on this day across several years. The wording is assembled on the device and localized with the rest of the app.
That conditional entry was a product decision as much as an engineering one. A permanent empty card would advertise the feature more often, but it would make Profile noisier every day the feature had nothing useful to say.
Then & Now treats location as the common thread
Then & Now looks for photos taken near the same spot at least two years apart. The implementation uses a compact spatial grid: filtered photo coordinates are placed into cells roughly 280 meters wide, and each cell keeps only its earliest and latest photo while scanning.
Cells with a long enough time span become candidates. The longest spans come first, nearby candidates are deduplicated so one plaza cannot fill the whole list, and the bundled gazetteer supplies a city and country label. The result is memoized until the photo index changes.
This is intentionally not image similarity. The photos do not have to show the same composition or subject; that is a different job for Constellations. Then & Now asks a simpler question: what did this place look like when you returned years later?
Pairs open in the normal photo viewer and can be shared through the same rendering path as Passport cards. The originals remain in their source library, while Mapsake holds the lightweight metadata needed to find the pair again.
Why 280 meters and two years?
The spatial cell is deliberately forgiving. Phone GPS can drift, a landmark can be photographed from opposite sides of a plaza, and an older camera may have less precise coordinates. An exact-coordinate match would miss many genuine returns. A city-level match would be so broad that it paired unrelated neighborhoods.
Roughly 280 meters is a product threshold, not a claim that two photos show the identical physical point. It asks whether the return is close enough to feel connected when the images are placed side by side. The two-year minimum keeps a vacation's first and last day from being framed as a long-term change.
Only the earliest and latest photo in each cell are retained during the scan. That makes memory use proportional to occupied cells rather than total images and naturally maximizes the time span. Candidate pairs are then sorted by duration and spatially deduplicated so a person with hundreds of photos around one home square still sees variety.
The memoization key follows the photo metadata generation and exclusion count. Import a new library batch or remove a photo from the map and the pairs recompute; reopen the screen without changing the source and the app reuses the result.
The first benchmark pass later showed that Then & Now also spent substantial time in nearby-city lookups. Because it uses the shared gazetteer rather than a feature-specific reverse geocoder, the geographic index work that sped up imports and Constellations also made these labels much cheaper. Shared foundations create shared wins.
Sharing reuses the Passport pipeline
Then & Now needed a two-photo card with years, place, and span. Building a new exporter would have duplicated light and dark rendering, social aspect ratios, image preloading, Photos saving, and the system share sheet.
Instead, the pair is wrapped as a custom Passport card and handed to the existing share screen. The source images are preloaded because SwiftUI's offscreen ImageRenderer is synchronous at the final render point. The user sees the same preview-and-destination flow used for maps and statistics.
That reuse is more than code economy. It makes sharing behavior predictable: nothing posts automatically, the export looks like the preview, and the same accessibility and color rules apply.
Passport stamps need an assist, not false certainty
Real passport stamps are difficult OCR material. They are faded, rotated, layered over background art, written in many languages, and sometimes stamped directly over one another. Any scanner that claims perfect automatic recognition is setting the user up for bad travel data.
Mapsake uses Apple's Vision framework on the device to extract the text it can read, then ranks possible matches. An IATA airport code is a strong signal. A two-letter country code, country name, local endonym, city, port of entry, or European date can add evidence. Local-language airport stems help recognize that an entry was probably by plane even when OCR misses the end of the word.
The matcher presents a suggestion and a prefered place chain—country, region, city, and airport where available—but it never commits the guess by itself. The review screen always allows another candidate or a fully manual choice.
That conservative handoff is important. A missed suggestion costs a tap. A confident wrong suggestion quietly corrupts the atlas.
A faded Iceland stamp changed the matcher
One real stamp made the limits concrete. Its airport text should have read KEFLAVIKURFLUGVOLLUR, but the faded ink and line break reached Vision as something closer to KEFLAVIKURFLUGVOLI UR. A whole-word check for the Icelandic airport term failed, so Mapsake neither inferred a flight nor resolved Keflavik airport.
The fix was not a special case for one passport. The matcher now recognizes stems for common airport words across several languages: fragments corresponding to airport in Icelandic, German, Spanish, Portuguese, Dutch, Scandinavian languages, and others. A damaged ending can still suggest the mode of entry and bias place resolution toward an airport.
EU and Schengen stamps added two more lessons. A bare two-letter ISO country code in the corner oval is useful only when it appears alone; treating every two-letter word as a country would create absurd matches. European numeric dates also need day-first parsing before a locale-sensitive general detector gets a chance to read them month-first.
Point-of-entry resolution is prefix-tolerant for the same reason. Long local-language compound words can contain a city or airport name even when the bundled gazetteer stores the shorter English form. The resolver tries meaningful leading fragments, then builds the country, region, city, and airport chain around the confirmed result.
The chain is shown before saving. Choosing a fine-grained airport can mark its city, region, and country together, but each inferred level remains visible and editable. The UI is designed around a strong suggestion followed by a human decision.
Keep the artifact, not another copy
A Passport Stamp record stores metadata and a reference to the source photo, not the full image bytes. Mapsake creates a small regenerable thumbnail for the stamp wall and loads the original on demand. If a Photos-sourced original is truly deleted, reconciliation can remove its orphaned stamp without pretending the image still exists.
The “truly” in that sentence matters. Limited Photos permission cannot prove that an unseen asset was deleted; it may simply be outside the allowed selection. Reconciliation removes a stamp only when the library permission is sufficient and neither the local nor cloud identifier resolves. Ambiguity keeps the record.
This reference-based model also keeps CloudKit-friendly data small. A stamp can sync its country, date, book, entry method, page, favorite state, note, and identifiers without attempting to store a passport photograph inside a database row. A 256-pixel local thumbnail is a cache, not the source of truth.
Stamps can be organized into named passport books, marked as arrivals or departures, assigned dates and entry methods, and viewed by country. Crop, straighten, rotate, and a censor-blur brush help prepare a useful image before sharing a country or continent collage.
The same flow can scan a passport identity page into a book. Machine-readable-zone parsing supplies structured fields where possible, while the image remains a reference to the user's own library.
MRZ recognition disables language correction. The machine-readable zone is a rigid run of letters, digits, and angle brackets; asking OCR to turn it into natural words can make it look more readable while making the parsed fields less accurate. Printed fields such as place of birth use a separate best-effort pass, and every result lands in an editable book form.
Camera and picker flows share a crop-and-rotate step before recognition. Later polish added a straighten dial, zoom and pan, and a censor-blur brush for sensitive details. The editor disables conflicting gestures while the blur brush is active, then composites the edits into the saved source image according to the user's chosen storage behavior.
The stamp gallery groups artifacts by continent and country rather than only by passport book. Tapping a fanned country stack opens the individual stamps; arrivals, departures, and favorites can be filtered; continent and country headers can render a collage through the Passport share pipeline. Books remain useful metadata, but geography is the more natural browsing path in a travel atlas.
Technical enough to be trustworthy
These features use three different techniques—calendar joins, spatial bucketing, and OCR—but the user experience follows the same pattern:
- Derive a candidate from existing local data.
- Keep expensive work off the main interface.
- Explain what was found.
- Let the user open, correct, share, or ignore it.
That is the kind of intelligence I want in Mapsake. It should make the private record easier to rediscover without acting as if an algorithm understands a life better than the person who lived it.
There is more engineering in these features than their calm surfaces suggest, but none of it needs to become homework for the user. The technical work is successful when On This Day opens to the right year, Then & Now shows a surprising return, and a difficult stamp offers a useful candidate without overclaiming certainty.