Bliv en del af mit community / gratis nyhedsbrev — tilmeld dig her
- Client
- GrN.dk — internt projekt
- Sector
- Browserspil og sprogindlæring
- Periode
- juli 2026
At a glance
fantasy.grn.dk er コトバモン KotobaMon — et 3D-monsterfangerspil, der kører i en helt almindelig browserfane, og hvor hvert monster er et japansk ord. ヒバナ hibana er en gnist, コダマ kodama er en træånd, og at fange et er måden, ordet bliver lært på. Spillet har en procedureelt genereret ø med fem biomer, tolv arter, turbaserede kampe med et typeskema og fuld japansk voice-over med undertekster på japansk, romaji og engelsk på samme tid. Der er intet download, ingen konto, intet build-step og ingen backend: hele spillet er 2.821 linjer vanilla JavaScript plus en vendoret kopi af Three.js, serveret som statiske filer.
The challenge
Undervisningsproblemet kom først. En gloseapp er let at bygge og let at opgive; et spil bliver spillet. Men de fleste »lær et sprog«-spil bolter læringen på ude i siden — en quizskærm mellem baner, som kan springes over og ikke er noget værd. Hvis et rigtigt svar ikke ændrer, hvad der derefter sker i spillet, er det pynt, og spillerne lærer at springe det over.
Dernæst leverancekravene, som er den mere interessante halvdel for enhver, der bestiller software. Et projekt som dette giver kun mening, hvis det er hurtigt at producere og stort set gratis at holde i live: ingen licenseret grafik at købe, opbevare og holde synkroniseret; ingen regning pr. tegn fra en cloud-stemme-API; ingen serverproces, der skal patches klokken tre om natten; og ingen build-værktøjskæde, der stille holder op med at virke om to år og trækker projektet med sig ned. Monstrene skulle også være hundrede procent originale — det her er en genre med berømt velforsvarede varemærker.
Og den målgruppe, spillet faktisk er til, kan ikke læse japansk endnu — hvilket udelukker kun at vise kana og lige så vel udelukker kun at vise engelsk.
The solution
Spillet. Du strejfer rundt på en procedureelt genereret ø i tredjeperson — tastatur på desktop, et joystick på skærmen og en A-knap på telefonen. Fem biomer (eng, skov, sø, vulkan, snedækket tinde) har hver deres arter i hvert deres level-interval. Gå ind i et vildt monster, og en turbaseret kamp går i gang med otte elementer og et typeskema, der afgør, hvad der rammer hårdt, og hvad der fuser. Svæk det, kast en Kotodama Orb, og det slutter sig til holdet. Seks missioner og en KotobaDex med tolv opslag giver strejfturene en retning — inklusive én bevidst sky art, månekaninen ツキウサ, med en basisfangstchance på 15 % mod en starters 40 %.
Læring er et move, ikke en skærm. Glosequizzen er en af handlingerne i kampmenuen, én gang pr. kamp. Svar rigtigt på ordet, og fangstchancen stiger med flade 0,25 — til sammenligning er det 0,55 værd at slide et monsters helbred helt i bund, så et rigtigt svar er cirka det samme værd som at tage 45 % af dets HP, og det giver 25 point oveni. At svare godt er et reelt alternativ til at kæmpe godt, og det er den eneste måde at få en læringsmekanik til at betyde noget. Banken er på 36 ord — de tolv monsternavne plus hverdagsgloser — og der spørges begge veje, fra japansk til engelsk og tilbage igen.
Tre undertekster på én gang. Hver talt replik viser japansk, romaji-læsningen og den engelske betydning samtidig. Den lærende kan høre replikken, se på kanaen, tjekke udtalen og få bekræftet betydningen uden at forlade skærmen — det stillads, der gør spillet brugbart for en ægte begynder og ikke kun for en, der allerede læser japansk.
Stemme uden API-regning. De 31 japanske stemmereplikker blev genereret én gang af en self-hostet Kokoro-tekst-til-tale-model på den samme server — en kvindestemme til Professor Sakura, en mandsstemme til fortællerstemmen — og skrevet ud som statiske MP3'er sammen med et genereret manifest med alle tre undertekstrækker pr. replik. Intet faktureres pr. brug, ingen tekst forlader maskinen, og der er ingen runtime-afhængighed, der kan rate-limite eller forsvinde. Musikken er også genereret: baggrundssporene er en WebAudio-step-sequencer med hver sin stemning til strejf og kamp, så ud over voice-overen er der slet ingen lydfiler.
Intet build-step — med vilje. Three.js 0.178 er vendoret ind i projektet, og resten er vanilla JavaScript med native ES-moduler — ti filer, 2.821 linjer. Ingen bundler, ingen transpiler, intet CI-trin at holde grønt: de filer, der skrives, er de filer, der shipper, og de kører stadig om mange år uden en værktøjskæde, der skal genoplives. Grafikken er procedurel i samme ånd — terræn, monstre og træner er alle samlet af primitiver i kode frem for modelleret i et eksternt værktøj, så der er ingen grafikfiler at licensere eller holde synkroniseret. Det eneste tredjeparts, der hentes på kørselstidspunktet, er den japanske display-webfont.
Cachedisciplin som feature. At deploye er en filkopiering og en cache-purge, men et CDN cacher efter filendelse, så et halvt purget deploy serverede engang et forældet modul, mens et direkte kald til samme URL viste friske bytes. Reglen er nu, at hver relativ import og stylesheetet bærer den samme versions-query, som bumpes ved hvert deploy og aldrig genbruges. Versionsbadget i hjørnet af skærmen udledes på kørselstidspunktet af det indlæste moduls egen versions-query — så et forældet badge betyder et forældet deploy, helt bevidst, og spillet melder sine egne cachefejl.
Testbart udefra. En automatiseret browser evaluerer sine scripts i en isoleret JavaScript-verden, hvor sidens egne globals er usynlige, men DOM'en er delt. Derfor eksponerer spillet et lille #e2e-element: én attribut publicerer den levende spiltilstand som JSON, en anden modtager kommandoer. Det er det, der lader en ubemandet agent starte et nyt spil, springe den indtalte intro over, vælge en starter, gå ind i et monster og tjekke resultatet — skærmbilledet på denne side blev taget gennem den bro.
The results
KotobaMon har været live på fantasy.grn.dk siden 18. juli 2026 — på sit eget domæne og med eget certifikat fra dag ét — og er i skrivende stund på build v10.
Det er også et konkret eksempel på den leverancemodel, resten af denne portefølje beskriver. Hele spillet kom af et Trello-board ét kort ad gangen, hvert samlet op af en AI-agent: »Create a 3D pokemon game« var ét enkelt kort, og over de følgende to dage fik det selskab af kort om musikken, kampeffekterne, et Water Gun-move med monsterskift midt i kampen og en styringsrettelse, mere skiftearbejde og et synligt versionsnummer. Dage, ikke uger — og hver eneste af de ændringer kan spores til det kort, der bad om den.
Driftsomkostningen er pointen. Statiske filer bag et CDN: ingen database, ingen applikationsserver, ingen regning pr. stemmebrug og ingen hemmelighed at rotere. Fremskridt gemmes i spillerens egen browser, så der er ingen konto at oprette og intet om spilleren gemt nogen steder.
Hvad det ikke er, siger det højt. Det lærer dig gloser, ikke grammatik; der er tolv arter og én ø; gemte spil følger ikke med mellem enheder; og den procedurelle grafik er enkel med vilje, fordi enkel grafik, der shipper, slår bestilt grafik, der ikke gør. Den længere gennemgang af beslutningerne bag ligger her: Et 3D-browserspil shippet uden build-step og med self-hostet stemme.
Lær deres navne, og så lærer du også japansk!