makeyourtravell.com started as a travel discovery idea, but the implementation quickly became a much bigger systems problem. The public site had to help travelers browse and book experiences in Bulgaria, while the product behind it had to support suppliers, administrators, payments, content updates, translations, and booking operations.
That pushed the project into a shape we like a lot: a clear frontend deployed on Vercel, a focused backend on Render, and a data layer built to support marketplace logic without turning into a mess.
What we were actually building
Travel Maker is not just a marketing website. It is a multi-role product with three connected surfaces:
- A public customer experience for discovery, search, booking, checkout, articles, and support content
- A supplier area for managing services, availability, bookings, and payouts
- An admin area for moderation, CMS content, statistics, reviews, notifications, and operational control
That matters because the architecture had to support much more than pretty landing pages. It had to support real workflow state.
How the frontend is done
The frontend lives in a single Next.js 16 App Router codebase with React 19, TypeScript, and Tailwind CSS 4, and it is deployed on Vercel.
The public experience is centered around the /home flow and the service catalog. The homepage is assembled from structured sections such as hero, booking, featured group tours, popular trips, attractions, categories, testimonials, partners, and travel memories. The services page then takes that discovery layer into a more operational search experience with filters, sorting, pagination, featured tours, and map-aware content.
What we liked about this setup is that the same codebase also contains the supplier and admin areas. That made it easier to share UI patterns, auth-aware data access, and typed client logic without splitting the product into multiple frontends too early.
Another important part was language handling. Travel Maker supports Hebrew, English, and Bulgarian. Hebrew means real RTL support, not just translated strings. The frontend updates the document direction and language attributes, stores the preferred locale, and can request missing translations from the backend instead of forcing every new key to be pre-translated before shipping.
How the backend is working
The backend is a Fastify and TypeScript service deployed on Render. PostgreSQL and Redis are also hosted on Render, which keeps the operational footprint small and predictable for a product at this stage.
The API is responsible for the actual business logic: auth, services, bookings, supplier tools, admin actions, translations, CMS content, reviews, guides, notifications, discount codes, payouts, and payments. That is where the real product lives.
Redis is used for BullMQ queues, which handle the background work that should not depend on a browser request finishing successfully. In Travel Maker that includes:
- SLA monitoring for pending bookings
- Escrow release jobs
- Payout batch processing
- Email retries and transactional notifications
- Cleanup tasks
- Review request delivery
This made the backend much more resilient than trying to do everything inline during a booking request.
How a booking moves through the system
One of the most interesting parts of the project is that booking is not a single flow.
Travel Maker supports private bookings, group tours, platform-owned experiences with guide assignment, supplier-owned services, approval-required bookings, instant bookings, discount codes, and different payout paths. The booking service has to validate all of that before a booking can be created safely.
In practice, the flow looks roughly like this:
- A traveler finds a service in the public catalog and selects dates, guests, or seats.
- The backend validates the service state, booking type, guide availability when needed, and whether the request is a private or group booking.
- Pricing is calculated, including service-level discounts and optional discount codes.
- Commission and supplier amounts are derived from the booking model.
- A Stripe payment intent is created.
- After successful payment, the payment is marked as held, confirmation emails can be sent, and the booking continues through approval or fulfillment logic.
- Later jobs handle release and payout operations once the booking reaches the right state.
This is also where the backend earns its keep. A travel marketplace cannot rely on a single happy-path checkout assumption when different service types behave differently.
The biggest challenges we had
The hardest part was not choosing frameworks. It was keeping the product understandable while the rules kept growing.
1. One product, three audiences
Customer flows need to feel smooth and reassuring. Supplier tools need operational clarity. Admin tools need control and visibility. Keeping those experiences in one system without making the UX or the codebase feel tangled took discipline.
2. Multilingual travel UX, including RTL
Supporting Hebrew, English, and Bulgarian affects much more than labels. It changes layout direction, content assumptions, copy review, and the speed at which new features can be published. The translation workflow had to be practical enough that product work did not stop every time a new string appeared.
3. Booking state is more complex than it looks
Hotels, tours, attractions, group tours, guide-assigned experiences, instant confirmation, approval windows, and cash restrictions do not all follow the same business rules. We had to keep that logic explicit so pricing, availability, and booking status stayed trustworthy.
4. Payments and payouts are never just one integration
Charging a customer is only the start. You still need to think about escrow timing, refunds, supplier settlement, and operational fallbacks. Travel Maker’s payout layer reflects that reality with multiple payout paths, including Stripe Connect, virtual card support, and manual handling where needed.
5. Deploying across Vercel and Render
This split worked well, but it created coordination work. Frontend URLs, CORS configuration, auth and magic-link behavior, environment variables, queue workers, and webhook handling all need to stay aligned across two deployment platforms. That is manageable, but only if the boundaries stay clear.
Why this setup made sense
For this stage of the product, the Vercel plus Render split gave us a good balance. The frontend stayed fast to ship and easy to evolve, while the backend had enough room to own the complicated parts of the marketplace: booking state, background jobs, payment events, and supplier operations.
The biggest lesson from Travel Maker is that travel products become operational systems very quickly. Once that becomes clear, the goal is not to make the architecture look simple. The goal is to make the complexity legible, so new features can be added without breaking the trust of the people using it.