speedy · self-hosted

1. Reactive numbers (sanity check)

Click below. Open this page in another tab — the new number appears in both, in real time, over the Convex WebSocket.

Click the button!

2. Path A — Convex-managed upload

We call ctx.storage.generateUploadUrl() (a Convex mutation), PUT the file to the URL it returns, then record the resulting storageId in a Convex table. The bytes live in our MinIO via the S3 env vars Convex is configured with. Convex owns the lifecycle.

3. Path B — DIY presigned URL

We call a Convex action that uses the AWS SDK to sign a PUT URL to our uploads bucket. We PUT the file directly to MinIO (Convex is not in the bytes path), then record the object key in a separate Convex table. You own the lifecycle.

To download a file from this list, sign a GET URL with getDirectDownloadUrl (not wired to a button yet — kept minimal so the learning notes stay focused).

Open another page to send an action.