248 ANTHEMS · TPC SAWGRASS · PONTE VEDRA BEACH, FL
The Survey Sheet
A laboratory report about the most theatrical hole in golf. The 17th supplies all the tension anyone could need; the page’s only job is to measure it accurately and get out of the way.
01The design direction
The school is Swiss editorial modernism as codified in the 248 Brand System v2 — numbered sections, mono data labels, hairline rules, condensed display type on a bone page — pushed one step further into engineering drafting. Section 04 is not a hero graphic; it is a drawing sheet, with a header strip, a plan, a numbered key column, a title block, a dimension line and a caption block. That is the whole idea: the island green is the most photographed object in American golf, so this site refuses to photograph it. It draws it.
The concept is a number. 137 yards — a wedge, on paper — and 1,068 balls in the water at THE PLAYERS since 2003. Those two facts sit next to each other without comment, and the tension does the rest. No broadcast chyrons, no splash effects, no slow-motion drama. The restraint is the concept. The brief for every decision was: would this survive in a technical report?
Signal Lime
#CCFF00 · A BALL IN THE WATER
Bulkhead Timber
#6B4A32 · RAILROAD TIES
Lagoon
#2C4A45 · THE WATER FIELD
Accent Orange
#FF6A00 · 2007, ONCE
Brand tokens hold: bone page (tuned a shade cooler for Florida lagoon light), graphite ink, and the 70/20/8/2 ratio. Two course-derived support tints appear as drawing ink and thin band tints only — bulkhead timber for the railroad-tie language of the island edge and the walkway, lagoon for the water field, the survey grid and the beat scale. Lime stays the system signal, and here it earns a second job: on this page lime is the colour of a ball in the water. Accent orange appears exactly once, on 2007 — the band, its balloon, its key entry, its tile and its row in the log. One moment, one meaning.
Type is the brand trio: Barlow Condensed for display (standing in for DIN Condensed), Inter Variable for text, IBM Plex Mono for every number and label on the drawing. Motion is measured: the frames ribbon and pulse ring run on the true 112 BPM cycle, and while a track plays a single lime needle crosses the water field once every eight beats — 4.286 seconds — with a beat scale ruled underneath it so the reader can see that it is a metronome and not a splash. Idle, the plan is completely still. With prefers-reduced-motion, the sweep does not exist at all and the sheet renders fully drawn and fully annotated.
02The data layer, and how it stays honest
The signature is not the drawing. It is the 1,068 lime marks on it — one for each ball hit into the water at the 17th at THE PLAYERS since 2003. This is the one place on the site where a visualization could quietly lie, so it is built to make lying impossible:
- Deterministic. Every mark is placed by a
mulberry32PRNG seeded with2003, the first year of the record. The sheet is identical on every load, on every machine. Nothing is randomised at view time. - Uniform, and said so. The 975 marks outside the band are sampled uniformly across the open water. There is no clustering short, no bias right, no shape of any kind — because any shape would be an invention. The caption states the distribution in plain language.
- Captioned without euphemism. “1,068 marks = 1,068 balls. Positions are illustrative; the count is the record.” And, immediately after: none of them records where a ball actually finished.
- The 2007 band is labelled as a reading aid. The single-year high of 93 is grouped into a dashed annular band so that one season is legible against the other twenty-odd. The caption says the grouping is a reading aid, not a location. The 975 are excluded from that band so the band holds exactly 93 — a claim the reader could verify by counting.
- The sheet counts itself. The title block and the tally line under the drawing are not typed in. They are read back from the DOM after plotting:
ballsG.children.length + hiG.children.length. If the generator ever failed to place all 1,068, the tally would print a different number in orange rather than a reassuring one in lime. - The estimate is flagged as an estimate. The ~100,000+ balls a year from everyday golfers is the PGA Tour’s own estimate, and it is the only figure on the page that is not a count. Its tile is greyed, carries a black
PGA TOUR ESTIMATEflag, and says in the body copy that it is the only unmeasured number here.
Marks yield to annotation: the generator rejects any position inside the island, its bulkhead margin, the walkway, the tee, the dimension line and plate, or a balloon and its leader. That keeps the drawing readable, and the caption says so too — so the reader knows the empty channels are draughting, not data.
03How it was built
- Hand-written static HTML/CSS/JS — no framework, no authoring build step. ES modules only.
- Every internal reference is relative (
css/style.css,./player.js,manifest-fallback.json; from the guide,../css/…), so the site works served from a domain root or from a subpath. - No raster images anywhere. The entire visual world is type, CSS and one inline SVG. The island shape is a 16-point radial profile interpolated with a periodic Catmull-Rom spline, so one function produces the island outline, the green outline at 0.76 scale, the outward normals for all 104 bulkhead ticks, and the exact keep-clear test for the mark field. Geometry defined once, used five ways.
- The plan’s key column is a real title block: numbered balloons on the drawing map to numbered entries in the column, and the column carries the two figures the sheet exists to report.
- Fonts are self-hosted woff2 (latin subsets) from @fontsource packages;
build.mjsrestores them from npm at deploy time via thedeployAssetsmap, so deploy uploads stay text-only. - The ratio stripe is 32 real units — 24 graphite, 8 lime — and the copy inside the player panel encodes actual playback progress across those units.
- Deployed as its own Vercel project (
248-anthems-sawgrass) from the series monorepo, withcleanUrlsand immutable font caching.
04The audio pipeline
The player is the shared 248 core (player.js), skinned through its CSS custom properties into the dark panel of section 01 and mounted with an explicit two-track playlist — TPC Sawgrass — Anthem (Remastered) and TPC Sawgrass — Hype Anthem. Masters stream from the shared CORS-enabled audio host (248-anthems-audio.vercel.app); its manifest.json is the single source of truth, with a committed fallback copy so the page still knows its own tracks if the host is unreachable. Track titles, versions and durations come from that manifest and nowhere else.
Live visuals draw only from live audio: the spectrum behind the player reads the Web Audio analyser, and the pulse ring is driven by the real RMS level while playing. When nothing is playing, the ring breathes on the brand tempo (60/112 s) rather than faking a signal — and the plan is simply still. The metronome sweep is bound to body.is-playing, so it exists only when there is actually something to keep time with.
05The facts rule
Every course number and claim on the page comes from docs/facts/sawgrass.md; every tempo claim comes from docs/facts/tempo-science.md; all track data comes from the audio manifest. Verified and used: Pete Dye with Alice Dye; built 1980 as the permanent home of THE PLAYERS; commissioned by Commissioner Deane Beman; 415 acres of wooded wetlands bought by the Tour for a ceremonial $1 in February 1978; the first true Stadium Course, with spectator mounds and tiered sightlines; par 72 and 7,352 yards; hole 17 par 3 at 137 yards; Alice Dye proposing the island after excavation around the green; 1,068 balls in the water at THE PLAYERS since 2003; the single-year high of 93 in 2007; the 3.12 scoring average and the hardest sub-150-yard par 3 on Tour over that span; the PGA Tour’s ~100,000+ balls a year estimate for everyday players; hole 16 par 5 at 523 yards, reachable, lake right shared with 17; hole 18 par 4 dogleg left with water down the entire left side; THE PLAYERS here since 1982 and Jerry Pate throwing Beman and Dye into the lake before jumping in himself; Tiger Woods’ 2001 60-foot triple-breaking birdie on 17, Gary Koch’s “Better than most!”, and the one-shot win over Vijay Singh; Rickie Fowler’s 2015 six-under closing six holes, the playoff over Kisner and Garcia and the birdie at 17 in sudden death; the course record of 62 by Tom Hoge in round 3, 2023; and the landscape vocabulary — water, wooden bulkheads and railroad ties, pot bunkers, contoured greens, amphitheater mounds, pines, palmettos, lagoons.
Omitted: Pete Dye verbatim quotes, which the facts file marks unverified — so no designer quotation appears anywhere on this site, including as atmosphere. Also omitted: any yardage for the 18th (the verified record carries none, and the ledger prints an em dash with a note explaining why rather than guessing); the 17th green’s square footage; any per-hole yardage not listed; any claim about how many balls a given player has hit in the water; and any assertion about where balls land. 112 BPM is presented as engineering arithmetic — 24 frames ÷ 30fps = 0.80 s ≈ 1½ beats — never as a research finding, and the tempo footnotes name their sources and their caveats (the Yale work is an arXiv preprint and is called a “Yale physics study,” not peer-reviewed).
06Iteration passes
Found: (1) the balloon for the 2007 band pointed its leader into open water, several units short of the band it was labelling — the one annotation on the drawing that had to be exact, and it missed. Re-targeted to the band’s outer edge. (2) On phones the sheet carried its full desktop key column, so the reader had to pan across 45% of a 1,000-unit drawing before reaching the drawing itself. Below 1,080px the SVG now narrows to a 0 0 800 700 viewBox — dropping the key column entirely — and the key is rebuilt as an HTML list under the plan from the same array of balloons, so there is still exactly one source for it. (3) The lagoon tint on the water field was so weak that water and island read as two greys; raised the water to 13% lagoon and the island collar to 17% timber so the land separates without either becoming a colour block. (4) The keep-clear zone around the 137 dimension was 52 units wide and opened a visible empty corridor through the mark field; tightened to 38, which the dimension plate now covers. (5) The guide’s prose ran straight into the bottom of its bulleted lists with no spacing. Also confirmed here: the tally under the plan read 1,068 / 1,068 on the first build, so the generator was placing the whole record, not a rounded-off approximation of it.
Found: (1) a real bug — the page scrolled horizontally on every viewport under about 660px. The sheet is a grid item whose child is a scroll container, and a grid item’s automatic minimum size is its min-content width, so the drawing’s minimum width was pushing the whole document wide. Added min-width: 0 to the sheet and changed the stacked grid to minmax(0, 1fr); the document now measures exactly the viewport at every width tested, and the only thing that pans is the drawing, inside its own frame. (2) With a track playing, the metronome sweep was a 190-unit lime wash at up to 42% opacity — a splash effect, which is precisely what the brief forbids. Cut to a 132-unit trail topping out at 17% behind a 1.3-unit needle: it now reads as a bar passing over the record, and the beat scale ruled underneath it makes the reason legible. (3) The “drag to pan” hint showed at tablet widths where the sheet already fit; it is now driven by a real measurement of scroll width against client width, and the drawing’s minimum was trimmed to 620px so that nothing between roughly 660px and the desktop layout needs panning at all — only true phone widths do. (4) Contrast: the tally figure, the dark panel’s captions and the deep orange were each below 4.5:1 at their small sizes — darkened the lime ink to #5A7100 and the deep orange to #A33E00, and lifted the two mono captions on the charcoal panel. Verified by simulation: the reduced-motion render is fully drawn, fully annotated and completely still, with no sweep at all; and 975 + 93 = 1,068 marks in the DOM, matching the printed tally.