diff --git a/README.md b/README.md index 41ce0e4d5..eec469e23 100644 --- a/README.md +++ b/README.md @@ -7,12 +7,11 @@
- A headless upload engine with native, byte-identical UI packages for + A headless upload engine with native, DOM-identical UI packages for React, Vue, Svelte, Angular, Vanilla JS, and Preact — with optional server-mode uploads, cloud drives, camera, screen capture, and link imports.
-
We may collect personal data such as your name and email
- address when you sign up or contact us. Additionally, we
- gather usage data via cookies and similar technologies.
+ address when you contact us, submit the support form, or
+ request a provider integration. Additionally, we gather
+ usage data via cookies and similar technologies.
You can connect to upup using any S3 provider. We
- also support some non-S3 connections.
+ also support Azure Blob Storage in client mode.
@@ -31,15 +30,15 @@
**upup** is a free, MIT-licensed file uploader built as one headless
[`@useupup/core`](packages/core) engine with a matching native UI for every major
framework. React is the visual canon; the Vue, Svelte, Angular, Vanilla, and
-Preact ports render the **same DOM** with the **same props**, verified
-byte-for-byte by a cross-framework parity harness. Upload straight from the
-browser to any S3-compatible storage (Client Mode), or route through your own
-backend with an HMAC-signed trust model (Server Mode via
-[`@useupup/server`](packages/server)).
+Preact ports render the **same DOM** with the **same props**, verified by a
+cross-framework parity harness (structure, classes, accessibility attributes,
+text). Upload straight from the browser to any S3-compatible storage (Client
+Mode), or route through your own backend with an HMAC-signed trust model
+(Server Mode via [`@useupup/server`](packages/server)).
## Install
-Pick the package for your framework — the component API and rendered DOM are identical across all of them:
+Pick the package for your framework — the component API and the rendered DOM contract are identical across all of them:
| Package | Install | Get started |
| ------------------ | ------------------------ | ------------------------------------------------------------------ |
@@ -113,7 +112,7 @@ Express, Fastify, and Hono handlers ship as subpath exports
## Features
- **Headless core.** `@useupup/core` is a zero-framework-dependency engine: file state, an upload pipeline (compression, HEIC→JPEG, EXIF stripping, checksums, thumbnails, optional Web Worker offload), cloud-drive plugins, i18n, and theming. Build your own UI on it, or use a native package.
-- **Native UI for six frameworks.** React, Vue, Svelte, Angular, Vanilla JS, and Preact — same DOM, same Tailwind classes, enforced byte-for-byte by a parity harness.
+- **Native UI for six frameworks.** React, Vue, Svelte, Angular, Vanilla JS, and Preact — same DOM structure, same `upup-` classes, enforced by a cross-framework parity harness.
- **Client or Server mode.** Direct browser → storage presigned uploads, or a server-proxied [`@useupup/server`](packages/server) with an HMAC-signed trust model (signed length, key/uploadId binding, mandatory secrets).
- **S3-compatible storage.** AWS S3, Cloudflare R2, MinIO, DigitalOcean Spaces, Backblaze B2, Wasabi — any S3-compatible endpoint.
- **Cloud drives.** Import from Google Drive, OneDrive, Dropbox, and Box, in client or server mode.
@@ -123,7 +122,10 @@ Express, Fastify, and Hono handlers ship as subpath exports
- **i18n & theming.** ICU-based localization with 9 bundled locales and RTL support, plus a slot-level theming system that targets every rendered element.
- **TypeScript-first.** Full type definitions out of the box.
-## Battle-tested in production
+## 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/*`.
- **uNotes** — AI doc uploads for past exams → [unotes.net](https://unotes.net)
- **Shorty** — media uploads for transcripts → [aishorty.com](https://aishorty.com)
diff --git a/apps/landing/content/docs/comparisons/upup-vs-filepond.mdx b/apps/landing/content/docs/comparisons/upup-vs-filepond.mdx
index ae0586434..94f486766 100644
--- a/apps/landing/content/docs/comparisons/upup-vs-filepond.mdx
+++ b/apps/landing/content/docs/comparisons/upup-vs-filepond.mdx
@@ -14,17 +14,17 @@ capture, and an S3-compatible server with an HMAC-signed trust model.
## At a glance
-| Feature | FilePond | upup |
-| ----------------------------- | ------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------ |
-| Native first-party UI | Vanilla JS core + adapters: React, Vue, Angular, Svelte, jQuery | React, Vue, Svelte, Angular, Vanilla JS, Preact |
+| Feature | FilePond | upup |
+| ----------------------------- | ------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------- |
+| Native first-party UI | Vanilla JS core + adapters: React, Vue, Angular, Svelte, jQuery | React, Vue, Svelte, Angular, Vanilla JS, Preact |
| Headless core | No — renders its own UI component | Yes (`@useupup/core`) |
-| License / pricing | MIT, free & open source (the Pintura image editor is a separate commercial product) | MIT, free & open source |
+| License / pricing | MIT, free & open source (the Pintura image editor is a separate commercial product) | MIT, free & open source |
| Self-host incl. S3-compatible | Yes — uploads to your own server endpoint (process / revert / restore), with chunk uploads; no built-in S3 signing | Yes — `@useupup/server` presigns and proxies to any S3-compatible storage |
-| Cloud-drive sources | No (local files, directories, blobs, local/remote URLs, Data URIs, paste) | Google Drive, OneDrive, Dropbox, Box |
-| Camera / screen capture | No | Yes (both) |
-| Image editor | Via plugins (crop / resize / transform); a full editor is Pintura (separate/commercial) | Yes — React/Preact only |
-| Resumable uploads | Chunked uploads (server-driven) | Yes — optional (tus or S3 multipart) |
-| i18n | Configurable label strings (no locale bundles) | Yes (ICU locale bundles) |
+| Cloud-drive sources | No (local files, directories, blobs, local/remote URLs, Data URIs, paste) | Google Drive, OneDrive, Dropbox, Box |
+| Camera / screen capture | No | Yes (both) |
+| Image editor | Via plugins (crop / resize / transform); a full editor is Pintura (separate/commercial) | Yes — React/Preact only |
+| Resumable uploads | Chunked uploads (server-driven) | Yes — optional (tus or S3 multipart) |
+| i18n | 48 locale files in `locale/`, plus configurable label strings | Yes (ICU locale bundles) |
## Choose FilePond if
diff --git a/apps/landing/content/docs/comparisons/upup-vs-uploadthing.mdx b/apps/landing/content/docs/comparisons/upup-vs-uploadthing.mdx
index cdcdab006..0f9077dde 100644
--- a/apps/landing/content/docs/comparisons/upup-vs-uploadthing.mdx
+++ b/apps/landing/content/docs/comparisons/upup-vs-uploadthing.mdx
@@ -15,18 +15,18 @@ screen capture, image editing, and native UI for six frameworks.
## At a glance
-| Feature | UploadThing | upup |
-| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------- |
-| Model | Hosted SaaS (managed storage + CDN) | Self-hosted library (your storage) |
-| Native first-party UI | React components (`UploadButton` / `UploadDropzone`) + adapters for Next.js and other full-stack frameworks (Solid, Svelte, Vue, Nuxt, Expo, and more) | React, Vue, Svelte, Angular, Vanilla JS, Preact |
+| Feature | UploadThing | upup |
+| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------- |
+| Model | Hosted SaaS (managed storage + CDN) | Self-hosted library (your storage) |
+| Native first-party UI | React components (`UploadButton` / `UploadDropzone`) + adapters for Next.js and other full-stack frameworks (Solid, Svelte, Vue, Nuxt, Expo, and more) | React, Vue, Svelte, Angular, Vanilla JS, Preact |
| Headless core | React hooks (coupled to the service) | Yes (`@useupup/core`, framework-agnostic) |
-| License / pricing | Open-source SDK (MIT); the service is a paid SaaS with a free tier and usage-based plans | MIT, free & open source (you pay only for your own storage) |
+| License / pricing | Open-source SDK (MIT); the service is a paid SaaS with a free tier and usage-based plans | MIT, free & open source (you pay only for your own storage) |
| Storage / self-host | Managed — files are stored on UploadThing's infrastructure | Any S3-compatible storage you own (AWS, MinIO, R2, Spaces, Wasabi, Backblaze) via `@useupup/server` |
-| Cloud-drive sources | No | Google Drive, OneDrive, Dropbox, Box |
-| Camera / screen capture | No | Yes (both) |
-| Image editor | No | Yes — React/Preact only |
-| Resumable uploads | Not a primary feature | Yes — optional (tus or S3 multipart) |
-| i18n | No | Yes (ICU locale bundles) |
+| Cloud-drive sources | Not built in | Google Drive, OneDrive, Dropbox, Box |
+| Camera / screen capture | Not built in | Yes (both) |
+| Image editor | Not built in | Yes — React/Preact only |
+| Resumable uploads | Yes — `createUpload` (start, pause, resume), since v7 | Yes — optional (tus or S3 multipart) |
+| i18n | No | Yes (ICU locale bundles) |
## Choose UploadThing if
diff --git a/apps/landing/content/docs/guides/reliability.mdx b/apps/landing/content/docs/guides/reliability.mdx
index 4513fc0e0..03f795746 100644
--- a/apps/landing/content/docs/guides/reliability.mdx
+++ b/apps/landing/content/docs/guides/reliability.mdx
@@ -298,7 +298,7 @@ all, tus remains the resumable option.
## A note on `fastAbortThreshold`
`fastAbortThreshold` is accepted by the core options and forwarded internally,
-but nothing reads it in v3.1.0 — setting it has no effect on behavior. It is
+but nothing reads it as of v3.3 — setting it has no effect on behavior. It is
documented here only so you do not spend an afternoon tuning a value that does
nothing. Use `maxRetries` to control how long upup persists on a failing file.
diff --git a/apps/landing/content/docs/guides/server-auth.mdx b/apps/landing/content/docs/guides/server-auth.mdx
index 7af7e788c..fcb997b12 100644
--- a/apps/landing/content/docs/guides/server-auth.mdx
+++ b/apps/landing/content/docs/guides/server-auth.mdx
@@ -128,7 +128,7 @@ The token binds:
from `exp`, since `init` is the only issuer and has always used the same TTL.
It is signed with HMAC-SHA-256 over the payload using your
-`uploadTokenSecret`, via Web Crypto (so it works on Node 18+, edge runtimes,
+`uploadTokenSecret`, via Web Crypto (so it works on Node 20+, edge runtimes,
and Cloudflare Workers). On every continuation request the handler verifies the
signature **before** trusting any payload byte, compares it in constant time,
and checks expiry — the one exception being `resume`, which applies the resume
diff --git a/apps/landing/src/__tests__/claim-integrity.test.ts b/apps/landing/src/__tests__/claim-integrity.test.ts
new file mode 100644
index 000000000..5b8417233
--- /dev/null
+++ b/apps/landing/src/__tests__/claim-integrity.test.ts
@@ -0,0 +1,95 @@
+import { readFileSync } from 'node:fs'
+import { fileURLToPath } from 'node:url'
+import { describe, expect, it } from 'vitest'
+
+// Ratchet for the 2026-09 claim-integrity pass. Marketing copy is read
+// literally by the people evaluating upup, so the wording the audit retired
+// must not creep back in. Two classes are gated here:
+//
+// 1. Claims the code cannot back. The cross-framework parity suite compares a
+// NORMALIZED tree — structure, `upup-` class tokens, a11y attributes and
+// text, with framework-injected attributes stripped and Angular host
+// elements unwrapped (apps/e2e-test/cross-framework/parity-dom.ts) — so
+// "byte-identical" / "byte-for-byte" overstates what it proves. The site
+// also has no account system (src/app has no sign-up route), so copy about
+// data collected "when you sign up" describes a flow that does not exist.
+// 2. Social proof upup has never been able to substantiate: user counts,
+// "trusted by" endorsements, and ranking superlatives. None appear today —
+// this locks that in rather than fixing it after it ships.
+//
+// The sources are read as TEXT on purpose: the claims live in string literals
+// and JSX prose, and a text read catches them wherever in the file they move.
+
+const COPY_SOURCES: Record
1. Information We Collect
2. How We Use Your Information
diff --git a/apps/landing/src/components/FeatureShowcase/index.tsx b/apps/landing/src/components/FeatureShowcase/index.tsx
index 6649276b9..55531fdbc 100644
--- a/apps/landing/src/components/FeatureShowcase/index.tsx
+++ b/apps/landing/src/components/FeatureShowcase/index.tsx
@@ -46,7 +46,7 @@ const heroRows: HeroRow[] = [
icon: