JetEye is not one product; it's a suite of tools that each serve different users in the private aviation ecosystem. My job was to make all of them feel like one product while respecting the very specific rules of the domain: cabotage, repositioning limits, runway minimums, fractional ownership, regulatory bodies. Six products, zero existing design system.
I spent the first two weeks reading (operator manuals, FAA documentation, JetEye's existing internal notes) before drawing anything. Four constraints ended up shaping every screen I designed:
Cabotage
Cross-border flight restrictions
A Canadian-registered aircraft can't fly between two US points. I designed two different disclosure policies: silent filtering for passengers who don't need to know, and explicit reasoning for operators whose pricing depends on understanding it.
Repositioning (Ferry) Flights
The 2× rule
Repositioning hours can't exceed 2× the occupied leg time. This hard rule surfaces in pricing, search results, and operator fleet configuration, so I had to encode it into every relevant calculation and prevent operators from accidentally violating it.
Empty Legs
Discounted repositioning flights
When an aircraft must reposition empty, operators can sell those seats at a discount. These drive significant marketplace behavior. I designed contextual subscribe prompts that appear only when intent is already signaled, keeping the noise down.
Runway Minimums
3,000 ft default
Aircraft can't land at airports below a minimum runway length. Rather than a required field and validation errors, I worked with engineering to default to 3,000 ft. That gives operators forgiving onboarding without punishing them for skipping technical fields during setup.
TripScope
Embeddable booking widget
Search interface for private jets: One-Way, Round Trip, Multi-Leg, Empty Legs. Embeds on any operator's website with controlled flexibility: themeable tokens for brand adaptation, locked behavior for regulatory consistency. Designed for both broker speed and passenger simplicity simultaneously.
FleetPro + WebFleet
Operator fleet management + public embed
Card, list, and map views. Operators configure what visitors see via a live-preview config panel. The private aircraft toggle uses a two-step disclosure. Hiding the tail number and hiding the aircraft entirely are different intentions, and the UI needed to make that distinction explicit without adding complexity.
Marketplace
Public discovery for passengers
Empty legs and aircraft across all operators in one browsable map view. Route-scoped email subscriptions appear only after a user selects a specific origin + destination. That deliberate step filters for subscribers who'll actually open the emails.
Screener
Operator and aircraft intelligence
1,800+ FAA Part 135 and Transport Canada operators in a filterable, expandable data table. I defaulted to operator view because research showed people think "who" before "what." Filter chips that change column semantics (e.g. "Top Bombardier Operators" recalculates Fleet Size) surface their meaning change explicitly rather than silently.
Budget Builder + Hangar Queen
Pricing and operations tools
Pricing and configuration tools for operators and brokers. Both inherit the FleetPro design language and patterns. The system dividend: when new products join the suite, the foundational components are already there.
Weekly cadence: continuous, iterative
Written story with acceptance criteria
Low-fi exploration in Figma
High-fi UI + Loom walkthrough
Design review with client
Eng build → Design QA in staging
I write the story before I design. Forcing prose surfaces edge cases and ambiguities faster than jumping into Figma. By the time I open a frame, I'm executing a known problem, not discovering it mid-design.
Cabotage: a silent filter with an honest empty state
I decided to keep filtering silent in passenger flows; explaining cabotage would add friction without value for someone who just wants a seat. But in operator-facing views where it affects pricing, I expose the reasoning explicitly. Two different audiences, two different levels of transparency for the same underlying rule.
Runway default: 3,000 ft as a model-level safe choice
Operators skip technical fields during setup. I argued that the right response to that reality wasn't a validation wall; it was a safe, adjustable default. The form pre-fills it; operators can override it. Forgiving onboarding is a product decision, not just a UX nicety.
Subscription as a contextual prompt, not a settings page
The right moment to offer empty-leg alerts is when someone has just searched a specific route, not in a settings drawer. I moved the subscribe prompt into the empty legs tab and gated it behind origin + destination selection. The result is a smaller subscriber list that actually converts.
Airport tooltips designed for 1 to N runways
Airports have between one and a dozen runways. I resisted the temptation to design for the average case; the hover state shows a compact preview; clicking expands to a full list. Designing for N rather than one was where most of the real complexity lived in this product.
Private aircraft: a two-step disclosure instead of one toggle
Hiding a tail number and hiding an aircraft entirely are different intentions; a single toggle can't hold both without ambiguity. I designed "mark as private" as the first step, then surfaced "make available with Private badge?" as a second question. One compound toggle became two clear choices.
Six products, zero system, day one
There was no pre-existing design system when I started. I had to build the system while designing the first product; every token, component, and pattern established in TripScope became load-bearing infrastructure for everything that followed. The risk was committing to patterns too early; the mitigation was staying modular and reviewing the system after each product added new demands to it.
Domain opacity
Private aviation is deliberately non-transparent: operators don't want passengers to fully understand the pricing structure. This created a constant tension: design the product honestly for the people using it while respecting the commercial realities of how the industry operates. I resolved it by always asking "who is looking at this screen?" before deciding how much to expose.
Embeddable widget with no control over host context
TripScope needs to function correctly on any operator's website, across different colors, typography, container widths, and backgrounds. I designed a token system with two levels: brand-adaptable (colors, font stack) and locked (interaction patterns, regulatory behaviors). Operators can make it look like their product; they can't make it behave incorrectly.
Priority across six simultaneous products
As the sole designer, I couldn't give every product equal time every sprint. I developed a prioritization heuristic: user-facing shipping-blockers first, system investments second, polish third. This forced me to be explicit about design debt and communicate it clearly to engineering and stakeholders rather than quietly carrying it.
Domain literacy pays back
Two weeks of reading aviation documentation before designing anything paid back constantly. You can't make a good cabotage decision without knowing what cabotage is, and stakeholders trust you more when you can talk their language.
System first is not slower
Investing in the design system upfront looked slower in the first product. It made every subsequent product faster. When Budget Builder and Hangar Queen joined the suite, the components were already there.
Edge states aren't edge
Multi-runway airports, private aircraft, empty fleets, cabotage-blocked routes. These are the product for the operators who use it daily. They were on my Figma frames from version one, not an afterthought.