Skip to content

feat(site): Print, share, credit partners and invite to stay - #14

Merged
WillieCubed merged 5 commits into
mainfrom
feat/wwd-play-partners
Sep 24, 2026
Merged

WillieCubed merged 5 commits into
mainfrom
feat/wwd-play-partners

Conversation

@WillieCubed

Copy link
Copy Markdown
Contributor

TL;DR

Anyone can now print the Digital Transit Bingo card or share a picture of it. Partner organizations
have a real Partners page, with a partner kit giving each one its own link, QR code, banners and an
embed snippet. My week also gains a "Keep going after the week" card inviting participants to stay
with LVBT.

Overview of Changes

Printing a paper bingo card

Many of the people Week Without Driving is for, including older adults who have stopped driving,
don't use a smartphone, and partner groups want paper cards for their events. The Bingo page now has
a Print section with "Include my marks", "Large print (2 pages)" and "Print a card", built from the
same square list as the on-screen card so the two never disagree. The standard layout is one
black-and-white US Letter page with every square's full text, a name line, how to play, a QR code to
lvwwd.org/bingo and the giveaway's free way to enter; the large-print layout spreads the same squares
at 18 point over exactly two pages. Ticking "Include my marks" prints a check mark and thick border
on each marked square and the progress line under the dates. The old /bingo/print address redirects
to /bingo, since the print choices depend on the marks on this phone.

Sharing a picture of the card

"Share your card" now opens a share screen instead of only sharing a link. The phone draws a 1080 by
1920 picture of the card, with a check on every marked square, an outline on every finished line, and
a count line such as "4 squares · 1 bingo". The screen offers "Share image" or "Save image" where the
browser can't share files, and "Copy image description," showing the full description and noting
that a bingo card doesn't count as a trip for the giveaway. Nothing is uploaded or stored, and the
picture never shows a name. The site's QR encoder was rebuilt to make codes of any size with the
standard's error-correction blocks, so the printed card's QR code and partner links both get level M
codes, which still scan with about 15 percent of the code damaged.

One roster for every partner

Every partner now lives in one list, apps/site/src/data/partners.ts. A volunteer adds an
organization by adding one item there and publishing the site; the Partners page, the home page's
partner wall, the partner kit and the QR code files all follow from it. The build stops with a
message naming the organization when something is wrong: a missing field, an invalid or taken slug,
a website that isn't https://, an unlisted type, or a sentence over 200 characters. A new how-to,
Add a partner organization,
walks a volunteer through it. The roster is empty today, so the page opens with "Bring your
organization" and the home page's partner wall stays hidden, as before.

The partner kit, banners and embed snippet

A partner picks its name under "Your organization" and gets its giveaway link, a QR code with PNG
and SVG downloads, four banners with "Download" and "Copy image description," a posting tip, and an
embed snippet in two sizes with a live preview. The page address becomes /partners#kit-<slug>, so a
choice can be bookmarked or sent to a colleague; "None (general materials)" gives LVBT's own link,
which credits no one. The four banners are real PNG images at fixed lvwwd.org addresses, each under
45 KB, redrawn in one command by apps/site/scripts/build-banners.mjs; LVBT's media committee can
replace any file with its own design of the same size. The embed snippet is only a link and an image,
so partner websites load no script and set no cookie; the Worker serves the banner files with headers
that let any other website show them.

Partner credit — crediting a sign-up to the ?ref= link that brought it — now works: see the roster's
sign-up count on the admin page. From 12:00 am October 9, the roster heading reads "Took part in
2026," "Bring your organization" gives way to a note about next year, and the kit shows only a
closing message.

Keep going after the week

The week lasts eight days, but what participants notice about getting around the valley matters all
year. My week's new "Keep going after the week" card sits right after "Remind me to share my trip"
and carries an invitation to LVBT's newsletter and "Become a member"; /my-week#keep-going opens the
page at it. From 12:00 am October 9, Home tells a visitor who isn't signed in that the week has
ended, replacing "Sign up to win" with "Stay involved with LVBT" and showing the same card in place
of the closing call to sign up. A signed-in visitor keeps their way back to My week.

The one-tap newsletter sign-up on the card is fully built and checked, but ships turned off: it needs
a Worker newsletter route and Beehiiv key that don't exist yet, so the card links to LVBT's own
newsletter page instead, which works today. Turning the built sign-up on will be one line in
apps/site/src/lib/newsletter.ts once the route exists.

Follow-ups

  • Give each partner a printable flyer with its own QR code; the kit links to LVBT's general flyer for now.
  • Replace the banners with the media committee's designs if it makes its own.
  • Confirm that Hotlink Protection is off for lvwwd.org in Cloudflare, or other websites can't show the banners.
  • Check printing, sharing and the screen readers on an iPhone SE and a Samsung Galaxy A15 before October 1.
  • Build the newsletter route that subscribes participants to LVBT's newsletter through Beehiiv, with its consent records.
  • Create the Beehiiv API key for lvwwd.org, then turn on the one-tap newsletter sign-up.

🤖 Generated with Claude Code

WillieCubed and others added 5 commits September 23, 2026 19:02
People who don't use a smartphone, and partners who hand out cards at
events, can now print the same card everyone plays on their phones.
The Bingo page has a Print section under "Share your card" with
"Include my marks", "Large print (2 pages)" and "Print a card".

Both paper layouts are built into the page from the square list, so
the printed text always matches the card on screen. The print styles
show only the chosen layout: a one-page, black-and-white card on US
Letter paper with every square's full text, or a two-page large-print
list with rows 3 to 5 on the second page. With "Include my marks"
ticked, marked squares print with a check mark and a thick border and
the progress line prints under the dates. Without JavaScript, the
browser's own Print still prints the blank card. The old /bingo/print
page redirects to /bingo.

