A second destination on the same engine
Žabljak sits at around 1,456 metres, is the highest town in the Balkans and the main gateway to Durmitor National Park. It has eighteen glacial lakes, Bobotov Kuk, and the Tara Canyon on its doorstep. What it did not have was a single place selling all of that.
When we finished Visit Pljevlja, it was clear the same engine could drive more than one destination. Žabljak was the natural next step, for a practical reason: rafting on the Tara, canyoning in Nevidio and jeep tours around Durmitor are sold by both destinations. Same tour, two gateways, one operator.
So Žabljak is not a new website. It is a second destination in the network, on the same codebase and in the same admin.
What "a second destination" means
Content is tagged per site through a many-to-many relation. One tour can belong to both Pljevlja and Žabljak and will appear on both sites without a single duplicated record. Bookings land in the same inbox, stamped with the site they came from.

What is specific to Žabljak:
- Its own domain and brand,
visitzabljak.me, its own logo and its own homepage - Its own theme, a blue-green "alpine" palette instead of the Pljevlja green, done through CSS variables with no second build
- Its own copy, homepage, a "Where is Žabljak" page, legal pages and fun facts, translated into all 18 languages
- Its own data, coordinates for the weather widget and a dedicated sender address for email, so SPF and DKIM always match the domain
The practical consequence: a new destination launches in days rather than months, and maintenance stays on one codebase.
Maya, an AI guide that only knows what the site knows
The site has an AI assistant called Maya. She is not decoration.

Maya runs on an Anthropic model and her knowledge is the site itself. Tours, places, guides and practical information are compiled into a knowledge base per destination and per language, and the cache is invalidated the moment something is published or taken down. She cannot quote a tour that has been withdrawn.
Three things mattered to us:
- She can prepare a booking. Maya assembles the tour, date, guest count, departure time and meeting point into a single-use token, and the guest reviews and submits it themselves on the booking form. Maya does not book on the guest's behalf.
- She never fails onto the guest. Any error, refusal or timeout ends in a polite apology and a handoff to a human, with the team notified. The guest never sees an error.
- She cannot burn the budget. A daily message cap at site level, a daily cap per visitor and a hard limit per conversation. One abuser cannot switch the chat off for everyone else.
Conversations are kept for ninety days, then deleted automatically. Once a week an anonymised report arrives on what guests asked, and that becomes the list of gaps in the content.
Booking and payment
Booking does not charge immediately. The guest sends a request, gets a confirmation, the team sets the price and deposit, then the payment link goes out.

Payment runs through Stripe, but on the site's own domain, using an embedded payment element rather than a redirect. The deposit defaults to 30%, and 1% of every payment goes to charity, visible to the guest.
After payment the guest receives a QR voucher. The operator scans it on site, marks the tour as redeemed, then as completed. A worker signed in with their own account sees the voucher and the tour, but never sees a single commission figure.
Tour pricing covers how the work is actually done: per person, per group with a base guest count and a supplement for each extra one, or per unit (two jeeps at €160). On top of that come seasonal prices, a child discount and per-tour add-on options.
Eighteen languages
The site runs in 18 languages: English, Montenegrin, German, Russian, Hungarian, French, Italian, Polish, Turkish, Albanian, Spanish, Slovak, Slovenian, Ukrainian, Dutch, Danish, Swedish and Norwegian.

Translation is not a file-by-file chore. The source text is written in English, translations are generated per language, checked structurally, then written out as versioned files that a single command applies to the database. A corrected fact goes into the English source and is re-run through every language, instead of being patched in eighteen places.
What you see on the site
Beyond tours, the whole destination is there: nature and landscapes, culture and heritage, where to eat, where to stay, ethno villages.

Places are modelled as a single record type with multiple roles, so a restaurant that is also a landmark sits in both sections without duplication. There is also a blog of Durmitor stories, a live weather widget for Žabljak, and a partner portal where local operators submit their own tours and places, with mandatory moderation before publication.
Under the hood
Backend: PHP 8.3, Laravel 13, Filament v4 as the admin, Spatie Translatable for translatable columns, mcamara localization for language prefixes, Stripe, the Anthropic API for Maya, Open-Meteo for weather.
Frontend: Blade and Alpine.js, Tailwind CSS v4 with CSS-first configuration, Vite, critical CSS at build time. No React, no Vue, no jQuery.
Infrastructure: MySQL behind Cloudflare, automatic database backups every two hours with seven-day retention, deployment exclusively through GitHub.
We write more about building tourism sites that actually take bookings in websites that generate inquiries and bookings, and about reducing dependence on foreign platforms in direct bookings vs Booking.com.
Visit the website
If you run a destination, a tourism board or a tour operator and need a platform that sells rather than merely displays, get in touch. Have a look at the other projects in our portfolio.