Skip to content

docs(landing): claim-integrity pass — truthful wording for parity, providers, Node version, privacy and README - #418

Open
BSalaeddin wants to merge 1 commit into
devfrom
seo/claim-integrity
Open

docs(landing): claim-integrity pass — truthful wording for parity, providers, Node version, privacy and README#418
BSalaeddin wants to merge 1 commit into
devfrom
seo/claim-integrity

Conversation

@BSalaeddin

Copy link
Copy Markdown
Collaborator

Text-only claim-integrity pass over the public copy: the landing site, the docs
pages that state versions or compare upup to other uploaders, and the npm-facing
README. Every row below came from the audit in
upup-artifact/seo-2026-09-11/claim-inventory.md with verdict FALSE,
UNSUPPORTED or STALE, and every figure was re-fetched today (2026-09-12)
before the wording was changed. No dependency, layout or markup changes — only
the words, plus one new vitest guard.

What was wrong, and what it says now

file:line before after evidence
apps/landing/src/lib/faqs.ts:12 (also emitted as FAQPage JSON-LD) "Every framework renders byte-identical DOM, verified by a cross-framework parity test suite" "Every framework renders the same DOM structure, classes, and accessibility tree, verified by a cross-framework parity test suite" apps/e2e-test/cross-framework/parity-dom.ts:24-26 compares a normalized tree — "only the shared design-system contract (structure, stable data-testid / data-upup-slot hooks, a11y attrs, and upup--prefixed class tokens). Everything framework-injected is stripped" — and it unwraps Angular host elements (L32-37) and treats <svg> as a leaf (L38). It cannot prove byte equality.
apps/landing/src/components/FeatureShowcase/index.tsx:49 "one uploader that renders byte-identical DOM in every framework" "one uploader that renders the same DOM structure, classes, and accessibility tree in every framework" same
README.md:10 "native, byte-identical UI packages" "native, DOM-identical UI packages" same
README.md:34 "render the same DOM with the same props, verified byte-for-byte by a cross-framework parity harness" "…verified by a cross-framework parity harness (structure, classes, accessibility attributes, text)" same
README.md:41 "the component API and rendered DOM are identical" "the component API and the rendered DOM contract are identical" same — Angular host elements are unwrapped before comparison
README.md:115 "same DOM, same Tailwind classes, enforced byte-for-byte by a parity harness" "same DOM structure, same upup- classes, enforced by a cross-framework parity harness" same
apps/landing/src/components/HomepageFeatures/index.tsx:930 "We also support some non-S3 connections." "We also support Azure Blob Storage in client mode." packages/core/src/types/storage-provider.tsNON_S3_STORAGE_PROVIDERS contains exactly one member, Azure; packages/server/src/storage.ts:20 throws for it, which is why the qualifier is "client mode". The provider chip 60 lines above already says "client mode only".
apps/landing/src/app/privacy/page.tsx:39 "personal data such as your name and email address when you sign up or contact us" "…when you contact us, submit the support form, or request a provider integration" useupup.com has no account system: apps/landing/src/app/ contains only api/, docs/, docs-llms/, docs-md/, mobile-demo/, privacy/, support/. The three named paths are the ones that actually post personal data (api/upup-support/route.ts, reached from the support form and from the HomepageFeatures provider-interest modal).
apps/landing/src/app/privacy/page.tsx:19 "Last updated April 25th, 2025" "Last updated September 12th, 2026" The page has no April-2025 history at all (first committed 2025-11-06, 8813b1f4; last touched 2026-08-06, fc969f4b, layout only). The date is moved to today because this PR changes the policy's wording — had the text been left alone the badge would have been dropped instead of forward-dated.
apps/landing/content/docs/guides/server-auth.mdx:131 "so it works on Node 18+, edge runtimes, and Cloudflare Workers" "so it works on Node 20+, edge runtimes, and Cloudflare Workers" packages/server/package.json engines.node is ">=20"; .nvmrc is 20.20.2. Node 18 was never a supported target.
apps/landing/content/docs/guides/reliability.mdx:301 "nothing reads it in v3.1.0" "nothing reads it as of v3.3" Still unread: fastAbortThreshold is only declared (packages/core/src/options/types.ts:70) and forwarded (resolve-upload-config.ts:100-101, upload-manager.ts:27) — no consumer. The label is relabelled to the minor line so it stays true across 3.3.x instead of rotting again.
apps/landing/content/docs/comparisons/upup-vs-filepond.mdx:27 FilePond i18n: "Configurable label strings (no locale bundles)" "48 locale files in locale/, plus configurable label strings" GET api.github.com/repos/pqina/filepond/contents/locale → 48 files (am-et.jszh-tw.js), re-counted 2026-09-12. This was the only outright false cell about a competitor.
apps/landing/content/docs/comparisons/upup-vs-uploadthing.mdx:28 Resumable uploads: "Not a primary feature" "Yes — createUpload (start, pause, resume), since v7" docs.uploadthing.com/api-reference/client, fetched 2026-09-12: "createUploadSince 7.0 … Create a resumable upload. Resumable uploads allows you to start an upload, pause it, and then resume it at a later time." docs.uploadthing.com/uploading-files adds the raw-HTTP form ("include the Range header … x-ut-range-start").
apps/landing/content/docs/comparisons/upup-vs-uploadthing.mdx:25-27 Cloud-drive sources / camera+screen capture / image editor: "No" "Not built in" These were flagged UNSUPPORTED-by-absence: nothing in UploadThing's README or docs home offers them, but a bare "No" asserts more than an absence sweep can prove. "Not built in" is what the evidence supports.
README.md:15 <!-- npm badges: add after first @useupup publish --> (comment removed) The scope has been published since 2026-09-02; the TODO is stale. No badge was added — that would be a markup change, out of scope for this pass.
README.md:125-129 "## Battle-tested in production" + uNotes / Shorty, implying they run the current packages "## Used in production" + "Both apps below run the upup v3.1 engine under its previous @upupjs/* scope — the same codebase, published before the rename to @useupup/*." Verified today, and this corrected the audit itself: both apps pin @upupjs/core + @upupjs/next 3.1.0uNotes15/package.json:127-128 and shortyapi/package.json:101-102 (committed acdcc071, 2026-08-07). The inventory said Shorty was still on v1 upup-react-file-uploader@^1.5.2; that is no longer true, there is no upup-react-file-uploader reference left in that repo. Neither app runs @useupup/* 3.3.

New guard

apps/landing/src/__tests__/claim-integrity.test.ts (4 tests) reads the landing
copy sources as text — faqs.ts, FeatureShowcase/index.tsx,
HomepageFeatures/index.tsx, privacy/page.tsx — and fails if:

  • byte-identical or byte-for-byte reappears (whitespace-normalized first, so
    a phrase that straddles a JSX line wrap is still caught);
  • when you sign up reappears while the site still has no sign-up route;
  • any of trusted by, users worldwide, #1, most popular appears. None of
    those four is in the copy today
    — that assertion is a ratchet against
    unsubstantiated social proof arriving later, not a fix.

Proven both ways: green as committed (4 passed), and red on a temporary
re-insertion of byte-identical into faqs.ts (1 failed | 3 passed, pointing
at faqs.ts claims byte-identical rendering the parity suite does not verify).

Tests that pinned the old wording

None. Grepped apps/landing/src/__tests__, apps/landing/tests,
apps/e2e-test/landing and apps/e2e-test/cross-framework for every replaced
phrase: the only byte-identical hits are upload byte-integrity assertions in
apps/e2e-test/e2e/multipart-*.spec.ts (about stored objects matching their
source — unrelated) and one comment in ingestion-verification.spec.ts. The two
structural pins that would have mattered — docs-source.test.ts:24-30's
expect(pages.length).toBe(64) and landing/docs.spec.ts:30-31's
/documentation/comparisons redirect — are untouched: no comparison page was
added, renamed or removed.

Gates run locally (Windows, rtk proxy, exit codes checked)

gate result
pnpm --filter @useupup/landing run lint 0
pnpm --filter @useupup/landing run typecheck 0
pnpm --filter @useupup/landing run test all 5 src/__tests__ suites green incl. the new guard; the only failures are pre-existing timeouts in tests/ — see below
pnpm run test:quality 0 — 399 test files + 5 workflows clean
pnpm run vocab:check 0 — 1410 tracked files clean
pnpm run docs:links:check 0 — 403 links, 105 anchors, 8 redirect targets across 64 pages
pnpm run docs:api-sync:check 0 — 258 public API members
pnpm run docs:snippets:coverage 0
pnpm exec prettier --check on all 10 touched files (incl. README.md and the four .mdx) 0

Failures seen locally that this PR does not cause. Every one is
Error: Test timed out in 5000ms
on a box running five other build agents, and
the set changes between runs (1, then 4, then 5 failures) — the signature of load
flake, not a regression. None is in apps/landing/src/__tests__, where this PR's
only new test lives; all five src/__tests__ suites pass every run.

  • apps/landing/tests/support-route.test.ts — reproduced on the unmodified
    branch point (2 failed | 12 passed there vs 1 failed | 13 passed with this PR
    applied). This PR touches neither the route nor its test.
  • apps/landing/tests/analytics-isolation.test.ts — same timeout signature;
    untouched by this PR.
  • packages/react tests/source-overlay.test.tsx — failed once inside a parallel
    turbo run … --force, passes on its own (4 passed). No package source is
    touched by this PR.

pnpm run docs:snippets:check was not run locally: it type-checks doc snippets
against built dist, and no snippet changed. CI's Docs-Gate covers it.

Deliberately out of scope

  • apps/landing/src/app/page.tsx:17 (the last remaining "byte-identical" in
    product copy), src/app/[framework]/page.tsx metadata, and
    src/lib/siteConfig.ts are being rewritten by the parallel
    seo/money-page-copy PR, which drops the phrase there. Splitting it avoids
    two PRs fighting over the same strings. Once both land, no public surface
    claims byte equality.
  • Package versions were not touched (see the first owner question below).

Owner questions

  1. Keep the competitor comparison pages at all? With the two corrections
    above, every cell in all four tables is now backed by something fetched from
    the competitor's own docs or repo. The alternative is dropping the feature
    grids and keeping only the prose + "Choose X if" lists — note that deleting a
    comparison page also requires bumping docs-source.test.ts's toBe(64) and
    fixing the /documentation/comparisons redirect target.
  2. "Used in production" wording. Both reference apps run the v3.1 @upupjs
    lineage, so the section is now qualified rather than dropped. The other option
    is to upgrade uNotes and Shorty to @useupup/* 3.3 and then restore an
    unqualified claim. Related: the Discord badge points at guild
    1299099371647930502, which is still named "UpUp - React File Uploader"
    (9 members) — a Discord-side rename, nothing to change in this repo.
  3. 🟡 @useupup/server is behind on npm: registry latest is 3.3.0, while the
    other eight packages are at 3.3.3.
    (dev has every package at 3.3.0;
    master has the other eight at 3.3.3.) Publish lag or a failed publish? No
    version was touched by this PR, but any doc that names a server version will
    be wrong until it lands.
  4. Privacy page: should it name PostHog and Google Analytics as the
    processors behind "usage data via cookies and similar technologies"
    (posthog-provider.tsx, gtag.ts)? Also, the page still opens "Welcome to
    Upup" where the brand is lowercase "upup" everywhere else — left alone
    here as a style call, not a truth call.

@codesandbox

codesandbox Bot commented Sep 12, 2026

Copy link
Copy Markdown

Review or Edit in CodeSandbox

Open the branch in Web EditorVS CodeInsiders

Open Preview

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