Skip to content

Amerix.us

A brand new, decent-looking tour booking site for Amerix, built from scratch on Next.js and Strapi

Amerix sells tours around the United States, group ones and individual ones. Think of an East Coast tour with Niagara, or the region pages, like the one for Minneapolis. The sale of the different tours basically happens on the company's own site. Behind it there's a CRM, and that's where the staff work with the bookings and enquiries.

I did this whole project alone. That meant moving the old setup and the CRM off the old host, supporting the WordPress site all the way through, and building a new site to replace it.

The raw design was ready by the end of 2025. It was a prototype, pretty rough, and we used it with the client to agree on the look and the map of pages. Later it helped a lot in creating the new site itself. The idea to rebuild was there from the very beginning. But before any building, the old setup had to move.

The move

Everything lived on an old Ukrainian shared host: the WordPress site that sold the tours, the CRM, and a few smaller services around them. I moved all of it onto a Kubernetes cluster and put Cloudflare in front. That took some time, for sure, because every move meant checking that the data stayed consistent, and the CRM had to keep working the whole time.

The WordPress site went first, since it was the thing still selling tours. Once it sat on the cluster, it was on one network with everything I was about to build, and that's what later let the content script read the old database directly, instead of collecting the old website page by page over the internet.

By the end the cluster carried everything in one place: the new site and its content backend, the databases, the storage for every file, the translation server, the CRM, and the old WordPress site still taking orders beside them. The translation server runs there with the rest, so there's no subscription to pay for it, and a tour photo uploads into storage that's already paid for.

For the CRM the task was clear: no downtime. It went in a few parts. First I moved the host behind Cloudflare, so the traffic stopped going straight to the Ukrainian host and went through Cloudflare instead. Then I prepared a separate CRM deployment in the cluster, took a snapshot of the database and started the new CRM running on its own. Its database was connected in sync with the old one, and I made sure all the new data kept coming across from the old database while they were in sync. Once it had, I switched the route inside Cloudflare to the new Kubernetes instance. That was the whole cutover, and nobody had to stop working for it. The CRM runs faster there, too.

The move paid off in two ways you can put a number on. Hosting went from about $250 a month on the old server to under $100 on the cluster, and with more resources than before. And after the switch to Cloudflare the WordPress site got over 100% more users. The client told me he had never seen those numbers before. A Google Ads campaign was running at the same time, so of course part of that is the ads. It's a switch plus optimization, and it's still a win. Cloudflare caches the static parts, so the site and the CRM open quickly from anywhere in the world.

The old site

WordPress support ran alongside all of this, continuously: fixing bugs, updating code, making it faster. We made it faster, never fast enough. And that old site was really a stack of plugins. The tour catalog, the custom fields, the ordering, the page cache, the image compression, the forms, the search-engine tags and the file browser were each a separate plugin, some of them with a paid tier, and a few jobs were done twice by plugins that didn't know about each other. The client was paying to keep that whole arrangement, year after year, just to publish a tour.

You could see it in small places. The heading on the tour calendar page, the one that names the year of the tours, lived inside the template, so changing one word of it meant waiting for a developer. I moved it onto a field the client edits himself and kept the old sentence behind it, so the page still reads right while the field is empty. The new site is pretty much that same move, done for everything.

The new site

When the client asked me what technology is right to build on today, the answer was Next.js with Strapi as the backend, and Tolgee with next-intl for the languages. It would be supportable, and we could add languages to it. For me this combination is now just the basics of how you do a multi-language website, and every site I build from now on starts from it. The FAET faculty site uses the same base, though it's a separate project.

We started the new site after the migrations were done, early in 2026. The build took a couple of months. Then came a round of revisions, a lot of back and forth, from me to the client and from the client to me.

What came out is a tour catalog with filters and a map view, and each tour has its own route map with points of interest along it. The filters are one question to the server. It takes the countries, the regions, the departure city, the destination, the length, the price range, the month, the format, the free text and the sort order all at once, and it answers with a page of tours plus a count against every filter option, so a visitor sees how many tours match before ticking the box. Anybody can browse it without an account.

Booking goes in steps: pick the tour and a date, add extras, fill in your details, review. The price updates live as you go, and the server calculates it. Every change on the form asks the server and gets the whole bill back, itemized: the price per traveller, the tour itself, each paid extra with its unit price, each activity, the discount and the total. The booking widget and the summary next to it read that same answer, so the two of them can't disagree about what the trip costs. There are coupons, and hotel and transport levels to choose between. The site takes the booking and records what has been paid against it.

The site and the CRM are connected. When a visitor books a tour or sends an enquiry, that becomes a record in the content backend, and a sync pushes it into the CRM as a contact and a lead. That's where the staff pick it up.

flowchart LR V[Visitor] --> S[Tour site] S --> C[Headless CMS] C --> DB[(Content database)] C --> M[(Media store)] S --> B[Booking funnel] B --> R[Booking record] R --> X[CRM sync]

Customers get a dashboard with their bookings, reviews, enquiries and profile, and they can sign in with Google. The site works offline and installs like an app, and the forms have a bot check. Google Tag Manager runs on it under Consent Mode v2. Then a couple of small things that matter to the person booking. A group tour whose dates have all passed opens on the individual tab and says why. A tour priced on request asks for an enquiry instead of showing a zero.

The catalog is mostly photos, so the site serves them as WebP. AVIF would save a little more space, but it takes 5 to 20 times longer to encode, and on a catalog like this that would make image conversion the slowest thing on the site. WebP keeps almost all of the saving without that cost.

What the client edits

And this is the main idea of the whole project: the client runs the content himself. He edits tours, pages, destinations, discounts and redirects in Strapi on his own, and every field has a plain description of what it's for. Any text on the site, down to a button label, he changes in Tolgee.

The destinations block on the homepage even ranks itself. It shows the places the most tours go to, each with its tour count and its lowest price, both worked out from the catalog. He can take it over, pick the cities himself and set their order, and if he switches it to manual and then picks nothing, it goes back to ranking itself instead of showing an empty band. Automatic is the default, because the site has to be right in a week when nobody logs in.

A new tour goes up whenever he wants, with no developer in between. This is a real production website, and he can keep this specific design going for years by working in Strapi, which, let's be honest, reduces what you pay any other developer.

The client says it's probably one of the best-looking sites in his field, and I absolutely agree. Months later I opened it again to update dependencies, and it still looked and felt right: really responsive, well built, and it will stand for a couple of years for sure.

amerix.us

Stack

  • Next.js
  • React
  • Tailwind CSS
  • Apollo Client
  • GraphQL
  • Strapi
  • PostgreSQL
  • MySQL
  • Tolgee
  • next-intl
  • Leaflet
  • PWA
  • Google Tag Manager
  • WordPress
  • Cloudflare
  • Kubernetes
  • k0s
  • Helm
  • CloudNativePG
  • SeaweedFS

Credits

    • Amerix.us
    amerix.us
    • Wordmark, dark-ground and light-ground variants
    • Compact mark, dark-ground and light-ground variants
    • Captured pages of the Amerix.us tour booking site

So, what's broken?

Tell me the problem, a rough budget, and a timeline if you have one. I reply within 24h on weekdays.

Rough budgetoptional
* required