Portfolio

Media & Publishing: haveabook.pl

Nettsiden haveabook.pl er en moderne plattform dedikert til forlag og trykkeri, som betjener krevende kunder fra Skandinavia. Prosjektet ble laget for å vise...

#Nettsider
Media & Publishing: haveabook.pl

#haveabook.pl, Forlag og trykkeri for skandinaviske kunder

Nettstedet haveabook.pl er en plattform for forlags- og trykkeritjenester rettet mot krevende kunder i Skandinavia. Det viser hele tjenestetilbudet, lar kunder be om pris, og dokumenterer utførte arbeider. Løsningen ble levert i 2015 og arbeidet tok omtrent seks uker.

#Fire språk er ikke fire sett oversettelser

Den vanligste feilen i flerspråklige prosjekter er å behandle språk som en etikett festet på de samme dataene. Mot det skandinaviske markedet ryker den forenklingen på et sted ingen kontrollerer før overlevering: sortering av lister.

Svensk og dansk-norsk alfabet inneholder tegn som ikke finnes i det engelske, og enda viktigere, de plasserer dem i en annen rekkefølge. Dette er ingen typografisk pynt, det er en sorteringsregel. En liste over titler eller kunder sortert etter én regel for alle språk vil for en del av leserne rett og slett fremstå usortert. I søk kommer det i tillegg at en frase skrevet uten diakritisk tegn ikke finner posten som har det. Løsningen er at sammenligningsregelen for tekst er en egenskap ved språkversjonen og ikke en global innstilling i databasen.

Det andre punktet er skillet mellom språk og marked. En kunde i Norge og en kunde i Sverige kan begge lese nettstedet på engelsk og likevel trenge ulike papirformater og ulike ord for innbinding. Innholdsmodellen må derfor tillate at språkvariant og markedsvariant er to akser og ikke én. Nettsteder som limer dem sammen, ender med å oversette de samme dataene en gang til bare for å bytte ut én tabell.

Det tredje punktet gjelder adresser. Hver språkversjon trenger sin egen, varige URL og en erklæring om forholdet til de andre versjonene, ellers viser søkemotoren den engelske utgaven til en svensk forlegger, og det betyr i praksis en forespørsel som aldri kommer inn.

#Kunden: Have a Book fra Gdynia

Have a Book er et selskap fra Gdynia som har vært i drift siden 2007, med adresse i Wierzbowa-gaten og noen titalls ansatte. De beskriver seg som ett kontaktpunkt for utdanningsforlag i Europa: ombrekking og prepress, grafisk formgivning, typografi, trykk og innbinding, samt konvertering av publikasjoner til elektroniske formater med hensyn til tilgjengelighet etter WCAG. Kundene er utdanningsforlag i Norge, Frankrike, Sveits og Belgia.

Den kundeprofilen avgjør formen på nettstedet. Et utdanningsforlag kjøper ikke på impuls og kjøper ikke én bok. De kjøper en serie titler i flere varianter, og beslutningen tas av et team der én ser på budsjett, én på frist og én på om trykkeriet håndterer en bestemt innbinding i en lærebok som skal åpnes daglig i tre år. Et nettsted som skal støtte den beslutningen, trenger tre ting samtidig: pris, leveringstid og bevis på utførelseskvalitet.

#Et pristilbud er en funksjon, ikke et tall i en prisliste

Den største forskjellen mellom dette prosjektet og en vanlig nettbutikk ligger ett sted: her har produktet ingen pris. En bok som skal trykkes, er et sett parametere, og prisen er resultatet av en operasjon på det settet. Format, papirvekt, sidetall, innbindingstype, farger eller sort, opplag, etterbehandling. Hver av dem endrer resultatet, og flere av dem endrer det i sprang.

Dette lar seg ikke omgå med en prisliste. Antall kombinasjoner vokser multiplikativt, så å skrive dem ut som katalograder slutter å være gjennomførbart etter den tredje parameteren. Beregningen må derfor skje på forespørsel, ut fra en satsstruktur, og ikke leses av en liste.

Den andre egenskapen ved dette fagområdet er mindre åpenbar og lett å overse i koden. Trykkekostnad vokser ikke lineært med opplaget, fordi det koster like mye å gjøre maskinen klar for hundre eksemplarer som for ti tusen, og den kostnaden fordeles på opplaget. I tillegg kan et formatbytte flytte jobben til en annen maskin eller et annet ark, noe som endrer kostnaden i et sprang og ikke jevnt. En naiv implementasjon som interpolerer mellom to punkter i prislisten, gir riktige svar midt i intervallet og gale svar nøyaktig ved tersklene, altså der kunden spør oftest. Beregningen må gjengi tersklene, ikke en kurve trukket gjennom dem.

#Nøkkelfunksjoner og løsninger

