Pointify

Changelog

What we shipped

Follow our progress as we build the best travel search platform. Every feature, fix, and infrastructure improvement — documented.

42+
Features shipped
143
Pages indexed
300+
Airlines searchable
15
Email templates
New

World Cup 2026 — be first in line

  • New /world-cup landing page with editorial hero, 16-host-city grid (USA · Mexico · Canada), four points-and-miles plays for getting there (Aeroplan distance-based, AAdvantage off-peak, Hyatt + Marriott category caps, hybrid cash + points), and FAQ
  • Custom hero animation: rotating field-arc gradient, breathing radial wash, three USA / MEX / CAN host-country pulse dots, shimmer streak — all CSS keyframes, prefers-reduced-motion respected
  • New site-wide slide-up banner that drops in from the bottom-right after 25s on page (skips /admin, /world-cup, /waitlist, /auth). Compact 380px card with animated gradient border, three host-country pulse dots, custom rise animation, and a checkmark-burst success state
  • Banner persists dismissal + signup to localStorage so it never re-shows after a user takes action
  • Both surfaces submit to the existing /api/waitlist with feature=world-cup-2026-early-access — single signup record covers both
Fix

Group-trip hero images no longer broken (Unsplash source.* deprecation)

  • heroImageFor() in group-trips.ts was returning source.unsplash.com URLs as the fallback for any group trip without a custom hero. That service was deprecated by Unsplash in mid-2024 and now resolves to nothing — every real group trip with no hero image was rendering with a broken image
  • New three-tier resolution: explicit destination_image_url → curated local asset for known destinations (Paris, NYC, Tokyo, Maui, Cancun, Punta Cana, Vegas, Orlando, Maldives) → deterministic SVG-data-URI gradient hero with the destination as the headline
  • Affects 5 production pages: /group, /group/[id], /group/[id]/confirm, /group/[id]/confirmation, plus the /demo/group-trip showcase
  • 33/33 group-trips lib tests pass (5 updated to assert new behavior)
Fix

Contact form actually persists submissions

  • Every /contact form submission since launch had been returning a 500 ("save-failed") AND losing the lead — press inquiries, partnership inquiries, security reports, support requests, all dropped
  • Root cause: contact_inquiries table was queried by /api/contact-inquiry but never migrated. Insert errored, handler returned 500, confirmation + routing emails never fired, inquiry vanished
  • Migration ships the table the handler expects, with status workflow (new → assigned/in_progress → resolved/closed/spam), resolution_notes, and admin index on (status, created_at desc)
New

Guest checkout — book without an account

  • createCheckoutSession had customerEmail in its input schema for months but the impl rejected any caller without a Supabase session — guest tests were skipped pending wiring
  • Three modes: authenticated session (unchanged), guest mode (looks up Stripe customer by email, reuses or creates with metadata.pointify_guest=true, skips card-saving), neither (throws "Sign in or provide a guest email")
  • createSubscription explicitly rejects guests — recurring billing needs an account to bind to
  • 8/8 payment tests pass (3 newly enabled)
Fix

Saved-routes API actually persists

  • /api/saved-routes was queried by the route handler since launch but the saved_routes table was never created — silent failure under a graceful fallback that returned "Saved routes coming soon"
  • Migration ships the table the handler expects: id, user_id (FK auth.users CASCADE), origin/destination (3-char IATA), label, created_at, unique on (user_id, origin, destination), index on (user_id, created_at DESC)
  • RLS uses (SELECT auth.uid()) wrapper for InitPlan caching, consistent with the auth_rls_initplan cleanup that landed earlier today
Fix

