Skip to content

Cloudflare analytics statement, history corrections, drink page report line, Bar tab tiers, manifest screenshots, skip links, 32px chips, built highball or flute - #120

Merged
cjimti merged 1 commit into
mainfrom
bar-copy-drink-pages-papercuts
Sep 13, 2026

Conversation

@cjimti

@cjimti cjimti commented Sep 13, 2026

Copy link
Copy Markdown
Owner

Five tickets from the #99 deep QA. Hand-written change is about 220 lines added and 50 removed across 17 files; the rest is regenerated output (185 drink pages, sitemap.xml, llms-full.txt, three share cards) and two new screenshot PNGs.

Closes #100. Closes #103. Closes #106. Closes #115. Closes #116.

#100 Analytics statement

Cloudflare Web Analytics is still auto-injected on the live zone (checked with a browser User-Agent on 12 September), so this takes the "keep it and say so" outcome.

  • index.html Info tab, Analytics: a sentence naming Cloudflare's cookieless script beside Google Analytics; "That is the whole list" becomes "Those two are the whole list"; "It tells me nothing" becomes "Neither tells me"; the last paragraph says Cloudflare's script is added at the edge and is not in the source.
  • humans.txt: Analytics: Google Analytics and Cloudflare Web Analytics, aggregate only.

If the beacon is later turned off in the dashboard, both sentences need to come back out.

#103 History corrections

