2026-07-17 21:57:44 +02:00
|
|
|
// API-et proxyes server-side under samme opprinnelse (ingen CORS, cookien
|
|
|
|
|
// fungerer uendret) -- se ADR-009/015. TEECUP_API_ORIGIN peker mot en lokal
|
|
|
|
|
// backend i dev; i prod peker den mot teecup_api på det delte Docker-nettverket.
|
|
|
|
|
const API_ORIGIN = process.env.TEECUP_API_ORIGIN || "http://localhost:8000"
|
|
|
|
|
|
2026-07-17 21:40:42 +02:00
|
|
|
/** @type {import('next').NextConfig} */
|
|
|
|
|
const nextConfig = {
|
Alt rent, ingen byggeartefakter liggende igjen, dokumentasjonen oppdatert. Oppsummering:
Live og verifisert ende-til-ende:
/verify-siden bygget og live, e-postmalen sender nå en ekte klikkbar lenke (app/email.py/app/config.py)
Frontend containerisert (frontend/Dockerfile, standalone Next.js) og rullet ut som egen teecup_frontend-tjeneste
Caddy peker nå teecup.teeoff.no på frontend-en, som selv proxyer API-kall server-side — same-origin, ingen CORS, cookie uendret (dokumentert som ny ADR-016)
Fant og fikset en reell fallgruve: Next.js sin rewrites() bakes inn ved build-tid for standalone-output, ikke lest ved kjøretid — løst med en Docker build-time ARG
Ekte e-post sendt, ekte lenke klikket, sesjon opprettet — bekreftet av deg
Én ting du må huske: Caddy-endringen ligger i det separate /opt/teeoff-repoet (deploy/Caddyfile), ikke i teecup-repoet — den er ikke committet ennå. Lett å glemme siden resten av denne økten kun har jobbet i /opt/teecup. Vil du at jeg minner deg, eller committer du den nå selv i teeoff-repoet?
CLAUDE.md, FEATURE_BACKLOG.md og ARCHITECTURE_DECISIONS.md (ny ADR-016) er oppdatert. Klar for commit i teecup-repoet når du vil.
2026-07-17 22:28:43 +02:00
|
|
|
output: "standalone",
|
2026-07-17 21:40:42 +02:00
|
|
|
images: {
|
|
|
|
|
unoptimized: true,
|
|
|
|
|
},
|
2026-07-21 09:03:52 +02:00
|
|
|
// MERK (funnet 2026-07-19, se FEATURE_BACKLOG.md): en plain array her gir
|
|
|
|
|
// implisitt "afterFiles"-semantikk -- statiske filer/sider sjekkes FØR
|
|
|
|
|
// disse rewrites, men DYNAMISKE Next.js-sider (app/x/[id]/page.tsx)
|
|
|
|
|
// sjekkes ETTER. En frontend-SIDE må derfor ALDRI nestes direkte under
|
|
|
|
|
// et av prefiksene under (f.eks. /orgs/[id]/members) -- rewrite-regelen
|
|
|
|
|
// vinner presedens og siden blir uoppnåelig (rå API-404 i stedet).
|
|
|
|
|
// Legg nye frontend-sider et sted UTENFOR disse prefiksene (se
|
|
|
|
|
// app/organizations/[id]/members for eksempelet dette ble rettet på).
|
Update Todos
Diagnostisere de to feilmeldingene fra skjermbildene
Flytte frontend-sidene fra /rounds/* til /my-rounds/* (kollisjon med API-proxyen)
Oppdatere alle interne lenker/router-kall til nye stier
Oppdatere next.config.mjs-kommentaren med denne lærdommen
Typesjekket produksjonsbuild
Rulle ut live etter bekreftelse
Oppdatere statusdokumentasjon
Fant og fikset rot-årsaken til begge feilmeldingene — en reell, alvorlig bug, ikke bare kosmetikk:
/rounds var samtidig navnet på både frontend-listesiden og backend-APIets ressursprefiks. Next.js sin rewrite-presedens ("afterFiles") gjorde at:
GET/POST /rounds fra klienten aldri nådde backend — den statiske siden vant, så fetch() fikk Next sin egen HTML tilbake i stedet for JSON. Det ga akkurat de to feilmeldingene i skjermbildene.
/rounds/[id] (rundedetaljsiden) hadde det motsatte problemet — der vant rewriten, så selve siden var fullstendig uoppnåelig (ville vist rå backend-JSON i stedet for UI-et om du hadde kommet så langt).
Dette er nøyaktig samme klasse feil som medlemsside-hendelsen under ADR-016, bare i begge retninger samtidig siden det denne gangen var en eksakt navnekollisjon, ikke bare nøsting.
Fikset: flyttet alle tre frontend-sidene til /my-rounds/* (list, new, [id]) — API-et beholder /rounds uendret. Oppdatert alle interne lenker (round-card.tsx, own-rounds.tsx, new-round.tsx, round-detail.tsx, dashboard.tsx), lagt inn en tydelig advarsel i next.config.mjs for å hindre at dette gjentar seg. Bekreftet: «55/50/44/32» i det andre skjermbildet er ikke en bug — det er Tjøme Golfklubb sine faktiske utslagsnavn i teeoff (lengde i hundremeter).
Typesjekket produksjonsbuild kompilerer rent med de nye rutene.
2026-07-23 12:07:40 +02:00
|
|
|
//
|
|
|
|
|
// SAMME FELLE, VERRE UTSLAG (funnet 2026-07-23, ADR-033): en EKSAKT
|
|
|
|
|
// kollisjon (ikke bare nøsting) mellom en frontend-side og et
|
|
|
|
|
// rewrite-prefiks slår begge veier. `/rounds` var opprinnelig BÅDE en
|
|
|
|
|
// frontend-liste-side OG rounds.py sitt API-prefiks -- statisk side vs.
|
|
|
|
|
// eksakt rewrite: SIDEN vant, så `fetch("/rounds")`/`POST /rounds` fra
|
|
|
|
|
// klienten traff aldri backend (fikk Next sin egen HTML tilbake, JSON-
|
|
|
|
|
// parsing feilet stille). `/rounds/[id]` (DYNAMISK side) vs.
|
|
|
|
|
// `/rounds/:path*`: REWRITEN vant, så selve rundedetalj-siden var
|
|
|
|
|
// fullstendig uoppnåelig (rå backend-JSON i stedet for UI-et). Løst ved
|
|
|
|
|
// å flytte frontend-sidene til et HELT ANNET toppnivå-prefiks
|
|
|
|
|
// (`/my-rounds/*`) som ikke overlapper `/rounds/*` i det hele tatt --
|
|
|
|
|
// API-et beholder `/rounds` uendret. Lærdom: et rewrite-prefiks og en
|
|
|
|
|
// frontend-sides toppnivå-segment må ALDRI være identisk streng, selv
|
|
|
|
|
// om det virker naturlig (f.eks. "runder" for begge).
|
2026-07-17 21:57:44 +02:00
|
|
|
async rewrites() {
|
|
|
|
|
return [
|
|
|
|
|
{ source: "/auth/:path*", destination: `${API_ORIGIN}/auth/:path*` },
|
|
|
|
|
{ source: "/orgs/:path*", destination: `${API_ORIGIN}/orgs/:path*` },
|
Registrerings-API-et er live på https://teecup.teeoff.no. Oppsummert:
Bygget: GET /public/tournaments/{id} og POST /public/tournaments/{id}/register — helt uautentisert, egen /public-prefiks. players.py utvidet med alle sju nye feltene.
Grundig scratch-testet, ikke bare "kjørte uten feil": samtykke-avvisning, duplikat-avvisning, e-post-matching mot en organisator-forhåndsopprettet spiller (bekreftet ingen duplikat, mobil fylt inn, navn ikke overskrevet), kapasitet+venteliste, kapasitet+stengt, godkjenningskrav, utløpt frist — alle seks scenarioene fra ADR-en testet én etter én og ga riktig resultat.
Notatet ditt om synlighet er fanget i FEATURE_BACKLOG.md, koblet til det samme åpne spørsmålet for «Banter Board»-feeden — før dette API-et ble bygget, ikke etter, slik du ba om.
Gjenstår, bevisst utsatt:
E-post-basert kontosammenkobling ved innlogging (ADR-017 Beslutning B sin andre halvdel) — trenger en ny SECURITY DEFINER-funksjon på tvers av org-er, altså migrasjon 008 siden 007 alt er kjørt mot prod. Ikke gjort i denne runden.
Selve påmeldingsflyten er ikke testet med ekte data mot prod (kun ikke-destruktive sjekker: ukjent turnering ga korrekt 404).
Landingssider — egen ADR-runde, som avtalt.
2026-07-18 08:50:03 +02:00
|
|
|
{ source: "/public/:path*", destination: `${API_ORIGIN}/public/:path*` },
|
Update Todos
Legge til argon2-cffi, pyotp, qrcode i requirements.txt
Skrive migrasjon 012 (passord, 2FA, superadmin, org-invitasjoner)
app/auth.py: sesjonsstadier, passord-hashing, TOTP-hjelpere
app/routers/auth.py: passord-innlogging, 2FA-oppsett/verifisering
app/email.py: 2FA-kode og invitasjons-maler
app/routers/organizations.py: invitasjoner, medlemskapsstyring, superadmin-sti
Frontend: login-form passord-modus + 2FA-skjermer
Frontend: kontoinnstillinger + org-medlemsstyring-skjerm
Ekte typesjekket frontend-build
Scratch-verifisere hele auth-løpet grundig (backend)
Deploy mot ekte teecup_db/containere + oppdatere .md-filer
Backend og frontend er grundig scratch-verifisert — inkludert tre reelle bugs jeg fant og fikset underveis (en UUID-serialiseringsfeil i magic-link-innlogging, og to tilfeller av en uendelig 2FA-løkke der en nettopp bekreftet kode ble sjekket på nytt). Alle sikkerhetsvern testet eksplisitt: siste-eier-vern, blokkert selv-forfremmelse, admin kan ikke gi eierskap, superadmin fungerer/avvises riktig, tvungen 2FA for nye eiere, passord med spesialtegn/mellomrom, og bakoverkompatibilitet med eksisterende magic-link-flyt.
Klar til utrulling mot ekte systemer:
Migrasjon: 012_password_2fa_and_org_invitations.sql mot ekte teecup_db
Redeploy: både teecup_api og teecup_frontend
AskUserQuestion
2026-07-19 10:36:50 +02:00
|
|
|
{ source: "/superadmin/:path*", destination: `${API_ORIGIN}/superadmin/:path*` },
|
Migrasjonen er kjørt, og jeg har fortsatt helt til et komplett, verifisert API-lag.
Underveis fant og fikset jeg et reelt hull: round_participant manglet kolonner for selve rating-tallene (kun tee-navnet var lagret) — løst med migrasjon 021, kjørt mot ekte database sammen med resten.
Bygget og rullet ut:
app/routers/rounds.py — opprett/liste/hent/slett runde, legg til/fjern gjestedeltakere, registrer statistikk hull for hull, og en fullfør-endepunkt som kjører hele kjeden (Adjusted Gross Score → Score Differential → tellende-vurdering).
26 scratch-sjekker grønt, pluss en egen test mot den ekte kjørende teeoff-tjenesten som bekreftet at live-oppslaget fungerer nøyaktig som tiltenkt (ingen bane-kopi skrives noe sted).
Begge migrasjoner + ny kode er nå live mot ekte teecup_db/teecup_api. teeoff.no upåvirket.
Jeg la også inn /rounds og /personal-courses i frontendens proxy-oppsett proaktivt, siden prosjektet har blitt bitt av glemte proxy-ruter før — ikke deployet ennå, tas med neste gang frontend faktisk bygges.
Notatet om slaglengde-måling og avstand-til-punkter-på-banen er lagret i CLAUDE.md og FEATURE_BACKLOG.md, med en tydelig flagget avhengighet: dette krever geografiske/GPS-data som ingen nåværende kilde (verken teeoff eller den nye banekatalogen) har.
2026-07-22 11:31:08 +02:00
|
|
|
{ source: "/rounds/:path*", destination: `${API_ORIGIN}/rounds/:path*` },
|
|
|
|
|
{ source: "/rounds", destination: `${API_ORIGIN}/rounds` },
|
|
|
|
|
{ source: "/personal-courses/:path*", destination: `${API_ORIGIN}/personal-courses/:path*` },
|
|
|
|
|
{ source: "/personal-courses", destination: `${API_ORIGIN}/personal-courses` },
|
2026-07-17 21:57:44 +02:00
|
|
|
{ source: "/health", destination: `${API_ORIGIN}/health` },
|
|
|
|
|
]
|
|
|
|
|
},
|
2026-07-17 21:40:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default nextConfig
|