ReviewOS

also looking at this

stacks/lastsoulultra

LSU's own coaching surface, and what auditing the site turned up

#12
Merged glennmichael123 wants to merge claude/last-soul-ultra-web-6e0718 into main
86 files +3943 -1190

Review threads live on the whole diff, not on one commit, so none are shown here - a thread's line means something in the branch's final form, and painting it into an intermediate step would put it on code it is not about.

public/assets/images/race/board-1080.jpgdeleted+0-0

Binary file. Nothing to show line by line.

public/assets/images/race/board-540.jpgdeleted+0-0

Binary file. Nothing to show line by line.

public/assets/images/race/board-810.jpgdeleted+0-0

Binary file. Nothing to show line by line.

public/assets/images/race/loop-1080.jpgdeleted+0-0

Binary file. Nothing to show line by line.

public/assets/images/race/loop-540.jpgdeleted+0-0

Binary file. Nothing to show line by line.

public/assets/images/race/loop-810.jpgdeleted+0-0

Binary file. Nothing to show line by line.

public/assets/images/race/night-1080.jpgdeleted+0-0

Binary file. Nothing to show line by line.

public/assets/images/race/night-540.jpgdeleted+0-0

Binary file. Nothing to show line by line.

public/assets/images/race/night-810.jpgdeleted+0-0

Binary file. Nothing to show line by line.

public/assets/images/race/refuel-1080.jpgdeleted+0-0

Binary file. Nothing to show line by line.

public/assets/images/race/refuel-540.jpgdeleted+0-0

Binary file. Nothing to show line by line.

public/assets/images/race/refuel-810.jpgdeleted+0-0

Binary file. Nothing to show line by line.

resources/data/media.tsdeleted+0-82
Changes to resources/data/media.ts
@@ -1,82 +0,0 @@
1/**
2 * Race photography, published by the organiser on lastsoulultra.com and shot
3 * by rappid at the race.
4 *
5 * Only frames that have actually been looked at appear here, and each alt
6 * describes what is in that specific frame. Alt text written from a filename
7 * is worse than none: it tells a screen-reader user something confidently
8 * wrong, and nobody sighted ever notices.
9 *
10 * Served from this origin. They used to be hotlinked from the organiser's
11 * Squarespace CDN, which sent every visitor's IP to a third party the privacy
12 * policy did not name, and made every photograph on the site depend on a host
13 * we do not control and cannot cache.
14 *
15 * The four originals are 1080x1350, so the ladder stops at 1080 - Squarespace
16 * happily answered a request for 1600w with the same 1080px file, which is how
17 * the site came to believe it had widths it never had. Regenerate with
18 * `bun run scripts/photos.ts` (macOS only, uses sips).
19 */
20
21export interface Shot {
22 /** Slug on disk, not a URL: `<DIR>/<src>-<width>.jpg`. */
23 src: string
24 alt: string
25 /** Roughly how the frame is composed, so a slot can pick one that fits. */
26 orientation: 'portrait' | 'landscape'
27}
28
29/** Widths on disk. Nothing above 1080 exists, because nothing above 1080 was
30 * ever shot. */
31export const WIDTHS = [540, 810, 1080] as const
32
33const DIR = '/assets/images/race'
34
35export const shots = {
36 /**
37 * The lap board, and the best single image the race has: it states the
38 * format in the brand's own red without a word of explanation.
39 */
40 board: {
41 src: 'board',
42 alt: 'The race board lit red at dusk, reading 90 souls remaining, 7 laps, 46.9 total km',
43 orientation: 'portrait',
44 },
45 /** A runner caught by the flash against fog, out on the loop after dark. */
46 night: {
47 src: 'night',
48 alt: 'A runner in a pale jacket and rappid. cap lit by a flash against fog and darkness, carrying a soft flask',
49 orientation: 'portrait',
50 },
51 /** The gap between hours, which is the whole tactical problem of the format. */
52 refuel: {
53 src: 'refuel',
54 alt: 'A runner in a rappid. cap eating instant noodles from a cup, resting between laps',
55 orientation: 'portrait',
56 },
57 /** Daylight on the loop, wet road, somewhere in the middle of the race. */
58 loop: {
59 src: 'loop',
60 alt: 'A runner in a black jacket and rappid. cap running back down a wet country road at dawn',
61 orientation: 'portrait',
62 },
63} satisfies Record<string, Shot>
64
65/**
66 * The frame at the width a slot actually paints, snapped UP to a width that
67 * exists on disk. Asking for something we do not have used to yield a working
68 * URL from the CDN; now it would 404, so the snap is what keeps a template
69 * free to name the width it wants.
70 */
71export function at(shot: Shot, width: number): string {
72 const w = WIDTHS.find(candidate => candidate >= width) ?? WIDTHS[WIDTHS.length - 1]
73 return `${DIR}/${shot.src}-${w}.jpg`
74}
75
76/** 1x and 2x, so a retina screen gets the sharp file and a phone does not. */
77export function srcset(shot: Shot, width: number): string {
78 return `${at(shot, width)} 1x, ${at(shot, width * 2)} 2x`
79}
80
81/** The strip on the home page, ordered the way a race night runs. */
82export const recap: Shot[] = [shots.board, shots.loop, shots.refuel, shots.night]