Skip to content

Give ParaSign a product page at /parasign so the signing product can be found - #325

Merged
Apolloccrypt merged 3 commits into
mainfrom
feat/parasign-page
Sep 2, 2026
Merged

Give ParaSign a product page at /parasign so the signing product can be found#325
Apolloccrypt merged 3 commits into
mainfrom
feat/parasign-page

Conversation

@Apolloccrypt

@Apolloccrypt Apolloccrypt commented Sep 2, 2026

Copy link
Copy Markdown
Owner

Why

Measured on 2026-09-01 against the live site (vault: "Bevinding - ParaSign is onvindbaar"): /parasign answered 404 and was not in sitemap.xml; of the 59 sitemap pages, zero named ParaSign or ParaSend in <title>. The only indexable page about signing was /verify, which is for someone who already holds a signature. Block B3 of the snoeiplan.

What the page says now, in the order it says it

The order is the argument:

  1. Hero. What the reader gets: a document out for signature, back signed, checkable later. No algorithm names in the title, the description, the H1 or the first paragraph. One line under it sets up the split: free on Community, business plans from €49, the person you invite needs no account.
  2. 01 / What it does. Four capabilities: PDF editor and visible seal, co-signing with routing order, non-PDF files attested by fingerprint, developer API from Pro.
  3. 02 / What it costs. Community first, then the business plans.
  4. 03 / How to begin. Three steps.
  5. 04 / How it works, and how to check it. Only here do ML-DSA-65, FIPS 204 and SHA3-256 appear, each next to the page you can go and check it on. Heading: The technique is the evidence, not the pitch. Plus the SES-not-QES scope note.

Rendered at 1280 and 390 CSS pixels with Playwright: one h1, no horizontal scroll, the string "Community" first occurs at character 396 of the body text and "ML-DSA-65" at character 4543. The technique is below the plans, not above them. The only console line is the stubbed 401 on /api/user/session/verify, the same as on every page.

Community, and the business plans

Community, €0, forever. No card, no clock, no trial that quietly ends. The card says why it is free in the words about.html already carries: Paramant is built by Mick Beer, privacy and security researcher and founder of Paramantis Solutions B.V., and the Community plan is his way of giving something back. It is not a cut-down edition: Community gets the same signatures, the same encryption and the same public proof log as Business. What a paid plan buys is volume, an API, support and accountability. Never security.

The naming leans on #328. /pricing today lists this plan as the tier named Free. PR #328 (feat/homepage-koper) is the branch that introduces the Community wording, on the homepage and the dashboard, and it does not rename the tier on frontend/pricing.html either. So both pages carry the same bridge instead of a rename: this page says in plain sight that on /pricing the plan is the tier named Free, and a test fails if that sentence ever disappears while the word Community stays. Whichever of the two PRs lands first, no visitor goes looking for a plan name that is not on the pricing page. If #328 later does rename the tier, the gate below is the thing to update.

Business plans, presented as what they are: what pays for the free one. Names and amounts lifted from /pricing:

Tier Excl. btw Charged incl. 21% btw Annual
Pro €49/mo €59.29/mo €499 excl. / €603.79 incl.
Business €299/mo €361.79/mo €2,990 excl. / €3,617.90 incl.
Enterprise Let's talk Per organisation

relay/test/pricing-page.test.js resolves each of those four variants through relay/lib/billing-catalog.js and asserts both bases appear on parasign.html, so the product page cannot drift away from the catalog or from /pricing.

Rebase onto main

git rebase origin/main, no conflicts. Main had moved on by three PRs since the review: #324 (navigation), #326 (billing stance off unless BILLING_MODE says otherwise) and #330 (directie signals script). This branch touches none of the files those changed except through the generator.

  • python3 frontend/apply-nav.py stamped the page: the seven-item nav shell (Product, Security, Pricing, Docs, plus HELP, Sign in, Create account), the slim Company/Legal footer that replaced the site-map footer, and design-system.css?v=23 / nav.css?v=19 / nav.js?v=14 / js/nav-auth.js?v=5. Net effect on parasign.html: 118 lines out, 17 in. A second run reports Updated 0 files.
  • python3 bron-seo/apply_seo_head.py re-stamped the JSON-LD after the title and description changed; --check then reports would change: 0 pages.
  • python3 bron-seo/build_sitemap.py --check said out of date, so the sitemap was regenerated with the existing generator. The whole diff is one line: the lastmod of /vault, which Navigation says what we sell: seven items, not forty #324 touched. /parasign itself is unchanged in the sitemap (0.9 priority group, next to /pricing and /sign). --check is green afterwards.

