B-Travels
A platform for travel agents in Japan and the travellers they plan for, in Japanese and English. I led the frontend from the very first build all the way to the whole platform.
- Year
- 2024 – 2025
- Role
- Lead frontend developer
- Platforms
- Agent portal and traveller app
- Stack
- React · Next.js · TypeScript · TanStack Query
B-Travels – the agent portal – b-travels.com ↗The brief
Replace the phone calls, documents and fax machines with one place where everyone is looking at the same version.
End the version question
When I started, quotations were typed up in documents, and bookings were spread across email, spreadsheets, group chats and fax. One quote could take hours of manual work, and nobody could say for sure which document was the latest.
One platform, two audiences
I was building for two very different people at once. Agents run their whole workflow in the portal, and travellers browse and plan trips in the app, both reading the same data. An agent's screen is packed with detail a traveller never needs to see, so I gave each side its own view of the same records.
Ship at startup pace
There were two apps to build and a small team: a product manager, a backend engineer, the stakeholders, and me as the only frontend developer. We shipped every two weeks. A lot of my job was building, and a lot of it was telling everyone before the sprint started what couldn't make it in, and why.
Process
The booking step was drawn before it was rebuilt
Accommodation is the build that went back to Figma before it was rewritten. Agents told us the booking information was hard to find, so it was a layout problem. We worked it out on one board, starting from four reference checkouts, then two directions in B-Travels' own chrome, and finally the version that shipped.
Accommodation booking – R&D
We skipped wireframes for this one. Everyone already understood the flow; the problem was finding things in it. So we started by pulling apart the checkouts on Airbnb, Booking, Skyscanner and Agoda, which all solve the same problem but fit very different amounts onto the page. Then came two versions in B-Travels' own chrome, one led by images and one led by the booking summary. The version that shipped puts guest details, booking details and the price summary in a single column. It shows the hold deadline with its timezone, and it tells the agent plainly that nothing can be changed after booking.
The accommodation board – four reference checkouts, two directions in B-Travels' chrome, and the layout that shippedThe turn
I believed
An itinerary is an array of days with times on them.
What happened
Multi-day stops broke the moment a trip crossed timezones. Worse, moving Day 3 to Day 2 quietly shifted every booked activity underneath it. It showed up first on hotel check-in and check-out, which sit on the first and last card of each day. The agents caught it before any traveller did, but only just.
What changed
I rebuilt it on relative offsets, with an explicit timezone for every stop. The founder didn't want any kind of friction in a drag-and-drop, and I didn't get my way on it. So we drew the line by stakes rather than splitting the difference. The cards that can’t move without cascading, the anchored multi-day ones, aren’t draggable at all. Everything safe still drags freely. The lock isn’t arbitrary: a card is immovable exactly when moving it would rewrite the stops around it.
I believed
A point of interest is a Place ID. Cache the details from Google, render the pins, move on.
What happened
We ran into two problems at the same time. Google's terms don't let you keep most place data for long. And the things agents actually sell aren't in Google at all – which entrance to use, which guide to book, who will open up at 6am if you ask. Anyone can look a place up on Google, so what makes an agent's itinerary worth paying for is the notes they add to it.
What changed
We ended up with a mix of both. A thin layer of cached Google data, keyed by place ID, sits under a proper point-of-interest record that agents write themselves. Nobody had planned for it, so we made it a target for the next sprint, and we built it.
I believed
More generated code meant moving faster.
What happened
Reviewing two thousand lines of a map layer I hadn't written was slower than writing four hundred myself. At late night I couldn't find a clustering bug in it, because I'd never worked out in my own head how it fit together.
What changed
I started limiting generation to one module at a time, against a shared types package. It looked slower on paper, but we shipped sooner.
Decisions
The builds worth naming
These are the parts I built that agents spend most of their day in. Building them set the pattern for everything I built after.
Multi-step quotation system
Agents can open the client's PDF at any step, and the one that gets sent is generated right then, so it's never out of date.
Agents used to type everything into a document, copying customer details out of old emails and double-checking phone numbers in group chats. I built a flow that takes them through it step by step. It pulls in linked contacts, fills in the tour details for them, and lets them open a PDF preview whenever they want. The PDF the customer receives is only generated at the last step, so it's always the current version. Every version is tracked as well, which matters once an agent has several quotations on the go.
Drag-and-drop itinerary builder
Travellers plan their trip from a list their agent has put together.
I built the builder so agents can drag attractions, restaurants and hotels onto each day to make a master itinerary, and travellers plan from that list. When anyone moves something around, the distances between stops update straight away.
Accommodation searching
When an agent searches a hotel, they can see at a glance which of their selected POI sit near each option straight.
The first version leaned on the API, and its results didn’t always match what the real-time search had shown which made hotel search slow and sometimes misleading. I fixed it so there’s one consistent set of results the whole way through. Then I focused on what an agent needs first: which of their selected points of interest sit near each hotel. I surfaced that proximity against every option, from our own data, so it’s visible without digging. I also tuned the map layer against the real-time search running behind it, keeping the two in step as results come in.
Task & supplier tracking
Every itinerary makes its own task list, and an update in one place shows up everywhere.
I built it so each item on an itinerary, whether it's a hotel, a meal or a transfer, turns into a task, so agents can see what still needs sorting out without keeping it all in their heads. They assign suppliers to those tasks, like the tour guide, the coach driver, or whoever is providing the gift for a special occasion. Costs are logged against each one, and agents can see what's been paid and what's still outstanding in one place, instead of across a pile of spreadsheets.
Points of interest library
Both apps pull from the same library, so a place only needs adding once.
One place for every point of interest, each with its own details, images and tags. Agents can browse the library and pull places straight into an itinerary while they're building it, without switching to another tool.
The POI library – master records, tags and category. The portal runs in Japanese and English; this is the Japanese view.Impact
87% faster quotations – two hours down to fifteen minutes, the founder's own estimate as a working travel agent.
Everything in one place, so nobody digs through email, fax and group chats for the latest version anymore.
1 → 6 modules, covering the full workflow from itinerary planning to invoicing.
Both the B2B and B2C products shipped to production, and real agents and travellers use them.
Jun … worked with us on our SaaS project for just under two years in a fully remote setup. She communicates well, is easy to work with, and is generally proactive in clarifying requirements and following through on tasks. As an engineer rather than a designer by role, she stepped in to support design ownership when needed while being receptive to feedback and consistently focused on delivering practical and reliable solutions.
Reflection
There was a document open, customer details being copied out of an old email, and the phone number being checked again by phone, email or group chat. Then I watched the same quotation go through the new flow in about fifteen minutes. Seeing both taught me a lot about what an agent needs to see at each step, and what can wait.
I worked directly with the founder, a product manager and a backend engineer, deciding together what to build next and shipping every two weeks. Building for two audiences at once meant making the big architecture decisions early, and I've kept doing that since.
Differently, today
Since this project I pay a lot more attention to booking flows when I'm planning my own trips. I notice where the important details are, whether a hold deadline says which timezone it's in, and what I won't be able to change once I've booked. I bring all of that into every booking or checkout flow I work on now.
More projects