The last week and a half had a lot going on -- here's the round-up.
New Booking Detail Page
Every booking on your dashboard now has its own page (linked from the Sailings tab and from the "you have this booked" banner on the sailing page). Instead of pulling pieces together from three different views, everything that actually matters for that one cruise is in one place:
- A tactical header with cabin, passenger count, booking number, and a countdown to sail date
- A purchased packages table with per-passenger tooltips, properly grouping anything bundled into the Unlimited Dining Package or another parent so you don't see it twice
- An order history accounting log that shows what you paid, what changed, and when -- mirrored against the same totals shown elsewhere so the math always reconciles
- A price history modal for any package, so you can pull up the chart without leaving the page
- A "Relevant to You" sidebar with active alerts and prior sailings on the same itinerary
- A "Shop Other Packages" searchable multi-select that pulls in your personalized prices, not just public ones
- A collapsible raw reference section if you want to see the underlying data we have on file
Personalized price drop emails now deep-link straight to this page, so you can land on the booking, see paid vs. current, and decide what to do.
Unified Price Alerts
Package alerts and personalized-price alerts used to live in two separate systems with two separate database tables, two separate emails, and two separate sets of edge cases. They've been merged into one pipeline:
- Per-product chips per sailing on the dashboard alerts panel and on
/my-watches, with a clear Personalized vs Public badge so you know which kind of price each alert is watching - The watch UI on the sailing page now uses a diff-and-apply model -- toggle products on and off in any combination and a single save reconciles them
- Personalized drop emails now show passenger names and a paid vs. current comparison, instead of a generic "price went down" line
- Public emails are clearly labeled as guest-view pricing
- Auto-enrollment when a new account is linked carries over to the unified system, and opt-outs are preserved
Behind the scenes this also makes the alert checker much more deterministic, which means fewer ghost drops (an alert that fires because we briefly couldn't see a SKU, then "reappeared" at the same price).
SEO Pass
CruiseDen pages were previously missing a lot of the metadata that search engines and social platforms expect. That's now fixed across the board:
sitemap.xmllists every public page, including all sailings- JSON-LD structured data so Google can render rich previews for cruises, prices, and itineraries
- Meta descriptions, canonical URLs, OG and Twitter tags, and dynamic page titles -- pages shared on Twitter, Slack, iMessage, etc. now show a proper preview card instead of just a URL
- Breadcrumbs on sailing, casino, and analysis pages
- Table captions and prose summaries on Market Pulse so the page is meaningful even when consumed by a search engine
- URL normalization -- trailing slashes are stripped and underscores collapse to hyphens, so two URLs no longer compete for the same page
- Expanded
robots.txtand a newllms.txtfor AI crawlers
Faster Page Loads
A round of front-end performance work:
- Bootstrap, Flatpickr, and Choices.js are now deferred instead of blocking initial render
- All static assets are served with gzip + brotli compression
- Cache headers tightened so repeat visits are essentially instant on assets that haven't changed
The first-paint difference is noticeable, especially on the sailing page where Choices.js used to be in the critical path.
Homepage Filters
- New "Avoid Regions" filter -- the inverse of the existing region filter
- RC Instant Offers is now a first-class sidebar filter instead of a separate flow, with a tier dropdown that shows the actual tiers we've seen rather than asking you to guess the format
- Fixed: include and exclude filters on the same column (e.g. include Caribbean, exclude Bahamas) used to clobber each other -- they now coexist
- Fixed: the "No Overlap" filter was silently dropped on initial page load when it came in via URL, so a shared filter link would lose it
- B2B (back-to-back) port badges weren't showing for some sailings -- they do now
- Multi-select filter placeholders are fully visible again
Market Pulse
- Share buttons to send the page to Twitter / iMessage / etc.
- Explanatory tooltips on every metric and every chart so you don't have to guess what "median day-zero discount" means
- Beach Club is now its own line on the package trends chart, anchored by SKU name so it survives RC renames
- Per-cruise products (cabanas, day passes) are excluded from the per-day trends chart -- they were skewing the lines
- Cached
computed_attimestamps are now treated as UTC, so the "as of" stamps no longer drift by 7-8 hours
Booking Hardening
A handful of fixes around how we handle bookings that change underneath us:
- Past sailings no longer disappear if Royal Caribbean drops them from your reservation list. They're preserved on user-facing pages (dashboard, sailings tab, etc.) so your history stays intact
- Cruise fare is now shown alongside Cruise Planner purchases, with a fallback to taxes × passengers for casino-comp bookings where the fare itself is $0
- UDP-included reservations are grouped under their parent package on the booking page
- The order-history toggle on the booking page is no longer broken, and the Paid / Current / Rebook savings columns now sit on the right edge where you'd expect them
Calendar Events
When you add a sailing to your calendar via the .ics link, the event description now includes passenger count and passenger names -- handy when you're glancing at the entry on your phone and want to remember who's going.
Privacy
Two scoping fixes worth calling out:
- Notes attached to a casino offer are now strictly scoped to users allowed to see that offer
- Personalized package data on the sailing page is scoped to the current user only
Neither was leaking publicly -- both were narrow cases involving shared accounts -- but they're now properly locked down.
Small Things
- "Free" label for non-positive upgrade costs on the casino offer detail page (no more "$0" or "-$3" oddities)
- The dashboard sailings tab split Details into its own Breakdown column so the link target is obvious
- The personalized price chart picker no longer duplicates entries by product, and Voom defaults to the 1-device tier when present
- The sailing page list-creation dropdown now waits for Choices.js to finish initializing before binding, so the "create new list" flow is reliable on slower connections
- Instant Offers no longer mark a month "completed" when the scrape errored partway through, and won't deactivate offers when a sub-fetch fails
- A handful of ship-name canonicalization fixes that resolve a few sailings that were silently grouped under the wrong ship