Portfolio

Travel & Tourism Site: BALTIC PALACE

I den østlige delen av Mielno bygges et eksklusivt leilighetskompleks ved Østersjøen, DUNE Resort. Dette unike prosjektet minner om luksuriøse sommerresiden...

#Nettsider
Travel & Tourism Site: BALTIC PALACE

#Baltic-palace.com, teknikk for et hus ved Østersjøen

Hvem leser egentlig nettsiden til et overnattingssted? Ikke en anonym besøkende som oppdager stedet for første gang. I praksis er det som oftest noen som allerede kjenner navnet, har sett bilder et annet sted og nå vil sjekke om det stemmer. Baltic Palace har førtifire rom og leiligheter, og i den størrelsen avgjør nettopp den lesningen marginen: enten fullfører gjesten bestillingen her, eller så går hen tilbake til et bookingportal og lar provisjonen ligge der.

Bygget ligger i Pobierowo, i dynebeltet i Vest-Pommern, omtrent hundre meter fra strandnedgangen, og er tegnet av arkitektkontoret MTA Architekci. I første etasje ligger resepsjon, bar, restaurant, behandlingsrom og en SPA-sone med to bassenger og badstuer, i tillegg til konferansefasiliteter. Den blandingen betyr mer enn den ser ut til, for den gir minst tre lesere som ikke har noe til felles: et par som planlegger en helg, en familie som booker to uker i august, og en kurskoordinator som trenger å vite hvor mange som får plass i rommet.

Prosjektet ble gjennomført i 2017 og tok omtrent seks uker. Kunden leverte layout og plassering av elementer, så min del var å oversette det til maler, en innholdsmodell og responsiv oppførsel, ikke å bestemme uttrykket.

#Bestillingsveien og der den ryker

Oppdraget var ikke å skape etterspørsel. Merkevaretrafikken fantes allerede, og siden skulle slutte å lekke den. I praksis betyr det at bestillingsveien må tåle det folk faktisk gjør, ikke det en demonstrasjon gjør. De åpner to faner og sammenligner datoer. De trykker tilbake midt i skjemaet. De begynner på telefonen på toget med ustabil dekning og fullfører på laptop tre dager senere. En bestillingsflyt som bare fungerer når ingenting uvanlig skjer, fungerer bare i demonstrasjonen.

Bestillingen går gjennom en egen modul med Stripe-integrasjon, validering på serversiden og lagring i PostgreSQL med AES-256-kryptering. Validering på serversiden er ikke overflødig ved siden av nettleservalideringen. Skjemaet tar imot et datointervall, og et datointervall er det feltet som er lettest å ødelegge i et hvilket som helst bestillingssystem: tilbakeknappen, to åpne faner, en dato som var ledig da siden ble lastet og opptatt da skjemaet ble sendt. Alle disse tilfellene ser ut som et helt gyldig skjema fra klientsiden.

Frontenden bygger på Tailwind CSS og media queries, med WCAG 2.1 for øye. Universell utforming er ikke en formalitet her. En stor andel av gjestene er eldre, og et bestillingsskjema som leses på telefon i sollys trenger en kontrast som elegant lysegrått på hvitt rett og slett ikke gir. Av samme grunn har skjemafeltene synlige etiketter, ikke plassholdere som forsvinner ved første tastetrykk.

#Bildematerialet er hovedinnholdet

Galleriene og presentasjonen av bygningskroppen er den tyngste delen av nettstedet. Arkitektur- og interiørfoto er primærinnhold her, ikke pynt, og en komprimering som gjør pussen om til en flekk fjerner husets sterkeste argument. Bygningskroppen vises som en tredimensjonal modell i Three.js, og bildegalleriene lastes dynamisk gjennom GraphQL med srcset.

GraphQL har en konkret begrunnelse her. Et vanlig endepunkt returnerer alle felt for hvert bilde i et galleri, også de en listevisning aldri bruker, og én enkelt forespørsel om et dusin objekter med fullstendige metadata kan veie mer enn miniatyrbildene selv. En spørring som uttrykkelig ber om tre felt, flytter den kostnaden fra nettet til databasen, der den er billigere.

