UXProductTravelCMS

MakeMyTrip Holidays

Rail Europe for Holidays

Rail stitched into holiday packages across CMS and booking flows. The challenge was to make dynamic train pricing, passes, stations, and multi-leg routes feel native inside MakeMyTrip's existing holiday package system.

Rail Europe for Holidays hero image

1

Designer Lead Product Designer

2

Collaboration layers Core loop, periodic reviews

4

Core surfaces Desktop, mobile, CMS, Holiday Experts (HE) DIY

My Role

Lead Designer (IC) across CMS, desktop, mobile, and Holiday Expert DIY — translating Rail Europe's standalone booking logic into MMT Holidays' package model.

The Team

Core loop: Senior Design Manager, Senior PM

Periodic reviews: Design Director, Director PM

Platforms

  • Desktop web
  • Mobile app
  • CMS
  • Holiday Expert DIY

Status

Design shipped Feb 2026. Currently in development and expected to go live in 2026.

Challenge

Rail Was Dynamic. Holiday Packages Needed Structure.

Rail had to work inside an existing package system where flights, hotels, transfers, activities, meals, pricing, and availability were already connected.

The challenge wasn't to add a train card. It was to make rail work natively across every surface where packages are created, browsed, customized, and booked.

The problem set behind the rail experience

P2P transfers

City-to-city journeys with operator, class, and station variables on every leg.

Rail passes

Flexi and continuous passes as an alternative to single-trip tickets.

Age-based pricing

Youth, child, and senior fare categories that directly changed the package cost.

Filters and class options

Class, operator, station, direct/non-direct, and duration filters on every train search.

Overnight routes

Multi-leg journeys with interchanges and overnight timing needing pre-selection disclosure.

Hotel-to-station proximity

Station distance depended on which hotel and which train was selected — not a fixed value.

Dynamic availability

Trains could become unavailable after package creation or return no results at all.

Product Logic

Understanding Rail Europe’s product logic

Before designing the Holidays experience, I mapped how Rail Europe handled train discovery, passenger categories, route complexity, pricing, and booking confidence — then translated those behaviours into MMT’s package system.

Rail Europe behaviour

What Holidays needed

Train tickets vs rail passes

P2P transfer and Pass transfer setup in CMS

Adult / Youth / Senior fare categories

Contextual age capture in Holidays and HE DIY

Multiple departures and fare classes

Add/change train cards with time slots and class

Direct, non-direct, interchange routes

Route anatomy, overnight and interchange tags

Dynamic pricing and availability

Review fare updates and unavailable-train fallback

Station-based journeys

Hotel-to-station distance and dependency warnings

1. Rail Europe search widget — P2P vs rail passes

Rail Europe separated train tickets and rail passes upfront, with passenger-type inputs such as Adult, Senior, and Youth directly affecting fare discovery.

Rail Europe search widget showing train tickets, rail passes, and passenger category inputs

Train tickets and rail passes as separate entry points — passenger type sets the fare tier upfront.

2. Rail Europe results list

The Rail Europe flow treated train selection as a dynamic shopping journey, with changing prices, multiple departures, route durations, and checkout state visible together.

Rail Europe results list with dynamic prices, departures, journey details, and checkout state

Dynamic pricing, multiple departures, and route detail all visible in one train selection view.

3. Rail Europe complex route / interchange warning

Complex journeys needed explicit warnings for short interchanges, bus segments, number of changes, and route legs before the user committed.

Rail Europe route details showing short-interchange and complex journey warnings

Short interchange time and route complexity flagged before the user commits to a multi-leg journey.

4. Existing MMT Holidays flow without rail depth

The existing Holidays flow already supported transfers and traveller inputs, but it did not yet support Rail Europe-specific logic like youth fares, passes, station proximity, interchange warnings, or dynamic rate plans.

Existing MMT Holidays guest and traveller input flow before rail-specific depth

Rooms and guests — standard traveller input with no rail-specific age tier logic.

Existing MMT Holidays add-to-day transfer selection flow before rail-specific logic

Transfer mode selection — no Rail Europe operator, class, or pass options.

Existing MMT Holidays itinerary customization flow showing a rail pass entry and payment-side summary

Itinerary view — rail pass entry point exists but without pricing depth or route anatomy.

Existing MMT Holidays transfer details card without Rail Europe-specific route logic

Transfer card without station proximity, interchange warnings, or dynamic fare display.

CMS Foundation

Making rail configurable before it could become customer-facing.

Before Rail Europe could appear in holiday packages, package creators needed a way to add, search, and configure rail inside the existing CMS transport module.

Supporting P2P and pass transfer setup

The Transport module was extended to support Rail as a new transport option. Package creators could add Rail under Transport, choose between Point to Point Transfer and Pass Transfer, search trains or passes, apply filters, and attach rate plans with lock or optional behavior.

CMS transport screen showing Rail as a new transport option

Rail added as a new transport type alongside flights and cabs in the CMS transport module.

Point to Point Transfer rail setup in CMS