Rentals detail page — no more fake "Tulum villa" mock data

  • /rentals/[id] was rendering hardcoded mock data ("Luxury Beachfront Villa, Tulum, Carlos & Maria, $489/night, 4.92 stars") for every URL — click any rental on the listing page, arrive here, see Tulum
  • Two query-param bugs hidden under the mock: listing page passed checkin/checkout (lowercase), detail page read checkIn/checkOut (camelCase), so the dates the listing passed were silently dropped. Detail page also ignored ?price= and ?source=
  • Rewritten to be honest: hotel name from URL slug, real price + dates + partner from URL params, partner-handoff CTA labels the source ("Book on Expedia — $1,840"), drops 30 fake fields, replaces with a "What we have" facts panel + "Photos, amenities, and reviews live with {Partner}" disclosure
  • Surface area: 393 lines → 247 lines
Improved

/transfers redesigned in Blacklane editorial style

  • Full-bleed cinematic hero photo (executive sedan at night) with overlay headline "Your chauffeur awaits. Arrive at your best." — matches Blacklane's signature monumental-display treatment
  • Real photography on three tier cards (driver at arrivals, luxury car interior, business traveler with luggage) replaces the abstract gradient illustrations
  • New "We move with you" 4-occasion section — Smooth landings · Seize the day · Between cities · Corporate travel — direct echo of Blacklane's tile pattern, each with a distinct photo and discrete use-case
  • New "Step in. Breathe out." brand-promise interlude explains the emotional reason to pick chauffeur over Uber
  • New "Expect excellence" 4-pillar grid: available worldwide, high-end vehicles, safe travels, sustainability partners
  • Pricing copy rewritten as prose — replaced the variable-name formula with a human explanation of how every fare is calculated
  • New native FAQ accordion with proper ARIA — open one at a time, full keyboard support
New

/about redesigned + "Interested in joining Pointify?" section

  • New editorial hero — "Travel that values your time as much as your money." — replaces the dot-grid layout with a typographic primary-tinted gradient
  • By-the-numbers strip refreshed with current scale: 300+ airlines, 95 loyalty programs, 1,000+ airports, 6 bank programs
  • NEW dedicated "Interested in joining Pointify?" section anchored at #join with three "why-join" pillars (Shipped not staged, Travel-first stack, Real ownership) + dual CTA to /careers and /contact?topic=careers
  • IATAN credential gets its own card with Plane icon — was buried in the prose before
  • Mission and What-We-Do moved side-by-side instead of stacked
  • Bottom CTA collapsed from two duplicated "Ready to try Pointify?" blocks into a single canonical Get-in-touch + Start-searching split
New

12 hotel chain SEO landing pages

  • New pages at /hotels/marriott, /hotels/hilton, /hotels/hyatt, /hotels/ihg, /hotels/wyndham, /hotels/choice, /hotels/accor, /hotels/radisson, /hotels/best-western, /hotels/four-seasons, /hotels/aman, /hotels/mandarin-oriental
  • Each page surfaces program currency, points value, property count, distinctive program features, brand portfolio, and popular destinations
  • Four Seasons / Aman / Mandarin Oriental honestly disclose "no points program" and route to Amex Fine Hotels + Resorts and Chase Luxury Hotel & Resort Collection
  • Closes 11 broken homepage links — the program-logo-circles component had been linking to /hotels/<chain> 404s since launch
Improved

Travel-club partner brand wordmarks

  • Real brand-color SVG wordmarks for AAA (red), AARP (red), Costco (blue), USAA (navy) on the /airlines/partners page
  • Replaces the placeholder text-disc fallback — same hand-built approach as the Hertz / Avis / National car wordmarks already on disk
New

/wallet shows real Plaid balances + live-linked loyalty programs

  • Wallet Cards tab now hits /api/plaid/balances which calls Plaid /accounts/balance/get for every active connection — fresh balances, never cached
  • New NetWorthCard summarizes cash, credit used, credit limit, investments, and net worth across all linked banks
  • Loyalty tab merges manual member-number entries + live-synced loyalty_balances into one view — programs linked through /settings/loyalty now actually appear in /wallet
  • Per-account tile types (depository / credit / investment / loan) with correct labels
Improved