Informasjonsdelen om Pobierowo og stedet er skrevet for de søkene folk faktisk gjør i dette området, med raskere melding om endringer via Google Indexing API. Sikkerhetskopier går automatisk til Amazon S3 med replikering mellom regioner, versjonering og Zstandard-komprimering. Versjoneringen veier tyngre enn selve kopien, for den feilen som faktisk rammer overnattingssteder er ikke en død server. Det er en prisliste som ble overskrevet med feil fil to dager før høytiden.

Beliggenheten håndteres av en modul basert på Mapbox GL JS med GeoJSON-data og fliser. For et hus ved kysten svarer kartet på et spørsmål ingen stiller høyt: hvor langt er det egentlig til sjøen, når hvert eneste sted innenfor en kilometer skriver om seg selv at det ligger ved stranden.

Her står det vanligvis en liste med resultattall. Den finnes ikke på denne siden, og det er med vilje. Belegg, bestillingsvolum og omsetning tilhører huset, ikke leverandørens referanseomtale, og ingen av de tallene kunne belegges med en kilde her. Det som lar seg si ærlig, og som faktisk lar seg overføre til neste prosjekt, er beslutningene og begrunnelsene bak dem.

#Sesongen former arkitekturen

Trafikken til et overnattingssted ved Østersjøen er ikke en linje, den er en rekke smale topper: planlegging i januar, den lange mai-helgen, og så sommeren. Mellom toppene betjener nettstedet noen titalls besøk om dagen. Infrastruktur dimensjonert for toppen brenner penger mesteparten av året, og infrastruktur dimensjonert for gjennomsnittet bryter sammen nøyaktig i den uken huset tjener penger.

Sesongen har også en annen konsekvens, mindre åpenbar enn belastning. Tilbudsinnhold eldes i sprang, ikke gradvis. Priser for neste år, datoer, restaurantmenyen og innholdet i SPA-pakkene endres på én gang, som regel om høsten, og da må noen hos kunden oppdatere et dusin steder i samme økt. Ligger disse verdiene hardkodet i brødteksten, blir det alltid én side stående med fjorårets pris til våren. Innholdsmodellen skiller derfor beskrivelse fra parameter, slik at en parameter endres ett sted.

SPA-sonen og konferanserommene oppfører seg dessuten annerledes enn rom i innholdsmodellen. Et rom har tilgjengelighet og pris og er dermed en post. SPA-sonen har ikke tilgjengelighet i den forstand, den har behandlinger, åpningstider og sesongbegrensninger. Et konferanserom har en kapasitet som endrer seg med møbleringen, og det er det tallet, ikke bildet, som utløser en henvendelse. Å presse alle tre inn i én innholdstype gir felt som står tomme i to av tre tilfeller, og et redaksjonsgrensesnitt ingen finner fram i et år senere.

#Tekniske utfordringer og løsninger

Vekten på galleriet dukket opp først i testingen. Mange bilder i høy oppløsning forsinket første visning. Redis tar seg av mellomlagring av spørringer, og Fastly fungerer som et andre CDN-lag for parallell levering av media. Delingen gir mening fordi galleri og HTML-dokument har helt ulike invalideringsprofiler: tilbudstekst endres med noen ukers mellomrom, bilder fra en fotosesjon praktisk talt aldri. Å holde begge under samme hurtigbufferregel betyr enten å laste bilder på nytt for ofte eller å oppdatere tekst for sjelden.

Den tredimensjonale modellen bremset mobile nettlesere, noe som for et sted med tungt mobilt publikum var et reelt og ikke et teoretisk problem. Redusert antall polygoner og teksturkomprimering med Draco løste overføringssiden. Kompromisset fortjener å sies rett ut: hver slik reduksjon fjerner detalj, og detaljen er hele grunnen til at modellen finnes. Grensen går der bygningskroppen fortsatt leses som denne bygningskroppen og ikke som en vilkårlig blokk.

Bestillingssystemet hakket ved trafikktopper. Årsaken er strukturell. En reservasjon må sjekke tilgjengelighet, sperre datoene, gjennomføre betalingen og sende bekreftelse, og brukeren venter på det siste steget selv om hen bare bryr seg om det første. Å skille dem med RabbitMQ gjør at sperring og svar skjer umiddelbart, mens bekreftelse og etterfølgende synkronisering går i kø. Rate limiting på Nginx-nivå beskytter det samme endepunktet mot dobbeltklikk og mot botene som skanner ledige datoer gjennom hele sesongen.

Utdatert hurtigbuffer var den siste av disse og den kommersielt dyreste. En endring i tilbudet som ingen ser, er en telefon fra en irritert gjest. Varnish med purge utløst av webhook, sammen med Edge Side Includes for dynamiske deler, løser det uten å gi opp hurtigbufferen ellers. ESI svarer på en konkret spenning: en romside består av nitti prosent innhold som ikke endres på måneder og noen få prosent pris og tilgjengelighet som endres daglig. Uten den delingen må levetiden for hele dokumentet settes etter det korteste fragmentet, altså i praksis slås av.

#Teknologi i bruk

Yoast SEO håndterer metadata, XML-nettstedskart og varsling til søkemotorer. UpdraftPlus kjører sikkerhetskopier til Amazon S3 med replikering mellom regioner og AES-256-kryptering. Cloudflare leverer CDN-laget med Argo Smart Routing, Brotli-komprimering og beskyttelse mot volumetrisk trafikk. Redis holder objektbufferen med sharding og persistens for spørringer og økter. Varnish kjører sidebufferen på egen VCL, med grace-modus og ESI.

Grace-modus fortjener en egen setning, fordi det er den mest undervurderte innstillingen i hele oppsettet. Den lar bufferen levere en litt foreldet side når backend ikke svarer, i stedet for å vise en feil. I høysesong er forskjellen mellom en side fra to minutter siden og en feilmelding forskjellen mellom en bestilling og ingen bestilling.

Lighthouse kjører automatisk i CI/CD-løpet på GitHub Actions, slik at en ytelsesregresjon dukker opp ved endringen og ikke i en klage. RabbitMQ køer bestillingsarbeid og bekreftelser med gjenforsøk. Fastly legger til en andre distribusjonsvei for media med geografisk optimalisering. Mapbox GL JS tegner kartet med fliser. GraphQL håndterer lasting av galleri- og innholdsdata med batching, og Git sammen med løpet holder endringshistorikken i en tilstand der én ting kan rulles tilbake i stedet for en hel arbeidsuke.

Det hører med å si hva denne listen ikke sier. Den sier ingenting om hvordan den samme stacken oppfører seg på et annet sted. Tre bufferlag på førtifire rom med skarp sesongvariasjon er begrunnet nettopp av denne trafikkformen. På et sted med jevn etterspørsel gjennom året ville det samme oppsettet vært ballast der vedlikeholdskostnaden overstiger nytten.

Konferanse- og gruppepublikummet leser de samme sidene med helt andre øyne. De ser etter begrensninger, ikke stemning: kapasitet per møbleringsvariant, om pausen kan tas i restauranten, hvor langt det er til nærmeste stasjon. Den lesergruppen bestemmer seg ut fra en spesifikasjon, og en spesifikasjon begravd i et avsnitt brødtekst er en spesifikasjon ingen finner. Derfor ligger tallene i strukturerte felt og ikke i løpende tekst, slik at de kan vises som en tabell på ett sted og som et kort et annet, uten at noen må skrive dem inn to ganger.

Det laget en leverandør har minst kontroll over, er dessuten det viktigste i denne bransjen. Bildematerialet avgjør en bestilling sterkere enn noen optimalisering av lastetid. Nettstedets oppgave er å ikke stå i veien for det materialet: ikke beskjære det automatisk slik at bygningskroppen kuttes, ikke laste det i en rekkefølge der det første synlige bildet er en korridor, og ikke degradere det med komprimering til et nivå der himmelen over dynen faller fra hverandre i striper.

