Skip to content
colis

Template

The page your client opens.

Drop a file, get a code, a link and a QR code. Your client opens it, sees the file, and approves it or asks for changes, while your page shows the answer as it comes. A Next.js template on your own bucket, deployed on Vercel from the repository.

the environment
COLIS_BUCKET=livraisons
COLIS_ENDPOINT=https://<account-id>.r2.cloudflarestorage.com
COLIS_REGION=auto
AWS_ACCESS_KEY_ID=…
AWS_SECRET_ACCESS_KEY=…

# optional
DROP_PASSWORD=…              # asked before an upload, never for a pickup
DROP_EXPIRES_IN=86400        # the default lifetime, in seconds
DROP_MAX_EXPIRES_IN=604800   # the longest a sender may choose
DROP_MAX_SIZE_MB=4           # through the function, under Vercel's limit
DROP_MAX_UPLOAD_MB=2048      # above that, straight to the bucket, in parts
DROP_WEBHOOK_URL=…           # where the signed events go
DROP_WEBHOOK_SECRET=…        # and what signs them

01What you get

Two pages, and the routes between them.

The sending page, the pickup page, and the transfer routes with the receipt on top. Everything is yours to restyle.

Staged before it goes

Picking a file shows what it is and a form: the lifetime, a password for this parcel, burn after the first download, the name it downloads under, the sending device, and a note of up to 280 characters. Nothing leaves the machine until you press send.

A shipping label

The result prints the code on a label with a Code 39 barcode, the link to share, and a QR code of that link for a phone.

The pickup page

/K7QP2M4X shows the file before anything is saved: an image, a video, audio, a PDF, the first lines of a text. Then what is known about it: the size, the type, the time left, the sender’s note.

Approve or ask for changes

Under the preview, one question: does the file match what was expected? Approve the delivery, or ask for changes and say which, in up to 1,000 characters. One answer, final.

Your tracking

Your sending page follows the receipt on its own: sent, opened, then the verdict, stamped « Validé » or « À corriger », with the client’s comment.

Large files, resumable

Above DROP_MAX_SIZE_MB, the browser uploads straight to your bucket in 8 MiB parts, up to DROP_MAX_UPLOAD_MB, and picks an interrupted upload up where it stopped.

02Deploy

Five variables, one lifecycle rule.

Until the @colis packages are on npm, the page builds from the monorepo: import the whole repository on Vercel, not the template folder alone.

  1. 01Create a bucket on R2, S3, Scaleway, Wasabi or a MinIO you host, and a key pair with read and write on that bucket and nothing else.
  2. 02On Vercel, Add New → Project and pick the repository. Set the Root Directory to templates/drop and leave “Include files outside the root directory” on: its vercel.json installs with Bun at the root and builds the packages first.
  3. 03Paste the five variables, and DROP_PASSWORD so strangers cannot fill your bucket.
  4. 04Add a lifecycle rule that deletes objects under the prefix (drop/ by default) after a day or two, and a CORS rule for large files.
  5. 05Run colis verifier --remote https://your-deployment.vercel.app/api/transfers --token <password> and watch it round-trip a real parcel.
or run it locally
git clone https://github.com/mamadouwhile/colis.git && cd colis
bun install && bun run build
cp templates/drop/.env.example templates/drop/.env.local   # point it at a bucket
bun run --filter colis-drop dev                               # http://localhost:3400
Import on Vercel

03Worth knowing

What it does not do.

No accounts, no history

A code is a bearer token with an expiry. There is no list of past parcels; each one’s receipt lives as long as the deployment’s longest lifetime.

One file per code

Zip a folder first. From a terminal it is one line: tar cz ./dir | colis envoyer - --name dir.tar.gz.

A preview costs a download

The bytes come through the function either way, so DROP_PREVIEW_MAX_MB caps it and DROP_PREVIEW=false turns it off. Uploaded files are never served as a page this origin would run.

Send it. They sign off. You know.

Your storage, a delivery page under your name, a webhook at every step. Nothing hosted by someone else.