Spring til indhold

Web app-manifest

filen der lader et site blive installeret

Hvad det er

Et web app-manifest er et JSON-dokument, der beskriver et website som et program: hvad det hedder, hvilken adresse det åbner på, hvilke adresser der hører til det, hvordan vinduet skal se ud, og hvilke billeder der står for det. Siden peger på filen med et link-element, hvis rel er manifest, og en browser, der tilbyder installation, læser web app-manifestet for at afgøre, hvad den installerede kopi skal være. W3C-specifikationen bag formatet kalder det blot manifestet, og det gør de fleste i daglig tale også.

Filen er almindelig JSON. Den registrerede medietype er application/manifest+json, og den registrerede filendelse er .webmanifest, men specifikationen godtager enhver JSON-medietype, og mange sites serverer en manifest.json. Alle medlemmer er valgfrie. Et lille manifest til et opdigtet site med tidevandstabeller for en havn kan se sådan ud:

{
    "name": "Havnens tidevandstabeller",
    "short_name": "Tidevand",
    "start_url": "/tidevand/",
    "display": "standalone",
    "background_color": "#ffffff",
    "icons": [
        {
            "src": "/ikoner/tidevand-512.png",
            "sizes": "512x512",
            "type": "image/png"
        }
    ]
}

Tre medlemmer bestemmer, hvad appen er, til forskel fra hvordan den ser ud. start_url er den side, den installerede app åbner på. scope er de adresser, der regnes for at høre til inde i appen; mangler det, tager specifikationen start-URL’en og skærer filnavn, forespørgsel og fragment af, så eksemplet ovenfor ejer alt under /tidevand/. id er appens identitet, og mangler det, falder det tilbage på start-URL’en. Relative adresser i filen, til ikoner såvel som til start-URL’en, opløses i forhold til manifestets egen URL og ikke i forhold til den side, der linkede til det.

Resten handler om udseende. display beder om fullscreen, standalone, minimal-ui eller browser, og en browser, der ikke kan imødekomme ønsket, går ned ad listen i netop den rækkefølge. Hvert ikon kan have et purpose: any som standard, maskable til et billede tegnet til at tåle beskæring eller monochrome til et billede, hvis farver smides væk, så kun alfakanalen bruges. theme_color farver vinduet omkring appen. En ledsagende W3C-note tilføjer description, categories og screenshots, som installationsdialoger og appbutikker kan vise.

Hvorfor det betyder noget

Manifestet er den eneste del af en installation, sitet selv styrer. Specifikationen overlader beslutningen til browseren: den må tilbyde installation, og hver browser fastsætter sine egne betingelser, hvoraf nogle kræver bestemte medlemmer. Et team leverer råmaterialet, og browseren afgør, hvad der sker med det, så det nyttige spørgsmål handler mindre om, hvorvidt der skal være et manifest, end om, hvad det lover.

Identiteten er det løfte, der lever længere end filen. Når en browser henter manifestet igen, kræver specifikationen, at den bruger id til at afgøre, om den nye fil gælder en app, der allerede er installeret. Fordi et manglende id er lig med start-URL’en, skifter identiteten i stilhed, når startsiden flyttes, og den nye fil beskriver så et andet program end det, der ligger på læserens enhed. At låse id fast i den første udgivelse koster én linje og fjerner den risiko.

Omfanget afgør, hvor appvinduet slutter. Navigation inden for scope bliver i det installerede vindue. Et link, der fører ud, åbner stadig, men specifikationen forventer, at browseren gør det synligt for læseren, at siden ligger uden for appen, så et omfang, der er smallere end sitet, får almindelige links mellem dets afsnit til at ligne udgange.

Ikonerne er dér, hvor det meste af den synlige skade sker. Hjemmeskærme og appstartere beskærer ikoner til cirkler, afrundede firkanter og andre former, og et logo, der fylder hele sit kvadrat, mister kanterne. Specifikationen definerer sikkerhedszonen for et maskable ikon som en cirkel i midten med en radius på to femtedele af ikonets størrelse, og alt uden for den kan blive skåret væk. Et monokromt ikon beholder kun sin alfakanal, så et ikon tegnet på en uigennemsigtig baggrund bliver til en massiv firkant.

