teecup/frontend/app/t/[id]/page.tsx
Erol Haagenrud 1e491d73b3 MinIO-runden er ferdig, verifisert og live — ADR-018 er nå helt komplett, ingenting utsatt igjen bortsett fra selve opplastings-skjermen i frontend.
Presiseringen din midt i byggingen (AVIF) endret arkitekturen til det bedre: droppet den opprinnelige planen med presignerte nettleser-URL-er til fordel for ekte multipart-opplasting gjennom API-et, som konverterer til AVIF (Pillow) før lagring. Dette forenklet ting betydelig — kun én MinIO-klient trengs nå, og Caddy-ruten slapp den skjøre signatur-Host-header-følsomheten presignering ville krevd.

To reelle feil funnet under scratch-verifisering, aldri i produksjon:

pillow-avif-plugin testet frittstående først — fungerer uten ekstra systempakker.
MinIO avviser understrek i vertsnavn (teecup_minio feilet umiddelbart) — rettet til teecup-minio (bindestrek) før noe ble forsøkt mot ekte infrastruktur.
Caddy-ruten unngikk en skjult DNS-felle: en ny subdomene ville pekt til en IPv6-adresse denne serveren ikke har — løst med en sti-prefiks (/teecup-media/*) på det eksisterende domenet i stedet.

Verifisert i flere lag: ekte bilde lastet opp i scratch, bekreftet konvertert til gyldig AVIF, bekreftet lesbart anonymt direkte mot MinIO, alle tre valideringsveier (ugyldig format, korrupt fil, for stor fil) testet. Etter Caddy-omstart: et ekte anonymt kall mot produksjonsdomenet ga en ekte MinIO-feilrespons — beviser ruten treffer MinIO, ikke frontend sin 404-side. teeoff.no upåvirket gjennom hele runden.

Bevisst ikke gjort: et ekte bilde lastet opp til en ekte, live turnering (ville skrevet i din ekte konto uten at du ble spurt) — tilbys, ikke utført.

Vil du at jeg tester en ekte opplasting mot en av dine eksisterende turneringer, eller går vi videre til neste V0-skjerm (økt/program, blind draw, scorekort eller leaderboard)?
2026-07-18 11:25:52 +02:00

52 lines
1.7 KiB
TypeScript

import type { Metadata } from "next"
import { PublicTournament } from "@/components/public-tournament"
// Server-side -- IKKE nettleser-fetch, går derfor IKKE gjennom
// next.config.mjs sin rewrites() (kun for trafikk inn til Next.js-serveren
// fra en klient). Peker direkte på API-et.
const API_ORIGIN = process.env.TEECUP_API_ORIGIN || "http://localhost:8000"
type PublicTournamentInfo = {
name: string
organization_name: string
description: string | null
hero_image_url: string | null
}
export async function generateMetadata({
params,
}: {
params: Promise<{ id: string }>
}): Promise<Metadata> {
const { id } = await params
try {
const res = await fetch(`${API_ORIGIN}/public/tournaments/${id}`, { cache: "no-store" })
if (!res.ok) {
return { title: "Turnering | TeeCup" }
}
const data: PublicTournamentInfo = await res.json()
const title = `${data.name} | ${data.organization_name}`
const description =
data.description?.trim() || `${data.name} arrangeres av ${data.organization_name} på TeeCup.`
const images = data.hero_image_url ? [{ url: data.hero_image_url }] : undefined
return {
title,
description,
openGraph: { title, description, siteName: "TeeCup", type: "website", images },
twitter: { card: images ? "summary_large_image" : "summary", title, description, images },
}
} catch {
// Feil her skal ALDRI hindre selve siden i å laste -- kun forringe
// delingsforhåndsvisningen, som fortsatt får en trygg standardtittel.
return { title: "TeeCup" }
}
}
export default async function PublicTournamentPage({
params,
}: {
params: Promise<{ id: string }>
}) {
const { id } = await params
return <PublicTournament tournamentId={id} />
}