Product and interaction design
If you'd like to learn more, please get in touch.
Worlds are the core idea behind GoAtlas. People with a shared interest join a world to share their experiences, trade suggestions, and plan things together. World Chat is the single place where every member of a world comes to talk.
Chat is where a world comes alive. It's where a passing suggestion turns into a plan, and where members keep coming back to see what everyone else is up to.
When I started designing World Chat, I wanted two things from it. It should feel fun and joyous every time you show up, with almost no friction between having something to say and saying it. And it should bring GoAtlas's core features into the conversation, so you can plan right from the chat instead of jumping between screens.
The original World Chat covered the basics. You could send messages, share media, and react, and that was about it.
Even those basics didn't feel right. Reactions jittered as they landed, and tapping a photo made the conversation jump before the media viewer snapped open. Nothing moved smoothly from one moment to the next, so the parts of chat that should have felt the most alive felt flat instead.
As worlds started getting more active, it became clear that people genuinely liked talking in them, and that chat needed to do more than exchange messages.
At the same time, none of GoAtlas's core features lived in the chat. When a conversation turned into a plan, you had to leave the chat, go back to Home, ask Atlas AI to put the plan together, share it back into the chat, and pick the conversation up from there. If someone wanted a different time or place, the whole loop started again.
You could talk about plans in a world, but you couldn't actually make them there.
With the chance to rebuild chat, I wanted to bring talking and planning into the same place, so members could shape a plan together, adjusting the timing, location, and details to everyone's preferences, without ever leaving the conversation.
I wanted to avoid reinventing what a chat looks like, so I kept the familiar layout of bubbles, a composer, and a scrolling thread, and focused on how every interaction felt within it. I started with what members do most: sending messages, reacting, and opening media. If those didn't feel great, nothing layered on top would either.
Once that foundation felt right, we prioritised the smallest set of planning features that would meaningfully keep people in the conversation: bringing a plan into chat, asking Atlas AI right from the composer, and adjusting timing and location together.
That was enough to close the loop between talking and planning before we could prioritise a full plan creation experience inside chat.
Most group chats follow a fairly "obvious" pattern. Messages slide in, reactions pop onto a bubble, and photos open with a hard cut to a full-screen viewer. When it's time to plan, the plan lives somewhere else, and the chat only gets a link card that takes you out of the conversation to see it.
It works, but I've always felt it lacked warmth and added friction. Every interaction does its job without feeling like anything, and planning turns into a loop of leaving the chat, making a change, and coming back to tell everyone about it.
My goal was to make World Chat feel joyous to use, with interactions that feel physical and alive, while keeping it familiar enough that everything people already know about chat transfers right over. Planning should live inside the conversation, so the whole world can shape a plan together without anyone leaving the chat.
I approached the rebuild in two layers. Before adding anything new, the chat itself had to feel great to use. Only then could I bring Atlas and plans into the conversation on top of that foundation.
I started with the interactions members use most. Moving through the conversation now feels smooth and steady. Photos open into a media viewer that flows out of the bubble and settles back into it, and reactions land cleanly with no jitter. Holding a reaction charges it into a super react, a small celebration for when something deserves more than a tap.
With the core feeling right, I focused on bringing GoAtlas's agents and plans into the chat. Rather than adding new buttons or screens, I built them into the composer, the one place everyone already is.
Typing @ brings up a sheet docked above the keyboard with the world's members, Atlas, and its plans, so you can mention a friend, call in the agent, or bring a plan into the conversation from the same place.
Typing / opens a second sheet of planning commands, giving you quick shortcuts to start or shape a plan without leaving the thread.
Once a plan came together, we noticed that reaching the people in it was surprisingly hard. RSVPs happen across the whole world, and members opt in and out as plans change, so it was never clear who was actually going. Getting everyone's attention meant checking the plan, remembering each name, and tagging people one by one.
So I designed tagging by plan. Typing @plan opens a sheet with all of the world's plans. Pick one, choose which of its members you want to reach, and only the people currently in that plan get tagged.
Both build on patterns people already know from other apps, so they feel obvious in hindsight. Together, they turn the composer into the starting point for planning.
Every interaction in World Chat follows the same few rules. Things move from where they came from to where they're going, instead of simply appearing or disappearing. Motion runs on springs, so it settles naturally and can be interrupted at any moment. And the conversation always holds its place, so you never lose where you were.
To hold to those rules, I built a small motion engine that solves the physics frame by frame. Springs are calculated live on every frame and keep their own velocity, so any motion can be redirected mid-flight without a jump. Flights follow curved paths instead of straight lines: a reaction hops off the bar, sweeps across, and drops into its badge.
A message lifts out of the composer and flies into its bubble, rising into place with a small kick and a soft landing pop. The thread moves up in step with it, so nothing jumps.
Press and slide to pick an emoji in a single gesture. When you let go, it flies straight into the badge on the bubble instead of popping in. Hold it a little longer and it charges into a super react, bursting as it lands.
Photos grow out of their bubble into the viewer while the chat stays perfectly still behind it. Drag down and the blur and controls fade with your finger. Let go and the photo flies back into its exact spot, even if you change your mind halfway.
I think it's important, when you're rebuilding something people use every day, to do it with a lot of care for how it feels. I took the designs into code, building a high-fidelity prototype in SwiftUI, UIKit, and Core Animation, and studying how the best chat apps move frame by frame before building my own.
The values I picked almost never felt right on the first try. A drag threshold was a little too eager, or a spring settled a beat too slow. Changing a number, rebuilding, and running again for every tweak would have quietly killed the feel before I ever found it.
So I built a tuning sheet that reaches every interaction in the chat. Each value I care about, from spring timing to drag thresholds to how far a reaction hops, lives there as a slider I can move while the app is running. If something feels off, I pull up the sheet, nudge it, and I'm feeling the new value in the same second, right in the conversation, on a real device.