Skip to content

site: apps question, supporter share card and an app lookup page - #467

Draft
tnunamak wants to merge 47 commits into
mainfrom
site/supporter-apps-question
Draft

tnunamak wants to merge 47 commits into
mainfrom
site/supporter-apps-question

Conversation

@tnunamak

@tnunamak tnunamak commented Nov 6, 2026 •

Copy link
Copy Markdown
Contributor

Merging this fixes a signing-form bug that is live now (see "Fix" below). Everything in it goes live with the deploy; there are no flags to set.

What it adds to pdpp.dev:

  1. An apps question on the signing form. Supporters can name apps they would like to see join PDPP.
  2. A share card after signing.
  3. An "Is your app on PDPP?" page at /apps.

Apps question

The form gets an optional question, "Which apps would you like to see join PDPP?", with room for up to ten names. The answers are stored with the signature in the private register and are never published. We use them as counts: apps/site/scripts/count-requested-apps.mjs prints how many supporters named each app, so we can tell a company how many supporters asked for it without saying who. People can type anything, so the script prints only names from a reviewed list and counts everything else as unreviewed. docs/registers.md explains how to run it.

Blocked on Art: privacy text. The privacy page is unchanged in this PR. It needs Art-approved text before merge, because the form now collects the apps people name and may share per-company counts. The page also has two existing errors: it says we store the role of the person signing for an organisation (we don't), and it leaves out the affiliation an individual can give (we store it).

A signature that is waiting for email confirmation during the deploy still confirms normally, with an empty list of apps.

Share card

After a supporter confirms, the page offers a card to post: the supplied copy ("My data, my rules." and the pledge line) with the PDPP wordmark, in a feed size (1080x1350) and a Stories size (1080x1920). Buttons let the supporter download it, copy it, post to X or LinkedIn, or use the phone's share sheet. Every supporter gets the same image, so it carries no personal data. The card uses the site's own fonts, Inter and Source Serif 4. The build downloads them from Google Fonts, which the site already does for its pages, so no font files are added to the repo.

Also, after someone submits or confirms, the page no longer shows a blank signing form under the message, which read as an invitation to sign again.

Is your app on PDPP?

A visitor searches for an app and sees whether PDPP has an open-source connector for it and what data that connector brings, and whether the company has signed the Principles or registered an implementation. Many connectors are community-built and say nothing about the company, so the page names a company as a signer or registrant only when one of those registers lists it.

The connector list comes from the published connector catalogue and refreshes hourly. If that fetch fails, the page uses a copy kept in the repo. The page is linked from a new Participate menu in the top navigation, from the Participate page and from the footer, and is listed in the sitemap. This also fixes the top-navigation dropdowns, which did not open on hover because of a wrong Tailwind class.

Fix: the updates checkbox

The live signing form rejects every signature that leaves "Email me about new versions" unticked, and shows "We could not accept that submission". The box is meant to be optional. The schema now accepts it unticked, and a new test covers this for individuals and organisations. The boxes that are required (the Principles, the register, and age or authority) are now marked required, so the browser points at a missed one instead of the server returning the same vague error.

Testing

The site's tests, lint and production build pass. The tests check that the apps answers never reach the public register, that the count script never prints what people typed, that the card images have the right sizes, and that /apps falls back to the saved copy when the live fetch fails. I also used the share card and /apps on a preview deployment.

A signature on this PR's preview deployment, with two app names and the updates box unticked, went through email confirmation, and the stored record has both names in requestedApps and updates: false.

Not yet tested: "Copy image" and "Share…" on a phone.

Assisted-by: AI

Adds an optional question to the Principles signing form: up to three
app names. The names are stored in the private signatory record as
requestedApps and never published. A new script prints per-app counts
only, so the team can tell a company how many supporters named it.

Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
The privacy page and docs/registers.md said the register stores an
organisation signatory's role. buildRecord always writes signatoryRole:
null. For an individual it stores the optional affiliation, in the
organisation field. Describe what is stored.

Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
The count script printed any free-text spelling verbatim, so an answer
such as an email address or a full name could reach output that
docs/registers.md tells maintainers to share. By default it now prints
only canonical names (the suggestion list and alias targets) and a count
of unreviewed answers. --review lists the raw unreviewed values on
stderr, marked private, so a maintainer can extend the alias map.

Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
A record persisted by the previous deployment has no requestedApps
field. If its pending entry was not deleted, a retry after deploy builds
requestedApps: [] and the equality check rejected an identical record.
Read a missing requestedApps as [] on both sides, in one key order.

Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
The suggestion list was a design choice, not part of the request, and no
source lists every app with confidence. The count script keeps the reviewed
names it may print.

Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
Start with one box and add more on demand, with one shared limit for the
form, the schema and the retry cookie.

Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
After a confirmed signature, /principles can show a share panel with a
1080x1350 feed card and a 1080x1920 Stories card. Both are the same image
for every supporter and carry no personal data. They are built at build
time with next/og from fonts kept in the repo and the brand mark file.

NEXT_PUBLIC_PDPP_SHARE_CARD=1 turns on the panel and the
/principles/card/{feed,story} routes. With any other value the panel is
not rendered and the routes return 404. Production stays off until the
mark use is cleared with LF Decentralized Trust.

Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
Replace the vendored font files with unmodified copies from the Inter 4.1
and Source Serif 4.005 releases, add both upstream licence files, and
annotate them as OFL-1.1 in REUSE.toml.

Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
The flag is on only for "true", matching siteFlags.

Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
The card now uses the concept surface: the header wordmark path in the
primary colour, flat paper background, ink and ink-soft text, square
corners and 1px border-colour rules, Source Serif 4 and Inter. The old
copper and blue mark, cream gradients and oklch rewriting are gone.

Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
The card image links nowhere, so a post made from it carried no link, and on
desktop Share only copied the page link.

The panel now shows the caption with a Copy caption button, and offers
Download image, Download for Stories, Copy image, Post on X, Post on LinkedIn
and, only where the browser can share files, Share. Post on X opens a prefilled
post and downloads the card to attach. LinkedIn takes no text, so its button
downloads the card and copies the caption. The old link-only fallback is gone.

Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
…oo:'

Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
The panel no longer draws its own box, the card has no divider rules, and
the call to action is plain text: a picture cannot be tapped, so it should
not look like a button. The caption carries the real link.

Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
A visitor types an app name and sees what they can do with its data through
PDPP today, then whether the company has signed the Principles or registered.
It is a read-only view over lists PDPP already publishes: the signed connector
catalogue, the Supporters register and the conformance register. Nothing is
collected or sent.

The catalogue is committed as a snapshot, refreshed by
scripts/sync-connector-catalog.mjs. The snapshot is pinned to the manifest and
layer digests; the script does not check the catalogue's cosign signature.

The page returns not found unless NEXT_PUBLIC_PDPP_APP_DIRECTORY=true. No nav
links are added.

Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
…-source

Catalogue keys are hyphenated but most source folders use underscores, so 22
connectors had no labels. Most connectors were written by maintainers, so
'open-source connector' is the accurate description.

Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
An app such as Apple Health is a product, not the company that signs, so the
status line says 'The company' unless a register names it. A signed company
 with no connector leads with its signature. The count says connectors.

Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
Every row repeated the same sentence. Rows now show the app and the data it
brings; the page says once that companies have not signed unless a row says
so. Supported, the normal tier, carries no label.

Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
The link is pinned to the commit the catalogue was built from, so it shows
the code the listing describes. The search example is picked after
hydration so static HTML and the first render agree.

Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
The flag accepts only "true" since it was aligned with the other site flags; three test names still said 1.

Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
@vercel

vercel Bot commented Nov 6, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
pdpp Ready Ready Preview Nov 7, 2026 1:35pm UTC

Request Review

Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
@tnunamak tnunamak changed the title site: ask supporters which apps they want to see join PDPP site: ask supporters which apps they want, add a share card and an app lookup page Nov 6, 2026
@tnunamak tnunamak changed the title site: ask supporters which apps they want, add a share card and an app lookup page site: apps question, supporter share card and an app lookup page Nov 6, 2026
Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
The card sets the serif in regular and italic only; the bold file was never loaded.

Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
The page only reads lists PDPP already publishes, so it ships with the rest of the site. It is linked from the Participate menu, the Participate page and the footer, and is now in the sitemap.

Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
The card uses the site's own typefaces, Inter and Source Serif 4. It now asks Google Fonts for their TrueType files when it is built, the same source next/font already uses for the site, instead of keeping copies and their licences in the repo. Each request is tried three times; if Google Fonts stays unreachable the build fails, as it already does for next/font. Tests stub the download and serve the font next/og ships with.

Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
The share panel reads whether the browser can share images with useSyncExternalStore, which React provides for browser-only values, instead of setting state in an effect. The catalogue loader collects a connector's data labels in a Set instead of searching an array for each one.

Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
The signing form rejected every submission that left "Email me about new versions" unticked. An unticked checkbox is left out of the form data, and in zod 4 a union that includes z.undefined() still requires the key, so the schema failed and the form showed "We could not accept that submission". The existing tests always ticked the box. The schema now marks the field optional, and a new test covers both boxes for individuals and organisations.

Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
…rking directory

The server rejects a signature without the Principles, register and age (or authority) boxes, but the form did not mark them required, so a missed box came back only as "We could not accept that submission". The boxes now carry the required attribute, so the browser points at the one that is missing before the form is sent.

The app directory test read the saved connector list relative to the working directory. CI runs the site tests from the repository root, so the file was not found. The two readers now take the site root as an optional argument, and the test passes it.

Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
The form did not show which fields and boxes were required, so a missed box came back only as a generic error. Each required field and consent box now has an asterisk, and a line above the fields says what it means. The asterisk is hidden from screen readers, which already announce required inputs. The rules are unchanged.

Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
The card now shows after every confirmed signature and its two images are built with the site, so it goes live with the deploy like /apps. NEXT_PUBLIC_PDPP_SHARE_CARD and the tests that switched it are removed.

Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>
The privacy page is legal text and needs Art's sign-off. Restore it
to main. The apps question needs matching privacy text before this
can merge.

Assisted-by: AI
Signed-off-by: Tim Nunamaker <tnunamak@gmail.com>

This branch was successfully deployed

1 active deployment
Preview — 64cd54e0 Deployed Nov 7, 2026 by vercel[bot]
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