Prose only, in data/cocktails.json. No recipe, code, build or ref changed.

  • scofflaw: Henry Irving Dale (was Shaw); the contest ran in late 1923 and the word was announced in January 1924.
  • bees-knees: Brooklyn Standard Union 22 April 1929 (was 23), matching stingless-bee.
  • cock-n-bull-special: Bottoms Up, no apostrophe.
  • vodka-martini: the 1951 Bottoms Up (was 1952). The 1962 revised edition in salty-dog stays.
  • barbary-coast: Gaige's Cocktail Guide and Ladies' Companion 1941 (was 1945), matching fancy-free.
  • pegu-club: "Craddock's lime is a teaspoonful" (Rose's dropped).
  • whiskey-sour: the Oxford Companion entry in its refs does carry 1826 ("first appears in print as early as 1826, in a list of ways that whisky could be drunk"), so the date stays and the sentence now attributes it.
  • negroni-sbagliato: adds "Bar Basso itself says 1972."
  • ritz: "The printed menu left the Champagne off" (was "printed card"), from Papercuts: manifest fields and screenshots, a skip link, 32px chips, the offline sentence, three imperatives, hat-tip refs, card in the Ritz, the flute, the With chip #116.

#106 Drink pages say what the site is and where corrections go

scripts/pages.py:

  • Under the code: "The code is the shorthand off my printed menu; the Key tab decodes every letter." with Key tab linked to /#key (.page__key).
  • The all-drinks line becomes "This is one drink on my home bar's menu. Tick the bottles you own and the menu lists which of all 185 drinks they pour."
  • Footer, after the author and site links: "A wrong measure or a bad date is an issue at github.com/cjimti/drink/issues." linked to the issues page (REPORT).

The same footer sentence is added by hand to 404.html and offline.html, and once to the Info tab under Version. .page__key joins .page__open, .page__all and .page__foot in the print rule that hides them.

#115 Bar tab

  • data/bar.json tiers: Campari, Luxardo Maraschino, Bénédictine, St-Germain, Cynar 33 Proof and Fernet-Branca move to solid, so no tier heading sits over a lone bottle that the copy defines as a mixing bottle. Chartreuse stays excellent: Green and Yellow are two bottles of one brand, not a category with a mixing tier.
  • Brand names: El Dorado 12 Year, Sazerac 6 Year Rye, Old Forester Rye 100 Proof, Rittenhouse Rye 100 Proof, Lucid Absinthe Supérieure. Brand ids unchanged (they are localStorage keys). No price changed.
  • assets/app.js: TIER_GLOSS renders one line under the Alternatives heading, "A different bottle that does the same job. The drink changes and still pours." (.brands__gloss).
  • Next bottles lead: "The bottles that add the most drinks, and what each one opens." grep -c "recommended\|grow your" assets/app.js is 0.

Not changed, for a look against a receipt: Tanqueray 1.75L is listed at $25 beside Beefeater 1.75L at $35.

#116 Papercuts

  1. Manifest. id: "/" (resolves to the same https://fewbottles.com/ identity installed apps already carry, since it previously defaulted to start_url), lang, dir, categories, and two screenshots with form_factor narrow (780×1688) and wide (2560×1600) in assets/screens/. Taken from the live site at v1.5.0, dark, Martini open, via headless Chrome device emulation at 2x, quantised to 59 KB and 99 KB. theme_color left as the dark ground; index.html already carries per-scheme theme-color meta tags. New check_screenshots() in scripts/check_assets.py refuses a missing file, a sizes that does not match the PNG header, or a missing narrow or wide form factor; four cases in test_checks.py (shot/clean, shot/wrong size, shot/no file, shot/no wide). Screenshot paths join the manifest references check_served walks.
  2. Skip links. Skip to content (to #main) and Skip to tabs (to the new id="tabbar", hidden at 900px and up where the tabs are in the top bar). A plain #main href would reach route() and switch to the Menu, so skipTo() in app.js prevents the navigation and focuses the target. The target gets tabindex="-1" only while it holds focus and loses it on blur; a permanent one on #main would let Safari hand focus to the whole scroller on any tap that lands on a button it does not focus. Wired before the data fetch. Off screen until focused, offset by env(safe-area-inset-top).
  3. Chips. .chip is 32px tall through line-height: 14px; padding: 8px 11px. An inline-flex version was tried first and dropped: it collapses the space inside ✓ All bottles and before the arrow in Starter Shelves →. The two-row bottle chip clamp moves from 60px to 70px.
  4. offline.html: "so there is no saved copy to show while you are offline."
  5. Info tab: the three imperatives become "Here you tick what you have, and the menu shows which bottle opens the most drinks next."
  6. hat-tip refs: already handled on main. pages.py and renderRefs() both omit the block when refs is empty; confirmed on the page and in the app. No change.
  7. ritz: see History: seven claims to correct, starting with the Scofflaw's Henry Irving Dale #103 above.
  8. Flute. data/notation.json glass h gains label_built: "Highball or flute" and gloss_built: "no ice, sparkling wine on top". No glass letter changed. glassFor(d) in app.js and serve_line() in scripts/llms.py use them for a built drink in h (a fizz is shaken, so every built h is a Champagne top). Champagne Cocktail, Death in the Afternoon and Seelbach read "Highball or flute (no ice, sparkling wine on top)" in the app, "Highball or flute, lemon twist." on their pages and in the JSON-LD steps, "Highball or flute" in llms-full.txt, and "Built, highball or flute, orange twist" on their three redrawn cards. The short label is used off the app because the card's serve line is a single unwrapped line beside the glass. The unused glass field is removed from readServe().
  9. With chip. unlockLabel() renders a <span class="chip chip--pour is-on chip--label"> instead of a button aria-pressed="true" that no click branch handled. Out of the tab order, cursor: default, same height and look.

Verification

make verify passes: 260 test cases, 185 pages current, 185 cards current, served 7151 references inside SERVED.

Adversarial pass before testing found and fixed three things: the inline-flex whitespace collapse in chips, the permanent tabindex="-1" on #main, and the skip link sitting under the notch in standalone mode.

Browser checks, headless Chrome over the DevTools protocol against make serve on 8010:

  • Chips measure 32px at 390px and 1280px; ✓ All bottles and Starter Shelves → keep their spaces; the wide bottle row still clamps at two rows under "All 28 bottle filters".
  • Shift+Tab back from the brand link reaches Skip to tabs, then Skip to content, both visible at 16px. Enter on Skip to tabs focuses the tab bar with tabindex="-1", the next Tab lands on the Menu tab, and the attribute is gone after blur. At 1280px only Skip to content is in the order. Skip to content clicked on the Bar tab focuses #main and leaves the address at #bar with the Bar view still shown.
  • Glass line: Champagne Cocktail, Death in the Afternoon and Seelbach read the built label and gloss; Gin Fizz keeps "Highball (tall glass, no ice: a fizz)"; Gin and Tonic keeps "Highball, iced (...)".
  • Bar tab with gin, dry vermouth, orange bitters and lemon ticked: the new lead line renders; Cynar shows Solid over Cynar 33 Proof and Alternatives with the gloss over the four amari; Rye shows the normalised names. Tapping Bénédictine's +3 opens the Menu with a SPAN label "✓ With Bénédictine · 3", 32px, tabIndex -1.
  • Drink pages at 390px in dark and light: the Key line, the all-drinks line and the footer sentence render and wrap cleanly. With print media emulated, .page__key, .page__all and .page__foot compute to display: none.
  • offline.html carries the new sentence and footer; hat-tip renders no .recipe-refs.
  • Seelbach card inspected after redraw: the serve line fits beside the glass.

Not verified: a real phone, VoiceOver, Safari or iOS (including the safe-area offset and the blur removal of tabindex), Chrome's install sheet actually showing the screenshots, Lighthouse, a print preview of the Menu list (no list markup changed), and the Rich Results Test on the changed JSON-LD steps.

…t line, Bar tab tiers, manifest screenshots, skip links, 32px chips, built highball or flute

Info tab Analytics section and humans.txt name the Cloudflare Web Analytics script beside Google Analytics.

History fixes in data/cocktails.json: Scofflaw winner Henry Irving Dale and the 1923 contest, Bee's Knees 22 April 1929, Saucier's Bottoms Up 1951 in cock-n-bull-special and vodka-martini, Gaige 1941 in barbary-coast, Pegu Club lime as a teaspoonful, Whiskey Sour 1826 attributed to the Oxford Companion, Bar Basso's 1972 in negroni-sbagliato, "printed menu" in ritz.

pages.py: a Key tab line under the code, the all-drinks line rewritten, and a footer line pointing corrections at github.com/cjimti/drink/issues. The same footer line on 404.html and offline.html, and once on the Info tab under Version. The new page lines are hidden in print.

bar.json: Campari, Luxardo, Bénédictine, St-Germain, Cynar and Fernet-Branca filed solid; El Dorado, Sazerac 6, Old Forester Rye, Rittenhouse and Lucid names normalised. Brand ids and prices unchanged. app.js renders a gloss under the Alternatives tier and a new Next bottles lead line.

manifest.webmanifest: id, lang, dir, categories, and narrow and wide screenshots in assets/screens. check_assets.py check_screenshots refuses a missing file, a sizes value that does not match the PNG, or a missing form factor, with four cases in test_checks.py.

index.html: Skip to content and Skip to tabs links; app.js moves focus by hand so the hash router is not triggered, and sets tabindex only while the target holds focus. .chip is 32px tall via line-height and padding, and the bottle chip clamp is 70px. The With <bottle> chip is a span, not a button. Offline page sentence and the Info tab imperatives rewritten.

notation.json glass h carries label_built and gloss_built. app.js glassFor and llms.py serve_line use them for built drinks, so Champagne Cocktail, Death in the Afternoon and Seelbach read Highball or flute in the app, the drink pages, llms-full.txt and their three redrawn cards.

Closes #100. Closes #103. Closes #106. Closes #115. Closes #116.
@cjimti
cjimti merged commit cbd94b5 into main Sep 13, 2026
1 check passed
@cjimti
cjimti deleted the bar-copy-drink-pages-papercuts branch September 13, 2026 02:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment