Slik bygde jeg gribben.no sammen med AI

Du har kanskje en liten side eller et lite prosjekt du vil bygge med AI, uten å gi fra deg styringen. Slik har jeg gjort det her: hva Claude gjør, hva jeg gjør, og hva som gikk galt.

Magnus Gribbestad 8. oktober 2026 9 min
Figur · fra Strava til nettsida
Fra Strava til nettsida, med menneske og AI på riktig sted Seks trinn nedover. Jeg setter hver økt til offentlig eller privat i Strava. Claude henter bare de offentlige gjennom koblingen og legger dem inn i skriptet. Skriptet skriver en JSON-fil. Claude regner scoringa om i Python for å kontrollere kortet. Jeg leser og sender det ut til nettet. MAGNUS Strava offentlig eller privat CLAUDE Koblingen bare offentlige økter CLAUDE Skriptet økter inn i lista KODE JSON-fila genereres hver gang CLAUDE Kontrollen regnes om i Python MAGNUS Til nettet når jeg har lest Magnus Claude Kode og filer
  1. Det starter i Strava. Jeg avgjør per økt om den er offentlig eller privat, og det valget følger økta hele veien.
  2. Claude henter økter og runder gjennom koblingen til Strava. Bare økter satt til offentlig skal videre.
  3. De legges øverst i en liste i skriptet hent_okter.py. Claude skriver dem inn, jeg ser over.
  4. Skriptet skriver data/okter.json. Fila er generert, og den redigeres aldri for hånd.
  5. Før noe sendes ut, regner Claude scoringa i analysekortet om i Python og sammenligner med nærliggende økter.
  6. Til slutt leser jeg, og først da sendes det ut. Det er jeg som sier at det er klart.

Det jeg har lært mest av, er ikke at AI kan skrive kode. Det er hvor liten del av jobben det er. Resten er å avgjøre hva som skal ut, hva som aldri skal ut, og når noe er godt nok. Den delen har jeg beholdt selv.

Er du leder? Dette er det du tar med

AI gjør jobben, du eier avgjørelsen. Det som aldri skal ut, bør stoppes i systemet og ikke bare i en rutine. Det har jeg ikke fått helt til selv, og det står under. Feil er det du skriver ned, ikke det du skjuler. Resten av saken er hvordan, med eksempler fra en liten side.

En side om løping, uten byggesteg

gribben.no er min personlige side om løping og teknologi. Den er statisk HTML, uten byggesteg, uten pakkefil og uten Node.js. Verktøyspråket er Python. Det er et valg, og det har holdt: lite kan gå i stykker, og det er lett for både meg og Claude å se hele sida på en gang. Det jeg skal snakke om her er øktdatabasen, med offentlige Strava-økter og analysekort på intervalløktene. Her ligger også to spillsamlinger, Gribbelandet og Skolespillet, men dem lar jeg ligge.

125
commits siden 9. mars 2026. Kilde: git rev-list --count HEAD, tellet 8. oktober 2026.
85
av dem har Claude oppført som medforfatter i commit-meldinga. Kilde: git log.
7
skills i .claude/skills, hvorav én ikke er committet ennå: oppskrifter og lesere som Claude laster når oppgaven passer.
155
offentlige økter i data/okter.json, 21 av dem med rundedata. Kilde: fila selv.

Tallet 85 sier ikke hvor mye Claude skrev. Det sier at Claude var med i 85 av 125 endringer. Medforfatterlinjene nevner to modeller: Claude Opus 5 i 74 av commitene og Claude Fable 5 i 11. Commit-meldingene er skrevet av Claude, og i CLAUDE.md står det at den ikke skal pushe før jeg ber om det.

Hvem gjør hva

Figuren øverst viser veien fra en økt i Strava til en rad på sida. Fargene er poenget: gult er meg, blått er Claude, grønt er kode som kjører likt hver gang. Første og siste trinn er mine. Det er ikke tilfeldig.

OppgaveClaudeJeg
Nye økterHenter dem gjennom koblingen og legger dem inn i skriptetSetter synlighet i Strava og ber om synk
AnalysekortHenter runder, slår dem sammen til drag og regner scoringaLeser notatet og avgjør om kortet sier noe sant
TekstSkriver utkast i stemmen fra en skillRetter. Motivasjonssaken gikk fem runder
UtseendeBygger sider og figurer etter stilregleneSer på dem og sier fra når noe er feil
Når noe er klartKjører lesere over utkastetBestemmer

Fra Strava til en rad på sida

Hver synk går i samme rekkefølge. Claude henter aktivitetene gjennom koblingen til Strava, og hvordan du setter den opp selv står i artikkelen om løpetrener og fysioterapeut i Claude. For øktene som skal ha analysekort, henter den også rundene. Alt legges øverst i en liste i verktoy/hent_okter.py, og skriptet skriver data/okter.json. Sida leser fila og tegner tabellen og kortene.

Fila er generert, og jeg redigerer den aldri for hånd. Det står øverst i CLAUDE.md, fordi en håndredigering forsvinner ved neste synk uten at noe sier fra. Skriptet gjør også en ting jeg ikke hadde tenkt på selv: det stempler en innholdshash inn i sida som laster fila, så besøkende ikke får en gammel utgave i nettleseren etter en synk.

Filteret som ikke kan ligge i nettleseren

Strava merker hver økt som offentlig, bare for følgere eller bare for meg. Bare de offentlige skal inn. Jeg fant en privat økt allerede i de tre nyeste ved første uttrekk, så dette var aldri teori.

Regelen er at data som ikke skal vises, ikke skal finnes i fila. Å skjule en privat økt med JavaScript er ikke å filtrere den. Den ligger fortsatt i en fil som hvem som helst kan åpne. Derfor sier synk-commitene også hva som ble holdt utenfor, som i synken 5. oktober: «De to private er ikke med.»

Svakheten jeg ikke har rettet ennå

Regelen står i skriptets bruksanvisning, i synk-skillen og i CLAUDE.md. Men skriptet sjekker ingenting selv. Det får aldri se feltet for synlighet, fordi øktene limes inn etter at filteret er brukt. Filteret er en rutine Claude og jeg følger, ikke kode som stopper en feil.

Claude starter blankt hver gang

Claude har ikke med seg noe fra forrige økt. Det som skal bestå, må stå i en fil som leses først. Derfor har repoet tre lag, og jeg har lært å holde dem fra hverandre:

CLAUDE.md kom som commit nummer 110. Meldinga sier hva den var til for: fem ting som hadde blitt gjenoppdaget i hver eneste økt. Den burde kommet i commit nummer ti.

For deg som bygger: se filene

Tre utdrag, uredigert, så du ser hva jeg mener med lagene. Først toppen av CLAUDE.md: reglene som alltid gjelder.

CLAUDE.md · toppen
## Det viktigste først

**`data/okter.json` er generert. Rediger den aldri for hånd.**
Eneste vei inn er `verktoy/hent_okter.py`. Håndredigering forsvinner ved
neste synk, og cache-stempelet blir feil uten at noe sier fra.

**Private Strava-økter skal aldri inn i repoet.** Filtreringen skjer ved
uttrekket, ikke i nettleseren: bare `visibility = "everyone"` skal limes inn
i `OKTER`. Skriptet sjekker det ikke selv, for feltet finnes ikke i det som
limes inn. Regelen er et steg i prosedyren i `verktoy/hent_okter.py` og
`synk-okter`, og den må følges. Data som ikke skal vises, skal ikke finnes
i fila.

**Ingen Node.js.** Python er verktøyspråket her. Sida har ingen
byggesteg, ingen pakkefil og ingen avhengigheter.

Så starten på synk-skillen. Linjene mellom strekene er det Claude leser for å vite om skillen passer.

.claude/skills/synk-okter/SKILL.md · toppen
---
name: synk-okter
description: Hent nye Strava-økter inn i øktdatabasen på gribben.no og legg analysekort på intervalløkter. Bruk denne når Magnus ber om å «synke øktene», «hente siste aktiviteter», «legge på analysekort», eller når en ny økt skal inn i data/okter.json. Dekker hele flyten fra Strava-uttrekk til commit, med fallgruvene som ikke står i skriptet.
---

Til slutt starten på en oppføring i minnebanken, den om mølleøkta fra figuren lenger opp.

.claude/LAERT.md · en oppføring
## 2026-10-05 · Mølleøkter autolapper på kilometeren og skjuler draga

**Hva:** `get_activity_laps` for 8 x 1000 på mølle ga tolv runder à 1000 m
med fart 4:15 til 5:06 og ingen hvilerunder. Det ser ut som en slapp økt.
Den var ikke det: draga gikk på 3:26 til 3:30. Garmin autolappet hver
kilometer, så hvert innslag er en blanding av drag og pause.

Utdrag fra arbeidskopien 8. oktober 2026. CLAUDE.md har endringer som ikke er committet ennå.

Det som gikk galt

Mølleøkta som så rolig ut

Rundene fra en mølleøkt var tolv like lange biter uten hvile, og de så ut som en rolig tur. Draga hadde i virkeligheten gått på 3:26 til 3:30 per kilometer. Klokka lapper på hver kilometer når jeg ikke trykker selv, og hvert innslag er da en blanding av drag og pause. Analysekortet regnet gladelig på tallene uten å klage. Nå står det i minnebanken at like lange runder uten hvilerunder er autosplitt, og at strukturen må hentes ut av fartsstrømmen i stedet.

Økta som fikk full pott, og ikke fortjente det

En økt var planlagt som ti drag og ble avbrutt etter seks. De seks som ble løpt traff alle kriteriene i kortet, så kortet ga 100 poeng. Riktig regnet, helt misvisende lest. Kortet kjenner ikke planlagt volum, og det står ingen advarsel noe sted. Det er fortsatt åpent. I mellomtida må notatet under økta bære sannheten.

Snarveien til lyst tema som ikke fantes