The two review findings, still fixed

  • No test-vector promise. grep -in vector frontend/parasign.html returns nothing, and grep -ci vector frontend/crypto-agility.html is 0, so the claim and the page agree. What the page says instead is that the algorithm register on /crypto-agility lists ML-DSA-65 as the loaded default, which is crypto-agility.html line 318: 0x0002 | ML-DSA-65 | cat 3 | loaded (default).
  • The docs link resolves. The page links /docs#parasign-api, and docs.html line 508 defines id="parasign-api". (/pricing still links the older /docs#parasign, which has no anchor. Not this PR's file; worth a follow-up.)

New gates in this PR

Three assertions added to relay/test/pricing-page.test.js. Deliberately in that file and not in tests/ui-truthfulness.test.mjs, because #328 is rewriting the tail of that file and two PRs appending to the same tail is a conflict for no gain:

  1. If parasign.html contains the word Community, it must also contain tier named <strong>Free</strong>, and /pricing must still carry a tier named Free. Both halves have to hold, so neither page can quietly move without the other going red.
  2. Every tier-name printed on parasign.html must be a tier /pricing sells. Today: Pro, Business, Enterprise.
  3. The founder line may claim only what /about claims (Mick Beer, privacy and security researcher, Paramantis Solutions B.V.), and naming him obliges the page to name KvK 42115132, which the stamped footer carries.

Tests, local, this worktree

node --test tests/links.test.mjs tests/seo-contract.test.mjs \
  tests/frontend-loading-contract.test.mjs tests/navigation-shell.test.mjs
                                           # pass 18, fail 0, skipped 2
node tests/ui-truthfulness.test.mjs        # ok
node relay/test/pricing-page.test.js       # 34 checks passed (was 31, +3 new gates)
scripts/check-csp-inline.sh                # OK: geen inline JS onder de CSP
scripts/check-cache-bust.sh                # OK, 335 links, single consistent ?v=
npx eslint@9 .                             # clean
python3 bron-seo/build_sitemap.py --check   # up to date
python3 bron-seo/apply_seo_head.py --check  # would change: 0 pages
python3 frontend/apply-nav.py               # second run: Updated 0 files

The two skips in links are CHECK_EXTERNAL_LINKS=1 only; that suite runs hourly against production, not in pull requests.

tests/static-sanity.sh: all ten checks pass

Checks 1 to 9 were already green. Check 10 (scripts/check-commit-style.sh) is now green too.

It was red on the earlier revision, and only for one reason: the Co-Authored-By trailer on all three commits. The decision has been taken the other way round from last time. AGENTS.md is unambiguous ("Alles in Micks naam. Geen co-author-trailer (in welke schrijfwijze dan ook), geen generated-with-regel, geen enkele AI-attributie"), the guard enforces it, and the repo rule wins. So the trailer is gone from all three commit messages, the Claude-Session line with it, and this description carries no attribution block either.

The three commits were rewritten with git filter-branch --msg-filter over origin/main..HEAD, messages only. git diff between the old head and the new one is empty: same tree, same three commits, three shorter messages.

What check 10 scans, and the result on this branch:

Rule Scanned in Result
AI attribution (Co-authored, Generated with) commit messages and added diff lines 0 hits
Em-dash, U+2014 commit messages and added diff lines 0 hits
Emoji commit messages and added diff lines 0 hits
.style-denylist terms commit messages and added diff lines skipped, no denylist file in this checkout
bash scripts/check-commit-style.sh origin/main..HEAD
OK: commit-message(s) en toegevoegde regels voldoen aan de stijlregels

bash tests/static-sanity.sh
10. Commit/GitHub style guard (scripts/check-commit-style.sh)...
   OK  last commit message + added lines are style-clean
PASS (all hard checks clear)