Farvemedlemmerne rækker kortere, end de ser ud til. background_color er kun ment til øjeblikket, før stylesheetet når frem, og specifikationen forbyder browseren at bruge den, når stylesheetet er klar. Den farver det første billede, og intet efter det.

Sådan ser det ud i praksis

Dette site bygger sit manifest ud fra en skabelon i stedet for at vedligeholde en fil i hånden. Hugo-konfigurationen registrerer application/manifest+json med endelsen webmanifest og gør manifestet til et output af hvert sprogs forside, så hvert sprog får sin egen fil, og hovedet på hver side linker til filen for sit eget sprog. Konfigurationen noterer også hvorfor: én fælles kopi kan kun angive én start-URL, og en dansk besøgende, der installerede sitet, fik en app, der åbnede den engelske forside.

Skabelonen samler manifestet med Hugos dict og sender det gennem Hugos JSON-encoder, så escaping og kommaer er encoderens ansvar, og et glemt komma når aldrig ud. Hver ikonadresse starter ved roden af værten, og kommentaren i skabelonen forklarer grunden: en relativ adresse i /da/manifest.webmanifest ville blive opløst under /da/, og hvert ikon på dansk ville give 404. Selve ikonerne læses fra disken i tre mapper, én pr. formål, med ti størrelser i hver fra 36 til 512 pixel, og størrelsen aflæses i filnavnet, så en størrelse, som generatoren tilføjer, dukker op i manifestet, uden at nogen skal rette i det.

id er låst fast til sprogets forsideadresse, og scope er hele originet, så et link over i et andet sprog bliver i det installerede vindue. Skærmbilleder navngives <lang>-<form_factor>-<WxH>.webp, og skabelonen aflæser alle tre oplysninger i filnavnet: engelsk og dansk har hver ét bredt billede på 1.280 gange 800 og ét smalt på 780 gange 1.688. Et sprog uden skærmbilleder får slet intet screenshots-medlem, fordi en tom liste ville påstå, at appen intet har at vise.

Kolofonen nævner W3C-specifikationen blandt de standarder, sitet følger, og PWABuilder blandt de eksterne tjek, enhver selv kan køre: en tjeneste på Microsofts servere, der gennemgår manifestet og alt det øvrige, som installation afhænger af.

Installationssiden er læserens halvdel af den samme fil. Den viser, hvor hver browser gemmer installationskommandoen, fortæller, at Apples browsere aldrig byder sig til, og at desktopudgaven af Firefox overhovedet ikke installerer webapps, og den afstemmer forventningerne: den installerede app er et ikon og et selvstændigt vindue, og den kræver forbindelse, fordi offlinebrug forudsætter en service worker.

Hvor det går galt

Alle ikoner giver 404 på en oversat sti. En relativ src opløses i forhold til manifestets URL, så et manifest, der serveres under et sprogpræfiks, beder om ikoner under samme præfiks. Skriv ikonadresser fra værtens rod eller som fulde URL’er.

Den installerede app åbner på det forkerte sprog. Ét manifest kan angive én start-URL, så alle læsere installerer den samme forside. Server ét manifest pr. sprog med sin egen start_url og sit eget id, og link til det passende fra hver side.

Installerede kopier overser det nye manifest. Uden id er identiteten start-URL’en, så når startsiden flyttes, får filen en ny identitet, og browseren anvender den derefter ikke på den app, læserne allerede har. Sæt id før første udgivelse, og lad det ligge bagefter.

Hjemmeskærmen beskærer logoet. Et ikon med formålet any placeres eller beskæres, som platformen finder passende. Tilføj et maskable ikon, hvor alt vigtigt ligger inden for den midterste cirkel, hvis radius er 40 % af ikonets størrelse.

Rettelser i manifestet gør ingen forskel. HTML-standarden bruger kun det første link-element, hvis rel indeholder manifest, så har et tema eller et plugin sat sit eget link tidligere på siden, bliver den fil, der rettes i, aldrig læst. Hold præcis ét manifestlink pr. side.

Læs mere

Ordliste