/settings redesigned as enterprise-grade hub

  • Replaces the 460-LOC tab form with a Stripe/Linear-style hub: searchable list, status pills, deep links to dedicated sub-pages
  • New /settings/profile, /settings/cards, /settings/travel-preferences, /settings/privacy — each owns its own slice and save flow
  • Status pills tell you the state of each section at a glance ("5 cards linked", "Add your name") — derived from a single profile snapshot
  • Onboarding CTAs deep-link to the right sub-page (Add your name → /settings/profile, Connect loyalty → /settings/loyalty)
  • Destructive delete-account flow now requires typing DELETE to confirm + 30-day grace period
Fix

Database performance + security cleanup

  • Cleared all 14 ERROR-level Supabase advisor lints (RLS missing on 8 PII tables, 5 SECURITY DEFINER views, 1 sensitive-column exposure)
  • Locked down 5 admin/CRM tables (quotes, suppliers, customer interactions) that anyone could read or write — replaced USING (true) with admin/agent-only RLS policies
  • Indexed all 28 unindexed foreign keys — eliminates sequential scans on cascade deletes when child tables grow
  • Wrapped auth.uid() / auth.role() / auth.jwt() in (SELECT …) across all 403 RLS policies — Postgres now caches the call once per query instead of re-evaluating per row (auth_rls_initplan: 319 → 0)
  • Dropped 40 redundant service_role-only policies (service_role bypasses RLS via JWT, so they were dead code) — multiple_permissive_policies advisor count dropped 614 → 194
Fix

Loyalty model: Plaid removed, scraper-only path

  • Removed Plaid as a loyalty link_method — Plaid's products don't actually expose points balance for any of the 5 supported banks. Scraper is the universal path for all 95 programs
  • /wallet keeps Plaid for cash banking — separate flow on plaid_items
  • Updated privacy / terms / status copy to clarify Plaid is wallet-only, never used for loyalty balances
  • Sync-worker plaid_balance_refresh job no longer dead-codes — fans out across the user's loyalty programs when Plaid TRANSACTIONS_SYNC fires
New

Loyalty catalog expanded + searchable

  • Linkable loyalty catalog grew from 5 MVP programs to 95 — 5 banks, 80 airlines, 10 hotel programs
  • /settings/loyalty has a searchable picker — type "delta" or "marriott" instead of scrolling a giant <select>
  • Page copy derives the breakdown from the catalog itself so it stays accurate as we add programs
Improved

Photo licensing — full audit trail + install workflow

  • New `docs/marketing/airline-press-kits.md` — verified URL list for 11 airlines + 6 hotel chains. Goes to each brand's own press / media-relations program, where photography is licensed for partner-marketing use
  • New `scripts/install-airline-photo.sh` — validates a downloaded press-kit photo, refuses to overwrite existing files, copies into `/public/blog-heroes/`, appends to the license trail automatically
  • New `docs/marketing/photo-license-trail.md` — single audit document covering all 34 image assets currently shipped. 28 confirmed Unsplash CC, 1 confirmed press-kit, 3 user-provided, 2 with explicit operator-confirmation steps
  • Decline log preserved: documents the 5 third-party photo sources we explicitly rejected this session (Pinterest, Runway Magazine CDN, Cathay marketing site, Turkish marketing CDN, theluxurytravelexpert blog) and the reason for each, so the same proposals don't get re-pitched
  • Together, these three files form a closed photo-licensing loop: provenance is provable, additions auto-update the trail, and any future brand-protection contact gets a single document that answers their question
New