The guard is still local only: no workflow under .github/workflows/ runs static-sanity.sh or check-commit-style.sh, and core.hooksPath is unset in this checkout. Merged commits on main still carry the old trailer (c9cec7c #322, 0fc8648 #323); this branch does not, and this is the rule from here.

Deliberately not done

  • No deploy. Production stays on the 08-08 image.
  • No merge.
  • No rename of the tier on /pricing. That is Homepage speaks to a buyer: what it does, what it costs, why you can check it #328's call to make or not make; this page bridges to whatever /pricing says today.
  • No checkout buttons (data-billing-*) on this page. Checkout stays on /pricing.
  • No nav link to /parasign. That is the nav generator's territory.
  • /pricing's dead /docs#parasign link left alone. Different file, different PR.

Apolloccrypt added a commit that referenced this pull request Sep 2, 2026
… exists

Review of #325 found two claims on /parasign that the site does not back.
The trust block said the crypto agility page carries test vectors; it does
not, it is the algorithm register, so the sentence now says what that page
actually shows (ML-DSA-65 listed as the loaded default). The developer card
linked /docs#parasign, an anchor docs.html never had (only parasign-api),
so a visitor landed at the top of /docs.

In relay/test/pricing-page.test.js the summary line moved to the end of the
file so the count matches the ok lines (31, not 30), and the checkout
comment sits above the checkout block again instead of above the new
parasign block.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XJk2nCLCLmi3F71qkCUn7N
…be found

Measured on 2026-09-01 against the live site: /parasign answered 404 and was
not in sitemap.xml, and none of the 59 sitemap pages named ParaSign or
ParaSend in its <title>. The only indexable page about signing was /verify,
which is for someone who already holds a signature. A searcher looking for
post-quantum e-signing had no page to land on.

frontend/parasign.html says what ParaSign does, what it costs, how to start
and why to trust it. Every sentence is lifted from copy that is already on the
site and covered by a test: the feature list from index.html and sign.html
(sign-full, ui-truthfulness), the prices from pricing.html (pricing-page.test
recomputes them from billing-catalog.js), the trust claims and the SES-not-QES
scope note from about.html. Nothing new is promised.

The nav and footer are the stamped block from about.html, byte-identical to
pricing.html, so frontend/apply-nav.py picks the page up on its next run; the
generator itself is untouched. The sitemap entry comes from
bron-seo/build_sitemap.py, with /parasign in the 0.9 group next to /pricing
and /sign; the JSON-LD comes from bron-seo/apply_seo_head.py, with the page in
the SoftwareApplication set because it describes software a visitor can use.
No nginx change: the live config serves it through the generic
try_files $uri $uri.html block, the same way /about and /pricing are served.

relay/test/pricing-page.test.js now reads parasign.html as well, so the four
ParaSign prices cannot drift apart between the two pages.

Titles of other pages are left alone; that is a follow-up after the
navigation PR.
… exists

Review of #325 found two claims on /parasign that the site does not back.
The trust block said the crypto agility page carries test vectors; it does
not, it is the algorithm register, so the sentence now says what that page
actually shows (ML-DSA-65 listed as the loaded default). The developer card
linked /docs#parasign, an anchor docs.html never had (only parasign-api),
so a visitor landed at the top of /docs.

In relay/test/pricing-page.test.js the summary line moved to the end of the
file so the count matches the ok lines (31, not 30), and the checkout
comment sits above the checkout block again instead of above the new
parasign block.
Mick's two content requirements for /parasign, plus the rebase onto main.

The free plan is called Community, because that is what it is: a give-back,
not a trial and not a funnel. The card says so in the founder's own terms
(Mick Beer, privacy and security researcher at Paramantis Solutions B.V.,
the wording about.html already carries) and bridges to /pricing, where the
same plan is listed as the tier named Free. PR #328 introduces the same
Community wording on the homepage; whichever lands first, the bridge keeps
both pages honest.

The paid tiers are presented as what they are: business plans that pay for
the free one. Names and amounts are lifted from /pricing (Pro 49, Business
299, Enterprise on request, with the incl-btw checkout amounts), and
relay/test/pricing-page.test.js already ties every one of them to
relay/lib/billing-catalog.js.

The technique moved to section 04, under the heading that says it is
evidence and not a pitch. ML-DSA-65, FIPS 204 and SHA3-256 no longer appear
in the title, the description, the H1 area or the opening paragraph; first
occurrence in the rendered page is now at character 4633 of 1280px body
text, well past the plans. The hero says what the reader gets, the proof
section says how to check it.

Three new gates in relay/test/pricing-page.test.js, deliberately in that
file rather than in ui-truthfulness.test.mjs, which #328 is rewriting:
- saying Community obliges the page to name the /pricing tier it maps to,
  and obliges /pricing to still carry a tier named Free
- every tier name printed on /parasign must be a tier /pricing sells
- the founder line may claim only what /about claims, and naming him
  obliges the page to name the company registration

Rebased onto main (#324 navigation, #326 billing stance, #330 signals),
no conflicts. frontend/apply-nav.py stamped the seven-item nav shell, the
Company/Legal footer and the design-system versions onto the page; a second
run produces no diff. bron-seo/apply_seo_head.py re-stamped the JSON-LD for
the new title and description. bron-seo/build_sitemap.py said the sitemap
was out of date and regenerated it: one line, the lastmod of /vault, which
#324 touched.
Apolloccrypt added a commit that referenced this pull request Sep 2, 2026
… exists

Review of #325 found two claims on /parasign that the site does not back.
The trust block said the crypto agility page carries test vectors; it does
not, it is the algorithm register, so the sentence now says what that page
actually shows (ML-DSA-65 listed as the loaded default). The developer card
linked /docs#parasign, an anchor docs.html never had (only parasign-api),
so a visitor landed at the top of /docs.

In relay/test/pricing-page.test.js the summary line moved to the end of the
file so the count matches the ok lines (31, not 30), and the checkout
comment sits above the checkout block again instead of above the new
parasign block.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XJk2nCLCLmi3F71qkCUn7N
@Apolloccrypt
Apolloccrypt force-pushed the feat/parasign-page branch 2 times, most recently from 9122852 to cb33485 Compare September 2, 2026 14:25
@Apolloccrypt
Apolloccrypt merged commit f8bd1d2 into main Sep 2, 2026
12 checks passed
Apolloccrypt added a commit that referenced this pull request Sep 2, 2026
…xists

Rebased onto a main that gained the /parasign page (#325). Two things followed.

That page calls the free plan Community and then carried a bridge sentence, 'on
the pricing page this plan is the tier named Free', with a gate in
relay/test/pricing-page.test.js requiring it. The bridge existed only because
/pricing disagreed with every other page. This branch renames the tier instead,
so the sentence is gone and the gate now checks what actually has to hold:
/pricing carries a tier named Community, carries no tier named Free, and
/parasign does not explain the name away. A visitor who reads Community and
goes looking for it on the pricing page finds it.

The ui-truthfulness gate covers /parasign as well now, so all four pages that
mention the plan are held to one name.

/pricing linked to /docs#parasign, which is not an anchor on that page. The id
is parasign-api. Swept every /docs# link on the site afterwards; that was the
only broken one.

Relay suite compared name by name against a stashed origin/main baseline: no
new failures.
Apolloccrypt added a commit that referenced this pull request Sep 2, 2026
…does

Review of #334 found the head elements were consistent but not honest, and
not pinned. Eleven points, all inside <head>.

Who is behind it, visible to people
The founder and the legal entity were in the JSON-LD only, which no preview
in WhatsApp, LinkedIn or iMessage renders. The meta description, og:description
and twitter:description of /index and /about now carry the same sentence the
footer and /about already print: a product of Paramantis Solutions B.V. in
Harderwijk, founded by Mick Beer, privacy and security researcher.

Preview text a buyer can read
Algorithm names and internal words are out of the sentence a search result
shows. /verify no longer opens with ML-DSA-65 (FIPS 204) but with what the
page does. The same for /sign, /index, /vault, /download, /pricing, /trust,
/audit-log-export, /status, /sla and /co-sign. The word "relay" is ours, not
the reader's, so it is out of every title and out of every first sentence
except on the four pages whose subject is the architecture itself. The names
stay on the pages, where there is room to explain them.

A title the page keeps
"Sign and send without a US server" was the clearest sentence on the site and
appeared nowhere on the page, and it promoted a claim /security contradicts:
Cloudflare is on the third-party list there. The title is now "Sign and send
documents under EU law", which is what rule 04 on the homepage says and what
/security backs.

Prices in the pricing description
/pricing promised "organisations pay for higher limits" and named no amount.
It now names ParaSend Pro at 15 euro a month and ParaSign Pro at 49, excl.
VAT, the figures on the page. The first sentence is the free plan, which is
the point of the plan structure. The first screen of the page itself is body
work and out of scope here.

Product names after the verb
/index and /pricing opened with ParaSign and ParaSend as if the reader knew
them. Both now open with the action.

Three gates, because consistency is not truth
The gate added earlier pins title, og:title and twitter:title to each other,
which the sentence "Paramant is ISO 27001 certified and free forever" passed
on all three. Added:
- the sentences of /index, /pricing and /about are pinned word for word
- no title or description may claim a certification, an accreditation, a
  qualified signature or a 100% guarantee, none of which the site backs
- the title and the first sentence of the description stay free of ML-DSA,
  ML-KEM, FIPS, .prmnt, AES-n, envelope, open-core and relay, except on
  /architecture, /crypto-agility, /ct-log and the OT brief

Loose ends from the review
- the test comment no longer cites docs/brand/messaging.md, which is still an
  open PR and not in the repo
- /parashare is private in both PRIVATE sets, so its head is back to what main
  has: a gated page should not carry an ungated head change
- admin, account and iot carried "PARAMANT" and an em-dash in og and twitter
  tags; they are private, but the claim that both are gone from every head is
  now true
- merged origin/main, so /parasign from #325 is covered by the new gates

Green: seo-contract (14), links, ui-truthfulness, site-claims, navigation-shell,
frontend-loading-contract, frontend-module-scripts, pricing-page, the full root
integration set (123), check-csp-inline, check-cache-bust, eslint.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XJk2nCLCLmi3F71qkCUn7N
Apolloccrypt added a commit that referenced this pull request Sep 2, 2026
Review of #339 read both product pages as a buyer and found the same defect
twice: the first paragraph explains the mechanism to someone who already knows
what it is. "ML-DSA-65", "transparency log", "ciphertext", "RAM" and above all
"the relay" appear before the page has said what the reader gets. The relay is
our word for our own server and it is not defined anywhere on either page.

So both ledes now say what happens in words a reader already has, and the
mechanism keeps its place under "06 / The proof", where the /about sentences
ui-truthfulness pins are still quoted verbatim.

  /parasign  ParaSign signs your PDF on your own computer. The document and
             your signing key never leave your browser. Whoever opens the file
             later can check for themselves that nothing in it was changed,
             without asking us and without an account.
  /parasend  Your file is scrambled on your own device before anything is sent.
             We never write it to disk, and once the person you sent it to has
             downloaded it, it is gone. Servers in Germany, under EU law.

Order. Section 01 ran the full tier tables, so on a 390px screen the reader
scrolled roughly 1,850px of prices, "Business 299 euro/month" among them, before
a word about what the product does. The split stays at 01 because it is the
thing that has to be clear first, but only as the two paragraphs /pricing
already carries plus a link. The tables moved to 05, after "what it does" and
"how to begin". Measured at 390x844: tiers now start at 4,449px on /parasign and
4,315px on /parasend instead of 725px and 720px.

eIDAS, on the first screen. The h1 promises "prove it years later" and the
scope note sat at 6,386px of a 7,922px page, screen 8 of 9, while for a law or
advisory firm it is the first question. A line under the buttons now says it is
an ordinary electronic signature (SES) and not a qualified eIDAS signature, and
links to the full note. The note itself is unchanged and still pinned.

Who it is for, on the first screen: an audience line under each lede, at 487px
and 392px. And the section label a reader meets first is no longer
"post-quantum e-signing" but "document signing with proof that lasts".

Three claims that read as more than they are:

- SLA 99.9% on /parasend contradicted the published 99.95% on /pricing and
  /sla. This is the drift the PR exists to prevent, and nothing pinned it, so
  pricing-page.test.js now reads the Enterprise target out of sla.html and
  fails any page that states a different SLA figure. It reads the Enterprise
  cell by name because /sla also publishes 99.5% for Community.
- "IEC 62443 / NIS2 / NEN 7510 documentation" stood on screen 3 while the "no
  third-party certification" limit was 4,000px lower. The limit is in the
  bullet now, and pinned there.
- "Post-quantum, zero-knowledge" opened the honest paragraph on /parasign with
  a term nothing on the page supports. Replaced by what actually happens: we
  never see your document.

ParaShare was a third product name with no explanation, in a tier bullet and in
step 2. It is named as what it is, the send screen of ParaSend, in both places
and in the ParaShare card under "what it does".

Tier cards now carry the names /pricing sells (Free, Pro, Business,
Enterprise) instead of product-prefixed variants, which is what the tier-name
check from #325 asks for, and the Community wording gets its bridge sentence to
the tier /pricing calls Free.

/sign: "the private key never reaches the relay" is now "never reaches our
servers". The rest of that page was read as fine.

Rebased onto main, which now carries #325's own /parasign. Conflicts in
bron-seo/apply_seo_head.py, bron-seo/build_sitemap.py, frontend/sitemap.xml,
relay/test/pricing-page.test.js and frontend/parasign.html resolved by taking
this branch's page and keeping every assertion #325 added, including the ones
that then failed against it.

Green locally: seo-contract (9), ui-truthfulness, links, frontend-loading-
contract (7), navigation-shell (24), pricing-page (44), check-csp-inline.sh,
check-cache-bust.sh, eslint (exit 0). No horizontal overflow at 390px on any of
the three pages. index.html, apply-nav.py and js/nav-auth.js untouched.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XJk2nCLCLmi3F71qkCUn7N
Apolloccrypt added a commit that referenced this pull request Sep 2, 2026
main moved while this branch was open. Rebased onto 99909a1 and folded what
arrived into the CHANGELOG section, because a release section that is a
snapshot of the moment it was written is the exact failure this PR is fixing.

New in the section: the ParaSign product page at /parasign (#325), the
messaging guide (#331), the homepage rewrite for a buyer (#328), the site
claims pinned to the code that makes them true (#327), the heartbeat that
cannot be green without evidence (#338), and the route suites that boot a real
relay.js (#341). Count in the intro goes from 268 commits and 52 PRs to 277 and
58, and the intro now says it was rebased rather than pretending it was written
in one pass.

#341 is worth naming for what it is: point 3 of the toekomstbestendigheid
report was that relay.js, 6488 lines and 68 routes, was loaded by no unit test
at all. It is now loaded by the route suites. That point is not closed, but it
is no longer zero.

Two conflicts, both resolved toward main's newer structure:

- product-heartbeat.yml: #338 moved the live job out into heartbeat.yml. Took
  main's file whole and applied the Node 24 bump to both files instead, so the
  bump follows the job rather than the filename. All seven node-version entries
  across the five workflows now read '24'.
- test.yml: #341 added a second silent-suites gate for the route job and set
  both expected sets to empty. Kept main's exclusion lists and applied
  --test-reporter=tap to both steps.

That second one matters more after the rebase than before. With a non-empty
expected list, the spec reporter made the gate fail, which is how it was found.
With an empty expected list, the spec reporter makes it PASS: the grep finds
nothing, silent is empty, and a gate that can no longer see anything reports
green. A dead gate that reports green is precisely what these two gates exist
to prevent, so both now pin the reporter rather than inherit a Node default.

Tests after the rebase, on Node 22 and again under node:24-alpine: relay 175,
admin 40, root 145 (143 pass, 2 pre-existing skips), both silent-suite gates
empty as expected. static-sanity PASS including the style guard, bash -n and
eslint clean. The root job now runs npm ci first, per #338; tests/README.md and
the local commands in docs/RELEASE.md match what CI does.
Apolloccrypt added a commit that referenced this pull request Sep 2, 2026
…araSign

Three pages, one shape, taken from docs/brand/messaging.md: what you can do
here, who it is for, the split with its real number, who is behind it, then the
proof and the honest limits. The algorithm names moved to the bottom of every
page, where they are the reason a plain sentence above is true.

/parasend is new. ParaSign has had a page since #325; ParaSend had nothing, so
the send half of the product could not be found by name. It follows the
/parasign pattern the guide asks for.

What changed against the review, per page.

/parasign
- H1 is the one the guide specifies: "Sign documents in your browser, prove it
  years later." The old H1 was the product name, which does not say what the
  page is for.
- The opening paragraph says what a buyer gets, in two sentences and 160
  characters, and no longer opens on ML-DSA-65 and a transparency log. The
  guide's own tone rule keeps cryptography below the fold; the sentence it
  specifies for this page contradicted that rule, so the sentence now sits
  verbatim in the proof block at 04 instead of in the hero.
- The buyer is named in the first screen: legal, finance and healthcare
  practices in the EU, the same audience index.html states.
- The eIDAS status moved from 6,386px to 737px. A lawyer asks it first; the
  page now answers it before the tiers instead of on screen 8 of 9.
- The free promise carries its number. "Free forever" became "Free on the
  Community plan: 2 signatures a month, no card, forever."
- "Zero-knowledge" is gone from the scope note. It described nothing this page
  can point at, and it sat next to the most honest paragraph on the page.
- The proof block quotes /about word for word and carries the EU claim in the
  form #328 settled: no US provider in the data path, with Resend named in the
  same breath.

/parasend
- Section 02, the section that has to convince, said AES-256-GCM, ciphertext,
  RAM, ML-KEM-768, tenant and RAM budget. It now says what the buyer gets. The
  algorithm names are in 06, each next to the page that checks it.
- The free promise carries its limits: links that last an hour, gone after one
  read, 10 uploads an hour.
- The bridge sentence explaining that Community is listed as Free is gone, and
  the tier card is named Community. #328 renamed the tier on /pricing, so there
  is nothing left to explain away.
- The founder block quotes /about instead of composing a sentence about US
  subscriptions. #332 put that sentence on /about, so it is now sourced.

/sign
- "Private key" was the last jargon in the first screenful. Same fact, words a
  practice manager already uses.

One layout fix, page-local. At 390px the house .sec-head keeps the section
number in its own grid column, which left the H1 about 160px to wrap in: six
lines of headline on /parasign, and the buttons and the eIDAS note off the
first screen. On a narrow screen the number now stacks above the headline.
design-system.css is untouched, because it is shared with pages this PR does
not open.

Measured at 390px with Playwright, per page: no horizontal overflow anywhere
(scrollWidth 390), and on /parasign the H1, the audience, both buttons, the
free promise and the eIDAS note all land inside the first 844px.
Apolloccrypt added a commit that referenced this pull request Sep 2, 2026
…araSign

Three pages, one shape, taken from docs/brand/messaging.md: what you can do
here, who it is for, the split with its real number, who is behind it, then the
proof and the honest limits. The algorithm names moved to the bottom of every
page, where they are the reason a plain sentence above is true.

/parasend is new. ParaSign has had a page since #325; ParaSend had nothing, so
the send half of the product could not be found by name. It follows the
/parasign pattern the guide asks for.

What changed against the review, per page.

/parasign
- H1 is the one the guide specifies: "Sign documents in your browser, prove it
  years later." The old H1 was the product name, which does not say what the
  page is for.
- The opening paragraph says what a buyer gets, in two sentences and 160
  characters, and no longer opens on ML-DSA-65 and a transparency log. The
  guide's own tone rule keeps cryptography below the fold; the sentence it
  specifies for this page contradicted that rule, so the sentence now sits
  verbatim in the proof block at 04 instead of in the hero.
- The buyer is named in the first screen: legal, finance and healthcare
  practices in the EU, the same audience index.html states.
- The eIDAS status moved from 6,386px to 737px. A lawyer asks it first; the
  page now answers it before the tiers instead of on screen 8 of 9.
- The free promise carries its number. "Free forever" became "Free on the
  Community plan: 2 signatures a month, no card, forever."
- "Zero-knowledge" is gone from the scope note. It described nothing this page
  can point at, and it sat next to the most honest paragraph on the page.
- The proof block quotes /about word for word and carries the EU claim in the
  form #328 settled: no US provider in the data path, with Resend named in the
  same breath.

/parasend
- Section 02, the section that has to convince, said AES-256-GCM, ciphertext,
  RAM, ML-KEM-768, tenant and RAM budget. It now says what the buyer gets. The
  algorithm names are in 06, each next to the page that checks it.
- The free promise carries its limits: links that last an hour, gone after one
  read, 10 uploads an hour.
- The bridge sentence explaining that Community is listed as Free is gone, and
  the tier card is named Community. #328 renamed the tier on /pricing, so there
  is nothing left to explain away.
- The founder block quotes /about instead of composing a sentence about US
  subscriptions. #332 put that sentence on /about, so it is now sourced.

/sign
- "Private key" was the last jargon in the first screenful. Same fact, words a
  practice manager already uses.

One layout fix, page-local. At 390px the house .sec-head keeps the section
number in its own grid column, which left the H1 about 160px to wrap in: six
lines of headline on /parasign, and the buttons and the eIDAS note off the
first screen. On a narrow screen the number now stacks above the headline.
design-system.css is untouched, because it is shared with pages this PR does
not open.

Measured at 390px with Playwright, per page: no horizontal overflow anywhere
(scrollWidth 390), and on /parasign the H1, the audience, both buttons, the
free promise and the eIDAS note all land inside the first 844px.
Apolloccrypt added a commit that referenced this pull request Sep 2, 2026
…araSign

Three pages, one shape, taken from docs/brand/messaging.md: what you can do
here, who it is for, the split with its real number, who is behind it, then the
proof and the honest limits. The algorithm names moved to the bottom of every
page, where they are the reason a plain sentence above is true.

/parasend is new. ParaSign has had a page since #325; ParaSend had nothing, so
the send half of the product could not be found by name. It follows the
/parasign pattern the guide asks for.

What changed against the review, per page.

/parasign
- H1 is the one the guide specifies: "Sign documents in your browser, prove it
  years later." The old H1 was the product name, which does not say what the
  page is for.
- The opening paragraph says what a buyer gets, in two sentences and 160
  characters, and no longer opens on ML-DSA-65 and a transparency log. The
  guide's own tone rule keeps cryptography below the fold; the sentence it
  specifies for this page contradicted that rule, so the sentence now sits
  verbatim in the proof block at 04 instead of in the hero.
- The buyer is named in the first screen: legal, finance and healthcare
  practices in the EU, the same audience index.html states.
- The eIDAS status moved from 6,386px to 737px. A lawyer asks it first; the
  page now answers it before the tiers instead of on screen 8 of 9.
- The free promise carries its number. "Free forever" became "Free on the
  Community plan: 2 signatures a month, no card, forever."
- "Zero-knowledge" is gone from the scope note. It described nothing this page
  can point at, and it sat next to the most honest paragraph on the page.
- The proof block quotes /about word for word and carries the EU claim in the
  form #328 settled: no US provider in the data path, with Resend named in the
  same breath.

/parasend
- Section 02, the section that has to convince, said AES-256-GCM, ciphertext,
  RAM, ML-KEM-768, tenant and RAM budget. It now says what the buyer gets. The
  algorithm names are in 06, each next to the page that checks it.
- The free promise carries its limits: links that last an hour, gone after one
  read, 10 uploads an hour.
- The bridge sentence explaining that Community is listed as Free is gone, and
  the tier card is named Community. #328 renamed the tier on /pricing, so there
  is nothing left to explain away.
- The founder block quotes /about instead of composing a sentence about US
  subscriptions. #332 put that sentence on /about, so it is now sourced.

/sign
- "Private key" was the last jargon in the first screenful. Same fact, words a
  practice manager already uses.

One layout fix, page-local. At 390px the house .sec-head keeps the section
number in its own grid column, which left the H1 about 160px to wrap in: six
lines of headline on /parasign, and the buttons and the eIDAS note off the
first screen. On a narrow screen the number now stacks above the headline.
design-system.css is untouched, because it is shared with pages this PR does
not open.

Measured at 390px with Playwright, per page: no horizontal overflow anywhere
(scrollWidth 390), and on /parasign the H1, the audience, both buttons, the
free promise and the eIDAS note all land inside the first 844px.
@Apolloccrypt
Apolloccrypt deleted the feat/parasign-page branch September 5, 2026 18:56
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