Tjenestekatalogen er en visning filtrert på kategori, tjenestetype og spesifikasjon. Filtreringen skjer i spørringen og ikke i nettleseren, av samme grunn som i enhver teknisk katalog: mengden vokser, og å sende hele settet til nettleseren slutter å lønne seg lenge før noen legger merke til det under testing på eksempeldata.

Katalogen har dessuten en egenskap som skiller den fra en produktkatalog. En linje i tilbudet fra et trykkeri er ikke en ting, men en utførelsesevne, og den beskrives med intervaller: fra så mange til så mange sider, i disse formatene, på papir med denne vekten, med denne innbindingen. Overført til innholdsmodellen betyr det at attributtet på en katalogoppføring iblant er et intervall og ikke en verdi, og at et spesifikasjonsfilter må spørre om å ligge innenfor intervallet og ikke om likhet. Filtre bygget på likhet ser riktige ut under bygging og fjerner stille halve tilbudet så snart noen skriver inn et sidetall som ikke står i listen.

Porteføljen har her en funksjon den ikke har på de fleste tjenestenettsteder. En forlegger vurderer et trykkeri etter hvordan den ferdige boken ser ut, og et lavoppløst omslagsbilde sier ingenting om hvordan ryggen oppfører seg etter et år eller hvordan fargen faller på et gitt papir. Galleriene må vise detaljer, altså store filer, og derfra kommer det egne arbeidet med at gallerisiden ikke laster alt på en gang. Forhåndsvisninger først, fullversjoner ved åpning, og selve filene leveres fra innholdsleveringsnettverket og ikke fra applikasjonsserveren.

#Å ta imot filer er ikke en handlekurv

En trykkebestilling er ikke en handlekurv, den er en produksjonsordre med materiale vedlagt. Trykkefilen er ofte stor, og å sende den gjennom et vanlig skjema ryker på grenser satt på serveren og på brutte forbindelser.

Til det kommer at en fil som ser riktig ut i nettleseren, kan være ubrukelig i produksjon fordi den har feil fargerom eller mangler utfallende marger. En innledende kontroll ved mottak er derfor en del av prosessen og ikke et tillegg, for å oppdage en slik feil ved mottak koster et minutt, mens å oppdage den ved maskinen koster hele opplaget.

#Utviklingsutfordringer og løsninger

Den første avgjørelsen gjaldt hvor beregningslogikken bor. Det frister å regne prisen i nettleseren, fordi svaret da kommer umiddelbart og ikke koster noe kall. Fristende og galt, siden satsstrukturen dermed blir offentlig, og en kopi av logikken i nettleseren glir fra serveren ved første prisendring som ingen flytter begge veier. Beregningen ligger derfor på serveren, og nettleseren samler parametere og viser et resultat.

Den andre utfordringen var reproduserbarhet. En pris oppgitt på mandag må kunne gjenskapes på torsdag, selv om satstabellen er endret i mellomtiden. Sammen med tilbudet lagres derfor hele parametersettet og versjonen av satsstrukturen det ble beregnet fra, ikke bare tallet. Uten det ugyldiggjør enhver prisendring historikken, og det enkle spørsmålet om hvorfor kunden så akkurat det beløpet, lar seg ikke besvare. Den samme avgjørelsen rydder i mellomlagringen: nøkkelen til et lagret resultat må inneholde satsversjonen, ellers leverer nettstedet gamle beløp en stund etter en prisoppdatering, og gjør det uten spor i loggene.

Den tredje utfordringen var ytelse med mye mediainnhold. Mellomlagring i minne, med Redis og Memcached, forkorter databasearbeidet for det som uansett må gjennom applikasjonslaget: katalogsett, satstabeller, innstillinger. Innholdsleveringsnettverket overtar filene. Dette er to ulike problemer, og de er verdt å skille eksplisitt, fordi de blandes ofte: mellomlagring i minne gjør ingenting for nedlastingen av et fulloppløst bilde, og et kantlag forkorter ingen databasespørring.

Den fjerde utfordringen var synkronisering mot systemene hos bedriften, altså produksjonsplaner og data om materialtilgang. Løsningen er at applikasjonen ikke spør produksjonssystemet mens en side genereres. Data hentes uavhengig og mellomlagres med levetid valgt separat per kilde, fordi en produksjonsplan endrer seg annerledes enn en satstabell. Viktigst er likevel oppførselen ved svikt: når kilden er utilgjengelig, viser visningen siste kjente verdi eller en variant uten den seksjonen, ikke en feilmelding. Den besøkende har ingen grunn til å vite at et internt system akkurat nå ikke svarer.

#Universell utforming er en del av det kunden selger

Her er et poeng som sjelden står i en prosjektbeskrivelse. Have a Book konverterer publikasjoner til elektroniske formater med hensyn til tilgjengelighet etter WCAG, altså selger de en kompetanse som nettstedet må kunne vise. Det gir en enkel og ubehagelig konsekvens: nettstedet til et selskap som selger tilgjengelige publikasjoner, kan ikke selv ha en katalog som ikke lar seg betjene fra tastaturet, eller spesifikasjonstabeller uten kobling mellom overskrifter og celler.

En tabell med tekniske parametere uten den koblingen er for en skjermleser en rekke tall uten mening, og på dette nettstedet er spesifikasjonstabellene hovedinnholdet. Det samme gjelder prisskjemaet: felter som henger logisk sammen, må henge sammen også i oppmerkingen, ellers når informasjonen om at valget av innbinding har begrenset tilgjengelige formater bare fram visuelt, og bare til den som tilfeldigvis ser på riktig del av skjermen.

#Verktøy og teknologier

Bakenden står på PHP og MySQL, det interaktive laget på JavaScript og egne endepunkter, og de raske lesestiene på mellomlagring i minne. Infrastrukturen er skybasert og koden ligger i versjonskontroll, noe som her har en konkret betydning: satstabellen er data og reglene for å bruke den er kode, og bare det skillet gjør det mulig å endre prisene uten en utrulling og å endre en regel uten å røre prisene.

Presentasjonslaget hviler på responsive standarder og en stilarkpreprosessor som holder bruddpunktene på ett sted. På et nettsted med et skjema på over ti felter er det ingen kosmetikk. Prisskjemaet er den viktigste visningen i prosjektet og samtidig den vanskeligste å sette opp på en smal skjerm, fordi feltene henger sammen og en endring i ett ofte skal ses i et annet.

#Støtte og plattformutvikling

Vedlikeholdet omfatter oppdateringer, overvåking og løpende endringer. På et nettsted med kalkulator kommer det en plikt i tillegg som en vanlig presentasjonsside ikke har: endringer i satsstrukturen må kontrolleres mot historiske data. En endring som ser riktig ut på ett eksempel, kan flytte resultatet ved en annen opplagsterskel, og det oppdages først av kunden som får et beløp som ikke stemmer med det fra forrige uke.

Oppdateringer går først på en kopi av produksjon, og det er ingen formalitet. En tom installasjon har ingen katalog av denne størrelsen, ingen fire språkversjoner av samme oppføring, ingen gallerier med filer i produksjonsoppløsning og ingen samling lagrede tilbud fra ulike prisversjoner. Alle fire er det oppdateringer ryker på, og ingen av dem finnes i et testmiljø bygget fra bunnen.

Sikkerhetskopier følger samme regel som overalt: en kopi ingen har tilbakeført, er en fil og ikke en kopi. Her kommer det i tillegg at filene kundene har sendt inn, er produksjonsmateriale og ikke nettstedsinnhold, og at det å miste dem er en hendelse av en annen klasse enn å miste en tjenestebeskrivelse.

#Oppsummering og kravanalyse

haveabook.pl skulle svare på fire krav samtidig. Først på å vise et tilbud som ikke lar seg beskrive med en prisliste, fordi prisen er resultatet av en operasjon på parametere. Deretter på fire språkversjoner, tre av dem skandinaviske, med sorteringsregler som hører til hver enkelt. Deretter på kobling mot systemene hos bedriften på en måte som ikke overfører deres driftsavbrudd til nettstedet. Og til slutt på å ta imot produksjonsmateriale og ikke bare bestillinger.

Av de fire kravene følger hele konstruksjonen: beregning på serversiden, versjonering av satsstrukturen sammen med det lagrede tilbudet, mellomlagring med nøkkel som inneholder den versjonen, skille mellom språkaksen og markedsaksen i innholdsmodellen, og et fillag holdt unna applikasjonsserveren. Det som ikke følger med videre, er innholdsmodellen og integrasjonene i dette prosjektet, skrevet for én bedrift og en brief i kategorien Nettsider. Et nytt prosjekt begynner med en analyse av omfanget, og tilbudet kommer etter den.

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 haveabook.pl?#
haveabook.pl er et prosjekt i kategorien Nettsider, levert i 2025. Bak det står PHP, JavaScript, Redis, MySQL og HTML5.
Hvordan gikk leveransen for haveabook.pl?#
Byggingen tok rundt seks uker og gikk live i 2025. Den står på PHP, JavaScript, Redis, MySQL og HTML5. 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 haveabook.pl?#
Ytelse under reell trafikk og cache. haveabook.pl krevde et testmiljø nær produksjon.
Hvilken del av haveabook.pl kan gjenbrukes på et nytt bygg?#
Det som følger med er det tekniske laget: PHP, JavaScript, Redis, MySQL og HTML5. Det ser omtrent likt ut på neste bygg. Det som ikke følger med er innholdsmodellen og integrasjonene, skrevet mot én kundes data og en brief i kategorien Nettsider. 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