I drift er det ikke koden som koster mest, men avviket mellom det som står på nettstedet og det resepsjonen sier. Enhver integrasjon som krymper det avviket, tjener seg inn raskere enn nok et bufferlag, og det er som regel riktig utvidelsesretning etter den første sesongen.

#Drift og vedlikehold

Nettstedet krever løpende oppfølging. Oppdateringer av system og utvidelser går gjennom et testmiljø med full kopi, ikke gjennom produksjon med optimisme. Forskjellen er tydeligst i bestillingsmodulen: en oppdatering testet på en tom installasjon går alltid gjennom, fordi det ikke finnes noe å ødelegge, mens den samme oppdateringen mot en produksjonskopi straks avslører at utvidelsen har endret datoformatet i eksisterende poster.

Cloudflare, Redis og Fastly bærer ytelsen under belastning, Varnish og RabbitMQ bærer stabiliteten i de dynamiske prosessene. SQL-spørringene går gjennom sammensatte indekser, fordi et tilgjengelighetssøk alltid filtrerer på dato og romtype samtidig, og en indeks på én av kolonnene alene hjelper ikke den spørringen. Hurtigbufferen tømmes punktvis ved innholdsendringer og ikke i sin helhet, for en full purge før en lang helg betyr at de første hundrevis av besøkene treffer en kald buffer.

Én spenning går igjen i alle overnattingsprosjekter og bør sies før byggingen, ikke etter. Eget nettsted og bookingportal beskriver det samme rommet på to forskjellige språk. Portalen tvinger fram et beskrivelsesformat, en fast fasilitetsliste og egne beskjæringsregler, og ser derfor identisk ut for alle steder på samme sted. Det egne nettstedet er det eneste stedet der det portalens skjema ikke bærer kan vises: formen på en terrasse, utsikten fra en bestemt etasje, måten ettermiddagslyset faller inn i spisesalen. Den som kopierer portalens struktur, gir fra seg sin eneste fordel og sitter igjen med et dårligere datosøk.

Nettstedet kan utvides med integrasjon mot hotellsystemet i resepsjonen, en modul for sesongkampanjer eller en del for gjesteomtaler. Hver av dem er et eget omfang, priset etter analyse og ikke lagt til underveis.

Artikkel-FAQ

Ofte stilte spørsmål

Praktiske svar for å bruke temaet i faktisk arbeid.

SEO-readyGEO-readyAEO-ready4 Q&A
Hvilket omfang hadde prosjektet BALTIC PALACE?#
BALTIC PALACE ble levert med WordPress, Tilpasset temautvikling, API-integrasjon, Ytelsesoptimalisering. Leveransenotat: Tilpasset reisenettsted
Hvordan gikk leveransen for BALTIC PALACE?#
Byggingen tok rundt seks uker og gikk live i 2025. Den står på WordPress, JavaScript, Redis, HTML5 og SASS. Layouten kom fra kunden. På den bygget jeg maler og innholdsmodell, og stiene som bærer trafikk testet jeg på en produksjonskopi, ikke på en tom installasjon.
Hva var hardest teknisk i BALTIC PALACE?#
Ytelse under reell trafikk og cache. BALTIC PALACE krevde et testmiljø nær produksjon.
Hvilken del av BALTIC PALACE kan gjenbrukes på et nytt bygg?#
Det som følger med er det tekniske laget: WordPress, JavaScript, Redis, HTML5 og SASS. Det ser omtrent likt ut på neste bygg. Det som ikke følger med er innholdsmodellen og integrasjonene, skrevet mot én kundes data. Et nytt bygg starter med en omfangsanalyse, og tilbudet kommer etter den.

Trenger du FAQ tilpasset bransje og marked? Vi lager en versjon som støtter dine forretningsmål.

Ta kontakt