33 gamle sider hadde et annet utseende enn resten. Jeg forsøkte én fellesløsning: ett overstyringsark som pekte de gamle fargene mot lyse verdier. Bakgrunnen ble riktig, men målingen fant mellom 11 og 121 tekstelementer per side med for svak kontrast, fordi mange paneler hadde mørke farger skrevet rett inn i seg. Jeg rullet tilbake alt. Siden har jeg tatt sidene én og én, med en måling som regner kontrast per element. Det forrige forsøket feilet fordi det ble gjort i blinde.

Datoer som var rimelige gjetninger

Da de gamle artiklene ble ført inn i oversikten, hadde mange bare årstall. Claude fordelte datoer etter hva som virket rimelig. Det står fortsatt på listen over teknisk gjeld, med begrunnelsen at feil publiseringsdato er verre enn ingen. Lærdommen er å be AI-en markere gjetninger som gjetninger.

Lesere som leser før jeg gjør det

Gjennom motivasjonssaken gikk vi fem runder. Hver runde fant jeg ting Claude ikke så selv: for mange grafer, feil metafor, et ord ingen sier og en regel som ikke stemte med min egen praksis. Leserne er et forsøk på å fange slikt før jeg må.

Det er to skills, les-loping med fem lesere og les-tech med fire, pluss en arrangør som leser foredragssida. Hver leser er en tenkt person med egne grunner til å gi opp. Kari har aldri prøvd og vil ikke føle seg dum. Leif skal ta en beslutning i et styre. Sara er utvikler og vil kjøre noe i kveld. Henrik jobber med maskinlæring og tåler ikke hype. Rapporten må ha sitat for hvert funn.

De er ikke hooks, og det er med vilje. En hook kjører av seg selv hver gang noe skjer. En hook som kjører fem lesere over hvert utkast blir noe du lærer deg å ignorere, og «nå er den klar» er en vurdering et menneske gjør. De erstatter ikke en ekte leser. De fanger det jeg ellers ville fanget selv, litt tidligere.

Figur · lesere før utgivelse
Fire lesere leser utkastet før jeg avgjør Et utkast leses av fire tenkte lesere: Kari, Leif, Sara og Henrik. Hver leser rapporterer med sitat. Rapportene samles, og jeg avgjør om teksten er klar. UTKAST Claude skriver Kari har aldri prøvd, vil ikke føle seg dum SITAT Leif skal ta en beslutning i et styre SITAT Sara vil kjøre noe i kveld SITAT Henrik tåler ikke hype SITAT Magnus leser rapportene og avgjør
  1. Claude skriver et utkast i stemmen som står i en skill.
  2. Før jeg leser, leses det av fire tenkte lesere. Hver har sine egne grunner til å gi opp.
  3. Hver av dem leser hele utkastet, ikke bare et utdrag.
  4. Regelen er sitat per funn. Et funn uten sitat er en mening.
  5. Rapportene havner hos meg. «Nå er den klar» er min vurdering, ikke en filendring.

Hva jeg ville gjort annerledes

Slik tar du det med til ditt eget prosjekt

Du trenger ikke et stort prosjekt. En liten side holder.

  1. Skriv ned reglene som aldri skal brytes, i én fil. Hold den kort.
  2. Skal noe aldri ut, så sørg for at det ikke finnes i det som publiseres, og bygg sjekken i kode.
  3. Be om et skript som kan kjøres på nytt, ikke en engangsendring. Da blir resultatet generert, og du kan stole på det.
  4. Skriv ned funn med dato, som påstander. Hold det som gjelder prosjektet adskilt fra det som gjelder deg.
  5. Gi AI-en noen lesere å skrive for, og krev sitat.
  6. Behold siste ord selv.

Her er et utkast du kan lime inn i et nytt prosjekt for å få første versjon av regelfila:

Prompt · Første regelfil
Les prosjektet i denne mappa. Skriv så et utkast til en regelfil på maks en side, med bare det som må være sant hver gang noen jobber her:
1. Hvilke filer som er generert og aldri skal redigeres for hånd.
2. Hva som aldri skal inn i prosjektet, for eksempel private data.
3. Hvilke språk og verktøy vi bruker, og hva vi bevisst ikke bruker.
4. Hvordan prosjektet kjøres lokalt, og hvordan vi sjekker at noe virker.
Ikke finn på regler. Er du usikker, still meg spørsmålet i stedet for å gjette.
Ting jeg vet allerede: [skriv her det du selv vet må med]
Les utkastet linje for linje. En regel du ikke kan stå inne for, skal ikke stå der.

Vil du ha dette som foredrag eller workshop for en gruppe? Se Foredrag og workshop. Er du leder og vil ha det på et bord, begynn med seks spørsmål til neste møte.

Oppdatert oktober 2026. Tallene er tellet i repoet 8. oktober 2026 med git og et lite Python-skript, og øktene er talt i data/okter.json. Av de sju skillsene er seks committet, og gribben-tech ligger ennå bare i arbeidskopien. Hendelsene og sitatene står i commit-meldingene, PLAN.md og .claude/LAERT.md i repoet. Medforfatterlinja i commit-meldinga viser at Claude var med, ikke hvor mye den skrev. Jeg bruker Claude Code, og hva som er mulig der, endrer seg raskt. Modellnavnene er lest i medforfatterlinjene i git-loggen, ikke i Claude Code selv.