Stable booking error codes + UUID for every failure

  • Every /api/booking/* response now carries a stable code (pointify.booking.offer_expired, payment_declined, identity_document_required, …) plus a UUID error_id you can quote to support
  • The same UUID is captured to Sentry as a tag, so support can paste your reference and find the exact event in one search
  • New banner shows the message + Copy-ID button + "Contact support with this ID" link on every booking error
  • On /help and /help/contact, ?error_id=<uuid> in the URL surfaces a "We received your error report" panel with mailto pre-filled — no more orphaned IDs
Fix

Lap-infant bookings + every passenger field actually reaches Duffel

  • Five fields the form was collecting were silently dropped before reaching Duffel — title, middle name, gender, redress number, and passport-issuing country. All wired through end-to-end now
  • Lap-infant fares were rejected 100% of the time because every passenger was hardcoded as "adult". New age-at-departure logic correctly classifies adult / child / infant_without_seat with conservative IATA defaults
  • Lap infants now link to the accompanying adult via Duffel's infant_passenger_id field
  • Partial passport entries (e.g. number without expiry) now bounce at validation with a clear hint instead of getting rejected by Duffel mid-flow
Improved

Booking summary now shows full flight detail

  • Per-slice block: "Outbound: BOS → IND · Jun 15 · 6:00 AM → 9:17 AM · 3h 17m · Nonstop · AA 0171 · Boeing 737-800"
  • Refund + change pills (green / amber / red) with carrier penalty in the booking's own currency
  • Baggage allowance derived from cabin class (carry-on + checked count)
  • Price breakdown with separate fare / taxes / Pointify fee / extras / total lines using locale-aware currency formatting
  • Round-trip and multi-city itineraries label legs explicitly (Outbound / Return / Leg N)
Improved

Post-payment success page rebuilt

  • Shows the route + flight number + departure / arrival times instead of just "Payment Confirmed"
  • Lists every passenger and their e-ticket number once the airline issues
  • Surfaces both your Pointify reference (PFT-XXXXXX) and the airline PNR — different stages need different ones
  • Total paid in the booking's currency, not always USD
Fix

Stripe + Duffel race-condition closed

  • Closed a window where two concurrent payment-success webhook deliveries could each create a Duffel order — charging once but creating two airline orders
  • Atomic Redis claim with 2-minute TTL keyed on booking ID; concurrent retries back off cleanly
  • Fail-open by design: a Redis blip never blocks a paid customer's ticket from issuing
Fix

Safari favicon + routing fixes

  • Safari (macOS Big Sur, iOS) now renders the proper Pointify mark in tab strips, pinned tabs, and home-screen icons — was falling back to a malformed single-resolution ICO
  • Added a monochrome mask-icon for Safari pinned tabs
  • Worked around a known Vercel routing bug that was 404'ing the order-services endpoint (renamed off /services with a 308 redirect for legacy clients)
New

Live buy-points rate checker + Alaska Atmos deal coverage

  • Interactive buy-points rate calculator at /points/buy — dial in the amount you need, see effective cents-per-point with all taxes baked in, click through to the program’s official purchase page
  • Covers Alaska Atmos, United, American, Delta, British Airways, Virgin Atlantic, JetBlue, Aeroplan, Marriott, Hilton, Hyatt, IHG, and more
  • Each program shows its own prerequisites (account-age, annual cap, how the card codes the purchase) so you can confirm eligibility before buying
  • New blog post on the Alaska Atmos Rewards 100% buy-points bonus (active through May 2) with four specific arbitrage itineraries and a stopover deep dive
  • Alaska × Hawaiian merger explainer: what happened to your miles, which partners you gained, what the Atmos Rewards rebrand means
  • Live deal banner on the homepage and on the Search page, auto-dismissible
Improved

Blog reading experience

  • Typographic upgrade across every post: drop-cap on the opening paragraph, serif pull-quotes for key lines, stat-card callouts for the important numbers
  • Inline product cards next to every credit card, buy-miles link, or bank mention — so you can evaluate the offer without leaving the article
  • Faster filtering on the blog index: search, category tabs, author filter, year filter, read-time buckets, sort by newest / oldest / quick-read / deep-dive
  • New grid-and-list view toggle for the blog index
Improved

Navigation and discovery

  • New /sitemap page with every public section grouped by topic
  • Footer reorganized into five columns with a dedicated Resources section (Status, Sitemap, Roadmap, Transfer Bonuses, Sweet Spots, Visa Checker)
  • Destinations page rebuilt: search, region chips, featured-destinations row, A–Z index
  • Airlines directory now shows the real airline brand logos instead of IATA-code placeholders
Improved

Seat map and booking polish

  • Interactive seat-map view during booking with pricing and availability
  • Search results now render return-leg and stopover details, with an option to filter to bookable results only
  • Cleaner mobile checkout: native date picker for date of birth, clearer copy on the confirm step
  • Cruise search wired to a daily-refreshed inventory source
Improved

Sign-in, security, and reliability

  • Phone one-time-password sign-in flows directly through Supabase now — fewer steps, faster verification
  • Dependency upgrades for the underlying framework and payment libraries
  • Duplicate webhook events are now deduplicated server-side so nothing double-charges or double-books on retries
  • Accessibility and dark-mode parity audit across 25+ components (search forms, ticker bar, mistake-fare list, transfer-partner pages)
New

Mobile app, iOS TestFlight update

  • Passport OCR (scan-to-fill) on the booking form — runs entirely on-device, nothing leaves your phone
  • Real Pointify brand mark on the iOS app icon and inside the app
  • Trending routes carousel on the mobile search landing
  • Account sync-status badges on the Profile screen so you can see which linked programs are fresh and which need a re-link
  • Snappier app launch: in-app purchase prompts are now lazy-loaded
New

Live cash booking + points-plus-cash

  • Flight bookings with cash now fully live: search, select, book, receive itinerary and e-ticket end-to-end
  • Link your bank accounts via a secure provider so Pointify can score the best way to pay (cash / points / mixed)
  • Award-availability scanner across major airline and hotel loyalty programs
  • Visa requirements checker: pick a passport, pick a destination, see the answer
  • Route map view with flight-duration and distance info
Improved

Faster search and cleaner emails

  • Cold-start search latency cut dramatically — first result now appears in seconds instead of tens of seconds
  • Every transactional email redesigned for better readability on mobile and dark-mode inboxes
Improved

Waitlist and credibility

  • Dedicated waitlist page with email capture and live counter
  • Partner ecosystem section showcasing airlines and loyalty programs we integrate with
  • Mobile navigation, filter bottom-sheets, and card layouts tightened up
New

Search filters, calendar view, compare mode

  • Filter results by stops, airline, price range, with clear "active filter" badges
  • Calendar fare grid: scan a whole month for the cheapest day to fly
  • Compare mode: pick up to 3 flights and see them side by side
  • Shareable deal links with a preview card for social
  • Fare-score badges (Deal / Mistake Fare) on results so outliers stand out
  • Transfer-partner pages with bonus tracking and sweet-spot redemptions
  • Honest "Pointify vs the alternatives" comparison page
New

Guides, destination pages, and FAQ

  • Airline detail pages with award programs and popular routes
  • Route pages with booking tips and price-trend context
  • Cabin class deep-dives (economy, business, first)
  • Expert guides: how points actually work, mistake fares, best time to book, hidden-city flights
  • FAQ with the 20 most-asked questions
  • Sitemap expanded so search engines find everything
New

Core product ready

  • Flight search across hundreds of airlines with cash prices
  • Hotel search with points redemption side-by-side against cash
  • Smart sort tabs: Cheapest, Fastest, Best Value
  • Command-palette (Cmd+K) quick nav with destinations and shortcuts
  • Navigation cleaned up to six focused sections
  • Destination detail pages for 50 cities worldwide
New

Deal alerts and post-booking essentials

  • Booking confirmation emails with full itinerary summary
  • Price-alert subscriptions: pick a route and target price, get notified when it hits
  • Honest flight-status badges with real-time data (no padded or outdated estimates)
  • Share button on flight cards (native Web Share sheet where supported)
  • Recent searches saved locally for fast re-searching
New

Accounts and branding

  • Password reset flow with secure email tokens
  • Email verification with resend
  • Pro and Business plan checkout
  • Airline logos attached to every search result for instant recognition
  • Honest trust badges: updated daily, data-driven, no signup required to search
New

Current platform foundation

  • Everything rebuilt on a single, unified codebase: web, mobile, search, booking, points tools, and the underlying data layer
  • Migrated off the previous iteration of the product and onto what we run today
  • Goal: make it simple to see whether cash, points, or a mix gets you the better deal — in one search
Improved

Design system overhaul

  • New Pointify brand orange (#E35F22) rolled out across every surface: web, mobile, email, favicon, app icon
  • Consolidated on a single type system (Inter for UI, Playfair Display for long-form and editorial moments)
  • Dark-first palette with a matching light theme that passes WCAG AA contrast across the whole product
Improved

Fifth-generation platform rewrite

  • Decision to collapse web, mobile, search, booking, points tools, and the backing data layer into a single unified codebase
  • Prior four generations had taught us which pieces had to live together and which could stay independent — this is the architecture we kept
  • Six weeks of quiet rebuilds before the March 16 unified platform went live
New

First shareable flight-deal cards

  • Flight results became shareable links with a custom preview card for social and iMessage
  • Early precursor to the Deal and Mistake-Fare badges that shipped on the current platform
New

Prototype v4: points-aware consumer search

  • First serious consumer search: cash prices and award prices on the same row, with a cents-per-point verdict inline
  • Sat on top of the same data we were already serving to developer customers through the API
  • Closed the loop between search, the points-math calculator, and booking in one flow instead of three separate tabs
Improved

Hotels and award-chart coverage expanded

  • Hotel search with points redemption next to cash pricing added to the consumer prototype
  • Award-chart data expanded beyond airlines to cover major hotel loyalty programs
New

Consumer beta opens

  • First invite-only public beta for a handful of friendly testers — real bookings, real feedback
  • Confirmed the central thesis: showing cash and points side-by-side materially changes which ticket people buy
Improved

Expanded API surface

  • Broader set of endpoints for flight search, hotel rates, and points-aware pricing available to developer customers
  • Heavy internal testing cycles before anything reached the public — most of what you see today was validated against real traffic under the covers first
New

Prototype v3: award-chart comparison tool

  • Side-by-side award-chart comparison across major programs — pick a route, see how many miles each program costs
  • Still static-data-driven at this stage, but enough to answer "which of my miles is worth the most on this trip" quickly
New

Prototype v2: trip-planning and credit-card matcher

  • Added a simple trip-planner on top of the original API — input a budget and a vibe, get a few destination suggestions
  • First credit-card recommendation flow: enter what you already hold, see which card gives the biggest marginal value for your next trip
  • First version to look and feel like a real product rather than a calculator
Improved

Developer API: expanded data coverage

  • Real-time cash-fare lookups added to the points-math endpoints
  • Loyalty-program metadata (transfer partners, transfer ratios, monthly promos) cleaned up and exposed uniformly
  • Customers at this stage were mostly other travel startups and fintech apps embedding the data inside their own flows
New

First public site and waitlist

  • Very first pointifytravels.com site: short landing page, email capture, and a live counter of how many people had already signed up
  • No product behind it yet — we were building toward the consumer experience that shipped in 2025
New

First Figma designs

  • Spent the summer in Figma instead of code — sketching what a "cash or points" flight search would actually look like for a real traveller
  • Decisions made in these mockups (the cpp pill next to each result, the sweet-spot callout, the combined cash-plus-points comparison) are still the defining visual cues on the product today
New

Day one: Pointify starts as a developer API

  • Pointify began as a small set of API endpoints other apps could call for points-math and loyalty-program data
  • No consumer site yet, no app — just clean data and one honest question: is this trip a better deal in cash or in points?
  • Everything on Pointify today is the result of iterating on that original API, testing with real traffic, and gradually learning what a traveller actually wants to see
Upcoming

Coming soon

  • More programs on the buy-points rate checker
  • Weekly deal digest email with the best buys we found across the loyalty world
  • NYT-style treatment applied to a growing library of new posts each week
  • Native Android app (iOS is already in TestFlight)
  • Points earning estimator — "if I booked this with card X, how many points would I earn?" — alongside the redemption math

Want to see what we build next?

We ship fast. Try it yourself.

Ready to find your best fare?

Join travel professionals who never overpay for flights. Free account in 30 seconds.

Create Free Account