The Bingo page now sends a `bingochange` event with the marks and the
progress line after loading and after every change, which is all the
Print section reads.

The card's QR code opens lvwwd.org/bingo at error correction level M.
The build-time QR encoder now splits longer codes into blocks as the
standard says and picks the mask with the lowest penalty, so partner
links can use level M too. A test decoder written apart from the
encoder reads every code back and checks its error correction.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
"Share your card" on the Bingo page, and in the "Bingo!" message, now
opens a share screen with a picture of the player's card instead of
sharing a link. The picture is 1080 by 1920 pixels, the size of a
phone story: the card with a check on every marked square, an outline
on every finished line, and a count line such as "4 squares · 1 bingo".

The share screen shows the picture, "Share image" (or "Save image"
where the browser can't share files), "Copy image description", the
written description a screen reader reads for the picture, and two
lines: the image is made on the phone, and a bingo card doesn't count
as a trip for the giveaway. Close, Escape and the phone's back gesture
close it and return focus to "Share your card".

The picture is drawn on the phone from the marks on screen, with the
site's own fonts, and nothing is uploaded or stored. The drawing lives
in bingo-picture.js and the screen in share-screen.js, so another
picture can use the same screen later. Unit tests run the shipped
script for the description and label fitting; browser tests read the
drawn pixels, the texts drawn on the canvas, and the screen's keyboard
and back-button behavior.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every partner now lives in one list, src/data/partners.ts. A volunteer
adds an organization by adding one item there and publishing the site;
the Partners page, the home page's partner wall and the QR code files
all follow. The build checks each item and stops with a message naming
the organization when a field is missing, a slug is malformed, taken
or "general", a website doesn't start with https://, a type isn't one
of the six, or a sentence runs past 200 characters.

The Partners page lists partners by name, ignoring capitals and a
leading "The", each with its name linking to its website, its type and
its sentence, in one column on a phone and two from 768 pixels. With no
partner yet, the roster is left out and the page opens with "Bring your
organization". "Copy email address" now announces "Copied" to screen
readers. From 12:00 am October 9, by the phone's clock, the roster
heading reads "Took part in 2026" and the join section gives way to a
note about next year.

For each partner, and for LVBT's general materials, the build writes
QR code files at /partners/qr/<slug>.png (1024 pixels square) and
.svg, each opening the partner's giveaway link at error correction
level M. A small PNG writer uses Node's own zlib.

The logo wall, the logo request, the sample posts and the staff email
leave the page: partners are listed by name only, and the partner kit
in the next change replaces the banner mockups. A how-to explains how
to add, change or remove a partner.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Partners page now ends with the partner kit. A partner picks its
name under "Your organization" and gets its giveaway link with "Copy
link", its QR code with PNG and SVG downloads, the four banners with
"Download" and "Copy image description", a posting tip, and an embed
snippet for its website in two sizes with a live preview. The page
address becomes /partners#kit-<slug>, so the choice can be bookmarked
or sent on, and opening that address picks it again. "None (general
materials)" gives LVBT's own link, which credits no one; with no
partner in the roster yet, it is the only choice. The flyer link sits
at the end of the kit.

The four banners are real images at lvwwd.org/partners/banners/: a
square post, a story, a website box and a website strip. Each shows
"Week Without Driving Las Vegas", "October 1 to 8, 2026" and "Sign up
to win at lvwwd.org" in the site's own fonts and colors, every text at
4.5 to 1 or more, and weighs under 45 KB. scripts/build-banners.mjs
draws them with the Chromium the tests already use, so a new design is
one command away, and LVBT's media committee can replace any file with
its own at the same address.

The embed snippet is only a link and an image, so partners' pages load
no script and set no cookie. The Worker sends the banners with
Access-Control-Allow-Origin, Cross-Origin-Resource-Policy and a day of
caching, so any site can show them. The kit shows only a closing note
from 12:00 am October 9, and asks for an email with JavaScript off.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
My week's "Keep going after the week" card is now the full card: the
invitation, LVBT's newsletter, the note that the newsletter comes from
LVBT and isn't deleted on November 30, "Ready to do more?" and "Become
a member". It sits right after "Remind me to share my trip", and
/my-week#keep-going opens the page at it.

From 12:00 am October 9, 2026, by the phone's clock, Home tells a
visitor who isn't signed in that the week has ended, swaps "Sign up to
win" for "Stay involved with LVBT", and shows the same card in place of
the closing call to sign up. The button moves focus to the section's
heading. A signed-in visitor keeps their way back to My week, and
without JavaScript Home stays as it was during the campaign.

The one-tap sign-up is built and tested but ships turned off. Joining
LVBT's newsletter from the site needs the Worker's POST /api/newsletter
and a Beehiiv key, which don't exist yet, so for now the card links to
LVBT's newsletter page, which works today. Turned on, the card shows
the participant's own address when their contact is an email ("Use a
different email" swaps in a field), asks Turnstile for a token only
when someone taps "Join the newsletter", sends the source and token,
and shows the exact message for every reply, with an offline notice on
Home. My week and Home get the Turnstile site key from the Worker, so
turning it on is a one-line change in src/lib/newsletter.ts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@WillieCubed
WillieCubed force-pushed the feat/wwd-play-partners branch from a8aed4c to 26a7f7d Compare September 24, 2026 02:08
@WillieCubed
WillieCubed merged commit 1e611e3 into main Sep 24, 2026
1 check passed
@WillieCubed
WillieCubed deleted the feat/wwd-play-partners branch September 28, 2026 03:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant