Travel

Reimagining Flighty: one system across multiple tiers, devices, and experiences

Bringing Flighty’s design system together across files, components and code, so a growing team can build with it without losing what makes Flighty feel like Flighty.

Capabilities
ProductDesign Systems
IndustryTravel
TimelineMay–Sep 2026
ScopeCustom iOS and Apple Watch, light and dark

The stakes

Flighty is an Apple Award-winning iOS app, and it already had a strong product loved by users all across the world and a distinct design language. But over time, its design system had spread across different files, components, and code. The shipped app had become the most reliable reference for how things should look and behave.

A lot of the thinking behind those decisions still lived with founding designer Markus Aarstad.

With new designers and engineers joining the team, that gets harder to sustain. Every new person would need to ask how something worked, look through existing screens, or make their own interpretation. Over time, those small differences could start changing what made Flighty feel like Flighty.

The goal wasn’t to introduce a new design language but rather to upgrade the existing one. It was to bring it together, make the decisions behind it easier to understand, and give the team a system they could build with.

We also wanted the product team spending its time improving Flighty, not piecing the design system together.

Approach

I started by auditing the existing system against the shipped product, looking at what was consistent, what had drifted, and where the gaps were.

Markus and I agreed on the approach and the decisions that needed to stay. From there, I worked through the system, keeping what was distinctly Flighty, fixing what had drifted, and rebuilding what was missing.

The product was the reference throughout. Its travel-specific interactions, existing design language, iOS conventions, and the way the team works shaped how the system came together.

1. Built around Flighty, not a generic component library

Flight information comes with its own set of interactions and conventions. Flight statuses, airports, aircraft, live tracking, and travel-specific details all need to work together.

I kept those patterns specific to Flighty and organised the system around them, rather than trying to fit everything into a generic component library.

Unpublished base variants, like the gate symbol, sit under the published badges, so gate and baggage-belt badges are built from the same parts.
Unpublished base variants, like the gate symbol, sit under the published badges, so gate and baggage-belt badges are built from the same parts.

2. Bringing the strongest patterns across the product

Flighty already had some very well-considered interactions. The challenge was making sure that same level of quality carried across the rest of the experience.

From flight search and Passport to onboarding, I worked through existing flows, identified the strongest patterns Markus and the team had established, and carried them into places where the experience had become inconsistent.

Missing screens were also rebuilt, so the system could represent complete flows rather than isolated components.

An airport’s Daily Performance: departures, arrivals and totals, built around the disruption data travellers care about, in light and dark.
An airport’s Daily Performance: departures, arrivals and totals, built around the disruption data travellers care about, in light and dark.
The Airport Detail Page, mapped as a main sheet and its sections, each built from shared headers, table rows, tags and action groups.
The Airport Detail Page, mapped as a main sheet and its sections, each built from shared headers, table rows, tags and action groups.

3. Base components underneath the experience

I introduced a layer of unpublished root components that sit underneath the patterns and features designers work with.

These shared building blocks make it easier to create new features from existing components, rather than rebuilding the same structures each time.

4. Adding range where the product actually needs it

Dark mode, illustrations, charts, and the Flighty Pro tier needed more than a minimal colour palette.

I rebuilt the foundations around 12 colour ramps with 15 steps each, alongside 12-step alpha ramps for black, white, and utility colours, so status colours hold up on any surface, in light and dark.

Flighty’s content, including flights, user states, and units, also became variables. Designers can now test realistic content and edge cases without waiting on someone else to provide the data.

Some of the finalised colour ramps: 15 steps each, from 25 to 1100, including the newly designed Flighty Pro purple. The longer ramps were designed specifically to work across both light and dark modes.
Some of the finalised colour ramps: 15 steps each, from 25 to 1100, including the newly designed Flighty Pro purple. The longer ramps were designed specifically to work across both light and dark modes.

5. Keeping the semantic styles intact

Flighty’s semantic styles were already connected to the team’s internal system and carried through to production.

Changing them would have created unnecessary work for engineering. Instead, I kept that layer intact and focused the cleanup underneath it, rebuilding the colour primitives, ramps, and alpha values.

The underlying structure became more organised without disrupting what the team was already using.

Utility colours keep their semantic names and now point to the rebuilt primitives, with separate light and dark values.
Utility colours keep their semantic names and now point to the rebuilt primitives, with separate light and dark values.

6. Following iOS conventions, the Flighty way

The system needed to feel native to iOS without losing the details that make Flighty recognisable.

I worked with Apple’s existing structure, incorporating Liquid Glass into materials and buttons, supporting iOS 18 and iOS 26 layouts, and using SF Symbols where appropriate.

I also kept the component states specific to what iOS actually uses, rather than carrying over conventions from other platforms.

Glass buttons are one of the button styles that carry Flighty’s Liquid Glass treatment across emphasis levels and states, in light and dark.
Glass buttons are one of the button styles that carry Flighty’s Liquid Glass treatment across emphasis levels and states, in light and dark.
One modal structure with segmented header, body and footer slots, for text or custom content, with or without an image banner. The goal is to make it easy for the team to swap and customise these patterns the way they want.
One modal structure with segmented header, body and footer slots, for text or custom content, with or without an image banner. The goal is to make it easy for the team to swap and customise these patterns the way they want.

7. Keeping flight status as its own foundation

In Flighty, status colours do much more than communicate a visual state. They tell travellers whether a flight is on time, delayed, or cancelled, often at a glance.

They were also one of the strongest parts of the existing system.

Markus and I decided to preserve status as a separate foundation layer rather than fold it into the general semantic colour system. That allows the team to adjust how flight statuses are represented without affecting colours across the rest of the interface.

Flight status as its own variable group: each state (early, on time, delayed, cancelled, diverted) has its own foreground and fill, pointing to the rebuilt colour ramps with separate light and dark values.
Flight status as its own variable group: each state (early, on time, delayed, cancelled, diverted) has its own foreground and fill, pointing to the rebuilt colour ramps with separate light and dark values.

8. Testing a different approach with Status Cards and the Flight Cell

The Flight Cell had 62 variants, each a mix of status, stage and flight type, so changing one badge meant editing many of them. The obvious fix was to cut it to around 18 generic variants, but then designers and developers would have to work out which combinations actually occur in Flighty.

So I split it into two layers: a compact UI layer of shared parts, built once, and a UX application grid of the real flight states (62 configurations, 124 variants across light and dark).

Status Cards follow the same structure. The base card holds the status colours, and the grid shows what it should say at each stage of a flight, for Pro and Free users.

These are the first places we’re testing this approach. If it works for the team, it can extend to other contextual components.

Status Card colours as their own foundation, in light and dark.
Status Card colours as their own foundation, in light and dark.
The compact UI layer: tags, icons and status elements, each built once and reused in every Flight Cell.
The compact UI layer: tags, icons and status elements, each built once and reused in every Flight Cell.
Status Cards, UX application grid: one card mapped across a flight’s timeline, with Pro and Free messaging.
Status Cards, UX application grid: one card mapped across a flight’s timeline, with Pro and Free messaging.

9. Fewer global components, with more room to reuse

This was the biggest part of the rebuild and cleanup. I consolidated repeated structures into a smaller set of global components. One header, list and table structure now supports pages, sections and cards, and cards, modals and sheets share the same header, body and footer slots.

Each one is built to be reused across the product, so new features don’t keep growing their own versions of the same thing.

Outcome

The final system gave Flighty’s growing team a shared reference for both how the product was built and the decisions behind it. Designers and engineers could build on existing patterns with the rules, states, and exceptions already laid out that were contextually relevant to the product, the industry, and the team’s way of working.

Repeated elements used shared components, making them easier to maintain together without losing the variations the product needed.

Each component was deliberately structured, with notes on what to refine and optimise in the next stage of the system’s development—including preparation for AI-assisted production implementation. This gave the team a clearer starting point for extending Flighty, with less to piece together or recreate as more people joined and as the team used AI more in their product design and development workflows.

Work Showcase

More Case Studies

The Complexity Gap

You know the product and industry inside out. The people buying or using it bring different levels of knowledge and experience. The work is in making that complexity manageable throughout the product—helping beginners get started, supporting people as their needs grow, and giving experts the depth and control they need.

The Retention Gap

Getting someone to try a product is one thing. Becoming part of their day-to-day workflow is another. That comes down to how well it helps them do their job—how naturally it fits into their work, how much easier it makes important tasks, and whether it gives them a reason to keep using it.

The Growth Gap

As your business grows, the experience doesn’t always keep up.

Your brand, website and product evolve at different speeds. Some parts reflect the business you’ve become; others still belong to an earlier stage. Customers see one company, but the quality of what they see and use can leave them with very different impressions.

Your teams feel that disconnect too. Marketing works around a website it has outgrown. Product and engineering rebuild patterns that should be shared. Sales spends time explaining value the experience should already make clear.

Each workaround helps someone move forward. Together, they make growth harder to sustain.

Cursor Text