May 27, 2026 – Laying the Foundation

Today I started building the core of ItinerSense. First up: the database layer. I chose GRDB/SQLite because it’s fast and gives me fine-grained control. The DatabaseManager now handles creating the landmarks table, copying the bundled default.json, and loading every pack file from Documents/Landmarks/ into the database. I also began wiring up LocationViewModel to request location access and listen for foreground/background changes. The goal is simple: show nearby landmarks and let the user explore.

The landmark model uses a GUID as the primary key (no auto-increment integers), and I added a verified column for future filtering. The database loads itself on init, then I added search with forgiving plural/singular matching. It feels good to have the data layer solid.

May 29, 2026 – First Trip Plans

I started the trip planner today. TripPlanViewModel currently saves plans as JSON files via UserDefaults just to get something working. The plan structure includes destination, dates, travelers, interests, pace, and a daily itinerary with activities. The itinerary generation is still a big TODO, but I can at least create and save a plan.

The decision to keep the view model separate from the views is already paying off — I can change storage later without touching the UI.

June 3, 2026 – Pack Download System

Today I built PackManager, which handles downloading city and bundle packs from Cloudflare. It supports:

I also added the 3-pack limit for free users, but I know the Pro logic isn’t wired up to the debug toggle yet — I’ll fix that later.

June 10, 2026 – Plan Detail & Day Card

The planner UI is coming together. PlanDetailSheet now shows a full itinerary with expandable day cards. Each DayCard builds a timeline with scheduled start times, travel segments, and activity rows. I added an “Edit” button and placeholder days that say “Tap to plan this day.”

The hotel propagation logic is tricky: changing the hotel on one day should update all future days until a placeholder or manual override. I got it working, but I’ll need to test edge cases.

June 15, 2026 – Itinerary Generation

Added the first version of generateSmartItinerary. It uses a scoring system based on verified landmarks, interest matches, family-friendliness, and ratings. Then it clusters landmarks by distance and fills each day within available hours. The first day gets a full plan; subsequent days get placeholders until the user taps them.

There’s a lot of async routing logic here — walking vs driving decisions, ferry detection, fallback to straight-line estimates. It’s messy but works.

July 10, 2026 – Feature Manager & Pro

I built FeatureManager today. It loads a remote config from Cloudflare, manages trial periods, and uses StoreKit for Pro purchases. Key features gated behind Pro include unlimited packs, unlimited plans, custom arrow colors, and AI suggestions.

I also added a TestFlight sandbox detection that grants temporary Pro access so testers can explore everything without paying. Debug builds get an “Always Pro” toggle in UserDefaults so I can test without affecting production.

July 20, 2026 – SwiftData + CloudKit Migration

This was the big one. I migrated trip plans from UserDefaults to SwiftData with CloudKit for private sync across devices. I created CDTripPlan, CDDailyItinerary, and CDActivity models with relationships and cascade deletes.

The mapping layer handles property name differences (CDActivity.activityDescription vs Activity.description) and assigns orderIndex to keep activities sorted. I had to manually delete child objects before deleting a parent because SwiftData’s cascade didn’t send explicit deletes to CloudKit.

Live sync works via NSPersistentCloudKitContainer.eventChangedNotification — no restart needed. Finally, cross-device sync.

July 25, 2026 – Announcements & PDF Customization

Today I added the “What’s New” popup using AnnouncementManager. It fetches a remote whatsnew.txt, falls back to a bundled file, and only shows once per build. The sheet appears over the tab view after a short delay.

I also upgraded the PDF export. Users can now choose a font and background color (Warm, Cool, Clean, Sepia, etc.). The PDF uses the selected font for all text and fills the page background. It’s a nice touch for sharing itineraries.

August 1, 2026 – Pack Limit Bug & Final Cleanup

Fixed a bug where Pro users and debug builds were still limited to 3 pack downloads. The fix used effectivelyPro that combines FeatureManager.hasProAccess with the debug toggle in #if DEBUG builds. Now trial users stay limited, but Pro/testers have unlimited downloads.

I also reviewed PackManager, DatabaseManager, FeatureManager, LocationViewModel, and TripPlanViewModel. Everything looks stable. I’m avoiding risky refactors this close to release.

August 10, 2026 – TestFlight & Submission Prep

The app is feature-complete. I’ve uploaded a TestFlight build and sent it to testers. The remaining tasks are minor: the console shows a harmless default.csv resource warning from Apple’s geoservices, and there’s a redundant telemetry log I might add later. Neither affects the release.

I’m feeling good. ItinerSense has come a long way from a database schema to a full trip planner with AI-powered generation, CloudKit sync, and PDF export. Time to submit.

ItinerSense — Plan smarter. Travel deeper.