colisdocs

Page de livraison

Déployer templates/drop sur Vercel avec votre bucket : Root Directory, variables, CORS et cycle de vie sur R2.

La page de livraison est une app Next.js du dépôt, templates/drop. C’est elle que votre client ouvre : elle reçoit les fichiers, affiche la page de retrait avec l’aperçu, tient l’accusé de réception et envoie les webhooks. Elle tourne sur votre compte Vercel, avec votre bucket ; une démo est en ligne sur colis-tau.vercel.app.

Ce qu’elle sert

RouteRôle
/La zone de dépôt, le fichier en attente avec ses options, et « Vous avez déjà un code ? ».
/K7QP2M4XLa page de retrait : l’aperçu, ce que l’on sait du colis, le téléchargement, un QR code, la réponse du client.
/api/transfers/*Les quatre routes du protocole, donc la CLI fonctionne aussi.
/api/transfers/:code/statusL’accusé de réception, et ses deux POST : opened et verdict. Voir Suivi et validation.
/api/transfers/uploads/*Les gros fichiers : URL présignées pour les morceaux, puis l’assemblage.
/api/preview/:codeLes mêmes octets, servis pour être regardés plutôt qu’enregistrés.
/connexion, /api/auth/*Les comptes, facultatifs : connexion par lien e-mail, et colis connexion pour un terminal.
/api/unlock/:codeLà où l’on tape le mot de passe d’un colis protégé.

Le bucket

  1. Créez un bucket et une paire de clés qui ne peut que lire et écrire dans ce bucket. Sur Cloudflare R2 : R2 → Create bucket, puis un jeton d’API avec Object Read & Write limité à ce bucket. Sur AWS : un utilisateur IAM ou un rôle limité au bucket. Voir Stockages.
  2. Ajoutez une règle de cycle de vie sur le préfixe (drop/ par défaut). L’expiration empêche un colis d’être remis ; seule la règle supprime l’objet. Réglez-la au moins un jour au-delà de la plus longue durée autorisée, DROP_MAX_EXPIRES_IN (sept jours par défaut, donc huit jours) — ou DROP_PRO_MAX_EXPIRES_IN (trente jours, donc 31) si le déploiement vend la formule Pro —, sinon le bucket supprime des colis encore valides. Ajoutez-y AbortIncompleteMultipartUpload après un jour, pour les envois de gros fichiers abandonnés.
  3. Ajoutez une règle CORS si vous gardez les gros fichiers : le navigateur envoie leurs morceaux directement au bucket.

Sur R2, les deux réglages sont dans R2 → votre bucket → Settings : Object lifecycle rules et CORS Policy. La règle CORS, avec l’adresse de votre déploiement :

[
  {
    "AllowedOrigins": ["https://votre-livraison.vercel.app"],
    "AllowedMethods": ["PUT"],
    "AllowedHeaders": ["*"],
    "ExposeHeaders": ["ETag"],
    "MaxAgeSeconds": 3600
  }
]

Ajoutez http://localhost:3400 aux origines pour tester en développement.

Sur Vercel

Tant que les paquets @colis/* ne sont pas sur npm, la page se construit depuis le monorepo : on importe tout le dépôt, pas seulement le dossier du template.

  1. Add New → Project, et choisissez votre fork du dépôt colis.
  2. Root Directory : templates/drop. Laissez Include files outside the root directory activé : le vercel.json de ce dossier installe à la racine avec Bun (bun install --frozen-lockfile) et construit avec Turborepo (bunx turbo run build --filter=colis-drop), paquets compris.
  3. Environment Variables : les cinq variables du bucket, et DROP_PASSWORD pour que des inconnus ne puissent pas remplir votre bucket.
VariableValeur
COLIS_BUCKETLe nom du bucket.
COLIS_ENDPOINTPour R2 : https://<account-id>.r2.cloudflarestorage.com. Vide pour AWS S3.
COLIS_REGIONauto pour R2 (c’est la valeur par défaut) ; une vraie région pour AWS et Scaleway.
AWS_ACCESS_KEY_IDLa clé d’accès.
AWS_SECRET_ACCESS_KEYLa clé secrète.
DROP_PASSWORDDemandé avant chaque envoi. Le retrait ne le demande jamais.

Toutes les autres variables (durées, tailles, aperçu, webhooks) sont dans Configuration.

  1. Vérifiez que le déploiement fait un vrai aller-retour :
colis verifier --remote https://votre-livraison.vercel.app/api/transfers --token "$DROP_PASSWORD"

Pour garder l’adresse et le mot de passe hors de votre historique, mettez-les dans un colis.config.json (colis init --provider remote), voir CLI.

Avant l’envoi

Choisir un fichier ne l’envoie pas : la page le montre (l’image, la vidéo, les premières lignes du texte) et propose ce que l’expéditeur peut décider. Rien ne part avant le bouton.

OptionEffet
Durée de conservationDe dix minutes à DROP_MAX_EXPIRES_IN. Passé ce délai, le bucket ne remet plus rien.
Mot de passe pour ce colisDemandé avant de voir quoi que ce soit. Haché avec scrypt, jamais récupérable.
Détruire après le premier téléchargementLe code cesse de fonctionner quand les octets partent. L’aperçu reste gratuit.
Renommer le fichierLe nom sous lequel le client le télécharge.
Envoyé depuisUne étiquette pour la machine, devinée depuis le navigateur : « Chrome sur macOS ».
Un messageJusqu’à 280 caractères, affichés au-dessus du fichier sur la page de retrait.

Ces options voyagent dans des en-têtes x-drop-* à côté du protocole, que la CLI ne connaît pas : un colis envoyé par colis envoyer prend les valeurs par défaut du déploiement. Depuis un terminal, les mêmes options s’envoient à la main :

curl -X POST https://votre-livraison.vercel.app/api/transfers \
  -H "authorization: Bearer $DROP_PASSWORD" \
  -H 'content-type: application/pdf' \
  -H "x-colis-filename: $(printf %s contrat.pdf | jq -sRr @uri)" \
  -H 'x-drop-expires-in: 3600' -H 'x-drop-once: 1' \
  -H 'x-drop-passphrase: open%20sesame' \
  --data-binary @contrat.pdf

x-drop-note et x-drop-device portent le message et l’étiquette, encodés de la même façon.

Le retrait

Trois façons d’arriver sur la page de retrait :

  • Taper le code sur la page d’accueil. k7qp-2m4x retrouve K7QP2M4X : séparateurs retirés, casse unifiée, O lu comme zéro.
  • Scanner le QR code affiché après l’envoi et sur la page de retrait.
  • Depuis un terminal : colis recevoir k7qp-2m4x --remote https://votre-livraison.vercel.app/api/transfers.

La page montre ce qu’il y a avant tout téléchargement : image, vidéo, audio, PDF, premières lignes d’un texte, et pour le reste l’extension et la taille. Dessous, le nom, la taille, le type, la date d’envoi, le temps restant, la machine d’envoi et, le cas échéant, la destruction au téléchargement. Puis la réponse du client : voir Suivi et validation.

Un colis protégé ne dit que cela tant que le mot de passe n’est pas tapé. Il part vers /api/unlock/<code>, qui donne au navigateur un cookie valable pour ce seul code, jusqu’à la fermeture du navigateur. Dix mauvais mots de passe depuis un même client, ou cinquante sur un même code, verrouillent ce code quinze minutes (429). Depuis un terminal, le mot de passe du colis passe en --token.

Un colis à usage unique l’annonce avant le clic. Le premier téléchargement le réserve par une écriture conditionnelle ; un second lancé au même moment est refusé.

Les deux mots de passe

DROP_PASSWORD appartient au déploiement : sans lui, quiconque trouve la page peut déposer un fichier dans votre bucket. Avec lui, la page le demande une fois avant l’envoi et l’envoie en jeton Bearer ; la CLI le passe avec --token, le nœud n8n dans ses identifiants.

Le mot de passe d’un colis appartient à l’expéditeur, un par colis. Seule son empreinte scrypt est stockée : personne, pas même vous, ne peut le relire ni le réinitialiser.

Personnaliser

Tailwind 4, deux pages, aucune bibliothèque de composants. Les couleurs, les polices et les rayons sont des variables en tête de app/globals.css, avec un jeu sombre sous prefers-color-scheme. DROP_NAME change le nom affiché dans l’en-tête et le titre. Le README du template liste chaque fichier et son rôle.

Sur cette page