At Cruise, we’re building the future of transportation. With hundreds of our own engineers — not to mention the countless others around the world — working to solve the generational challenge of building self-driving technology on complex urban roads, it’s only a matter of time until that technical feat is achieved and deployed at scale.
Therefore, to differentiate ourselves and find product-market fit, we must design an amazing user experience for our customers that goes beyond the core technology.
After two years of working on our internal tools and designing our mobile rideshare app (join our waitlist here!) from the ground up, I transitioned to work on exactly that with the Cruise Origin, our purpose-built rideshare autonomous vehicle that aims to revolutionize transportation at scale.
The Complexities of Designing the Future
Since the Origin is unlike any existing car—take, for example, its lack of a steering wheel, multiple in-car tablets, and unique campfire seating—, my team and I found ourselves in uncharted territory, working through questions such as:
- How do we communicate with pedestrians and other drivers without a human at the wheel?
- How do we design for safety and trust throughout a rider’s journey?
- How do we imbue delight into key moments?
- How do we help riders personalize their cabin experience?
- How do we leverage sound in tandem with visuals to create a cohesive, multi-sensory experience?
Given the complexity of these questions and the multitude of surfaces available on the Origin, it was critical for us to design, validate, and showcase our proposed end-to-end Origin experience to leadership before handing off to engineering. To do this, we needed to get creative with our prototyping approach. The perfectionist and engineer in me soon realized that the only way to make the experience truly feel real was to actually make it real, with code.
The Benefits of Prototyping in Code
1. Iterate rapidly at any level of complexity.
The declarative programming style and heavy use of reusable components inherent to languages like SwiftUI — a language that is quickly becoming the designer-engineer’s prototyping platform of choice, and the one I chose for this project—make replicating Figma designs a breeze, and let me spend more time experimenting with interaction models and animations, and building out various user paths and edge cases with complex logic.
Since the UI layer and logic layer can be separated in code, there’s no need to manually rebuild prototypes or re-time effects by hand like is often required with tools such as Principle, After Effects, and Origami.
This means I was able to do things such as:
- Update the visual design of any component and have it immediately propagated to all instances.
- Build a “Control Center’’ for the app that lets me adjust various settings like whether the user is a first-time rider, whether I want to test the end-to-end experience or focus on a singular moment, and which state a particular button interaction should elicit.
- Automatically test all my screens with different sets of mock data to catch edge cases and localization issues.
2. Think like an engineer.
One of the key advantages of being a technical product designer is the ability to empathize with the perspective of your engineering partners. Designing with code forces you to think seriously about constraints, and encourages an upfront investment in systems-level thinking for components and interactions that will account for edge cases and scale to accommodate new requirements down the line.
Plus, having gotten your hands dirty actually building your designs, you can streamline the handoff process and even help engineers with design QA by shipping production code yourself, saving them precious time to focus on core feature development.
3. Build something that feels real, because it is.
When making product decisions, one of the best forces of persuasion is a well-presented visual. The closer the visual can resemble reality, the more likely your product, engineering and leadership partners will get behind an idea. And what more closely resembles reality than a fully functional, coded app?
Traditional prototyping platforms, while powerful, are typically built for non-technical designers, and by design forfeit functionality and complexity in favor of low barriers to entry and simplicity. Therefore, there are some things that can only truly be done in code, such as:
- Real, interactive Mapbox maps with production styles, dynamically generated routes, and animated elements.
- Server-based state changes that enable synced actions across multiple devices.
- Device-level features like haptics, notifications, fluid 2D/3D animations, and more.
Today, with a fully functional prototype implemented and systems in place to enable continued rapid iteration, I am even more convinced of the plethora of benefits prototyping in code provides.
The tactile feeling of haptics, buttery smooth native animations, and “choose your own adventure” logic that comes with building my own designs has not only improved my design thinking, but has also revealed unforeseen edge cases, improved my coding abilities, and provided our team with the superpower of visualizing the entire experience without any engineering support.
If you’re a product designer or prototyper and this type of process appeals to you, consider joining our team.