Point to Point Transfer setup — train search, class, filters, and rate plan attachment.

Pass Transfer rail setup in CMS

Pass Transfer setup — pass search with lock or optional rate plan behaviour.

The package system had to understand rail as configurable, priceable, and editable before anything downstream could work. A train that doesn't exist in CMS can't meaningfully appear in an itinerary.

Design Decisions

Reuse first. Introduce new patterns only when rail truly required them.

The core design decision was to fit rail into MMT Holidays and the broader MakeMyTrip system without making it feel like a separate booking product.

Rail had to coexist with flights, hotels, transfers, activities, pricing, and review flows inside the existing Holidays package system.

Reuse first

Avoid new UI unless rail truly required new interaction logic inside Holidays.

Best-fit pattern over obvious pattern

Departure slots were adapted from activity-booking chip patterns because they worked better inside itineraries than flight-selection patterns did.

One genuinely new pattern

Station proximity was introduced because existing patterns did not cover the hotel-to-station dependency in rail selection.

Traveller Pricing

Age capture had to feel contextual, not like a fare-rules form.

Rail pricing depends on passenger type — youth discounts, child fares, senior categories — but surfacing that upfront would have made the standard package search feel complicated.

Unlocking youth and child fares without overloading search

The design introduced contextual age inputs around Europe rail packages — asking whether adults were aged 25 or younger and allowing child-age inputs where needed. Supporting guidance then clarified how Rail Europe age categories mapped to Youth, Adult, and Senior pricing once users needed more detail.

Holiday Packages homepage Rooms and Guests showing standard adult and child count with child age selection strip

Standard Rooms & Guests — adult count and child ages, no rail-specific prompt for non-European searches.

Paris Packages listing page Rooms and Guests panel showing Are any adults aged 12 to 25 prompt for European rail

European rail search — 'Are any adults aged 12–25?' appears contextually to unlock youth discounts, without changing the standard search.

Age Policies modal showing standard age bands and Rail Europe train-specific age guidelines for Youth Adult and Senior

Age Policies modal — standard age bands alongside Rail Europe's tiers: Youth (upto 25), Adult (26–60), Senior (60+). Surfaced on demand via 'Know more.'

Rail pricing rules surfaced only where they changed the fare outcome — keeping the default search clean while unlocking youth and child discounts where they applied.

Package Itinerary

Train journeys as editable itinerary components, not a side flow.

Rail had to live inside the day-wise itinerary alongside flights, hotels, and transfers — not as an external booking surface pasted on top.

Itinerary-level train cards

Train cards had to stay compact inside the itinerary — scannable at a glance, but actionable when users needed to inspect or change what was already in the package.

Compact itinerary-level train cards showing direct and non-direct journeys inside the package flow

Compact train card inside the itinerary — route, hotel-to-station distance, class, slot, duration, and risk tags. Change and View More Options lead into comparison without leaving the package.

Compact itinerary-level train card showing the included rail journey inside the day-wise package flow

Rail sits in the same day-wise slot as flights and hotels — no separate booking mode or interaction layer.

Expanded itinerary train-card state showing deeper rail details without leaving the package flow

Deeper rail detail available inline — without leaving the package itinerary view.

Giving rail the same structural slot as airport buses and cabs made train journeys immediately legible — no new interaction layer, no separate booking mode.

Transfer Flows

Comparing and changing trains without losing the package frame.

Users and Holiday Experts needed to change transfer options mid-journey — comparing trains, buses, and cabs in one place — without the interaction feeling like a switch into a different product.

Rail alongside bus, cab, and pass options in one flow

The Add/Change Transfer flow let users compare train options, bus and cab alternatives, time slots, rail passes, and filters within the same surface — no separate booking mode, no context switch, no loss of the package frame.

Expanded view of slots — transfer options panel

Time slot selection within the transfer panel — multiple departures, duration, and price difference visible together.

Rail transfer comparison with filtering and itinerary change state

Train, bus, and cab options in one surface — filters applied without switching context or losing the package frame.

Train Card Anatomy

Designing the train card anatomy

The larger Add/Change rail cards had to do more than confirm what was already in the itinerary. They needed to support comparison, slot selection, pricing tradeoffs, and route understanding without breaking the package frame.

Direct journeys

Compact — time slots, price deltas, and key route details at a glance.

Non-direct journeys

Expanded into route legs with operator, interchange duration, and risk tags.

Hybrid-class journeys

Class labels per leg — not hidden under a generic non-direct label.

1. Direct journey comparison card

A single-leg journey showing time slots, price delta per person, class, directness, and station proximity — compact enough to scan, detailed enough to decide.

Direct journey comparison card showing selectable time slots, price deltas, and expanded journey details

Direct journey — selectable slots, per-person price delta, station proximity, class, operator, and duration in one compact card.

2. Non-direct journey card

Multi-leg routes expand into individual segments — each with its own operator, train number, station, and timing — so complexity is visible before the user commits.

Non-direct journey card showing segmented route legs, interchange details, and risk tags

Non-direct journey — route legs expanded with operator, interchange duration, and overnight and short-interchange warnings surfaced before commitment.

Overnight train and short-interchange warning states

Overnight and short-interchange warnings

3. Hybrid class card

When inventory mixes first and second class across legs, each segment carries its own class label — no hiding it under a generic tag.

Hybrid-class journey card showing first-class and second-class legs across one route

Hybrid-class card — header flags the mix, and each route leg carries its own class label so the split is unambiguous.

Route Complexity

Stress-testing the card with edge-case routes

Harder route cases pushed beyond the simple transfer pattern, but the UI still needed to stay legible without branching into separate solutions.

Edge-case detail visible before selection

After the base card structure was resolved, I stress-tested it against Rail Europe's harder cases: overnight journeys, short interchanges, expanded slot lists, operator-specific legs, and mixed-class routes. The goal was to make the edge cases readable without creating a separate UI pattern for each one.

Rail journey option showing the first segment of route details
Rail journey option showing the middle segment of route details
Rail journey option showing the lower segment of route details
Expanded view of slots

Expanded slot view — alternate departure times, duration, and price differences visible together.

Dependency Warnings

Surfacing hidden connections between hotels and stations.

Hotel-to-station proximity wasn't a fixed property — it changed depending on which hotel and which train a user had selected.

Warnings when a change affects station proximity

The design surfaced contextual warnings when a hotel change or train/time-slot change would affect how far a user was from their station. That dependency appeared inside the package flow rather than staying hidden until later in the journey.

Hotel and station dependency warning after itinerary changes

New train/time slot selected — station distance may change.

Dependency warning state comparing station proximity after itinerary updates

Hotel changed — rail station proximity needs re-checking.

Dependency warning state showing change impact on nearby station access

Updated hotel context changes how convenient the selected station is.

Availability & Recovery

When trains disappear, the package shouldn't break.

Rail Europe availability was dynamic. Trains that existed at package-creation time could become unavailable later — and some searches returned no options at all.

A recoverable path instead of a dead end

The fallback state explained what happened and guided users back to the Add to Day → Transfers flow to choose an alternative. The package stayed editable; nothing required a restart.

Fallback state when trains are unavailable for that day

Unavailable train state — clear explanation with a recovery path back to transfer selection.

Beyond Selection

Completing the rail journey beyond selection.

Selection was the midpoint, not the end. Rail components carried forward into quotation views, booking review, package summary, and post-sales — so both customers and Holiday Experts saw the same rail context throughout, not just during selection.

Rail component across booking confirmation, itinerary, and day-detail post-sales surfaces

A sample of the downstream surfaces — booking confirmation, day-wise itinerary, and post-sales day detail. The same rail component ran across all of them.

Mobile & Holiday Expert

The same logic, scaled across channels.

Rail Europe wasn't a desktop-only feature. The same system — itinerary placement, transfer flows, age-based pricing, and fallback states — had to hold across mobile and Holiday Expert DIY package creation.

Mobile and expert-led continuity

On mobile: package discovery with rail callouts, itinerary view with train cards, transfer changes, filters, and fare-update review. On Holiday Expert DIY: route creation with internal trains, selected-route previews, traveller-age capture, and rail-specific age guidelines for Youth, Adult, and Senior categories.

Mobile App

Mobile package flow with rail continuity across itinerary and transfer views
Mobile discounted-pricing communication on the review page

Age-based discounts are communicated at review in the current implementation, with earlier surfacing planned as the flow matures.

Holiday Expert DIY

HE DIY Select Route step showing Round Trip Flights plus Internal Trains option selected

'Round Trip Flights + Internal Trains' selected — automatically includes a Paris–Madrid rail leg.

HE DIY Rooms and Guests modal asking for traveller age groups before the itinerary is built

Age groups captured before the itinerary builds — European rail detected, discounts applied from the start.

System-generated recommended European package shown to Holiday Expert for the traveller

System-generated package — '7 days in France & Spain' assembled and ready for the Holiday Expert to share.

New Rooms and Guests experience on the recommended package showing youth age discounting because system knows it includes European rail transfers

Rooms & Guests on the recommended package — system recognises European rail and surfaces youth age discounting inputs.

Outcome

One system, every surface.

Rail Europe became a package-ready travel component across CMS, customer-facing flows, and Holiday Expert workflows.

Configurable in CMS

P2P and Pass Transfer setup with rate plan attachment and rail metadata.

Day-wise itineraries

Compact train cards inside itinerary packages with route, class, and timing.

Add/Change Transfer flows

Slot comparison, per-person pricing, and interchange logic in one view.

Age-based pricing

Youth, child, and senior fares surfaced contextually without disrupting search.

Availability resilience

Unavailable-train fallback and fare-update review built into the booking flow.

Quotation and post-sales

Rail context carried forward into quotation, booking review, and post-sales.

What I'm most proud of is how the system balances density and clarity. Compact itinerary cards help travellers understand included train journeys at a glance, while expanded rail views reveal route anatomy, station proximity, time slots, class, operator, interchanges, and risk tags only when needed.