Créer des cartes de Saint-Valentin personnalisées avec Transloadit & Uppy
À l’approche de la Saint-Valentin, nous souhaitons partager un projet amusant que vous pouvez réaliser avec Transloadit et Uppy. Nous allons utiliser le Robot /image/resize pour créer un générateur de cartes de Saint-Valentin personnalisées. Ajoutez aussi un nom sur la carte, et vous obtiendrez une carte personnalisée à envoyer à l’être aimé.

Nos Assembly Instructions
Jetons d’abord un œil aux Assembly Instructions que nous allons utiliser.
{
"steps": {
"watermark": {
"use": ":original",
"robot": "/image/resize",
"width": "1921",
"height": "1921",
"resize_strategy": "fillcrop",
"watermark_url": "https://transloadit.com/assets/images/blog/2023-01-26-valentines-card-generator-1.png",
"watermark_size": "100%",
"watermark_position": "center",
"imagemagick_stack": "v3.0.1"
},
"add_text": {
"use": "watermark",
"robot": "/image/resize",
"text": [
{
"text": "${fields.message}",
"size": 80,
"color": "#ffffff",
"valign": "bottom",
"y_offset": -90,
"x_offset": 0
}
],
"imagemagick_stack": "v3.0.1",
"result": true
}
}
}
Ici, nous devons utiliser deux Steps distincts avec /image/resize. Notre premier Step ajoute un cadre décoratif autour de notre image d’origine, tout en la recadrant et en la redimensionnant pour qu’elle s’adapte. Le second Step ajoute ensuite du texte par-dessus notre image filigranée, que nous modifierons plus tard avec JavaScript. Si nous faisions cela dans le même Step, le cadre de notre image serait placé devant le texte et le masquerait dans notre résultat final.
Enregistrez ces Instructions en tant que Template. Le code JavaScript ci-dessous envoie le message sous forme de champ, ce qui permet de garder les Instructions de traitement au même endroit. Avant tout déploiement public, utilisez des signatures générées côté serveur et validez le message sur votre serveur. Ne placez jamais d’Auth Secret dans du code côté navigateur.
L’URL de la carte générée est temporaire et expire au bout de 24 heures. Enregistrez la carte avant son expiration, ou ajoutez un Robot d’exportation tel que /s3/store (English) pour un stockage durable.
HTML et CSS
Malheureusement, nous n’avons encore aucun endroit où présenter notre nouveau Template. Remédions-y ! Copiez le code HTML ci-dessous dans un nouveau fichier HTML.
Notez en particulier notre élément input. Nous l’utiliserons dans la section suivante pour
permettre à l’utilisateur de modifier le nom à ajouter à sa carte.
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Transloadit Valentine</title>
<link href="https://releases.transloadit.com/uppy/v3.3.1/uppy.min.css" rel="stylesheet" />
</head>
<style></style>
<body>
<h1>Transloadit Valentine</h1>
<p>Upload a picture of your Valentine and we'll make it a Valentine's Day card!</p>
<div class="input-container">
<label for="name">Name:</label>
<input id="name" name="name" maxlength="12" />
</div>
<div id="drag-drop-area"></div>
<img id="result" alt="Your personalized Valentine's Day card" hidden />
<p id="status" role="status"></p>
</body>
</html>
Ajoutons maintenant une jolie mise en forme à notre page. À l’intérieur de la balise style,
ajoutez le CSS suivant.
:root {
--primary: #7f626a;
--secondary: #f8edeb;
--accent: #ff4d6d;
--accent-highlight: #f9ccd2;
}
body {
display: flex;
flex-direction: column;
align-items: center;
background-color: var(--secondary);
color: var(--primary);
font-family: sans-serif;
}
h1,
p {
margin: 0 0 0.5rem;
}
#result {
border-radius: 10px;
width: 480px;
max-width: calc(100vw - 2rem);
border: none;
contain: content;
aspect-ratio: 1/1;
margin: 2rem;
}
.input-container {
margin: 1rem;
color: var(--primary);
}
input {
border: none;
border-bottom: 2px var(--primary) dashed;
background-color: transparent;
text-align: start;
font: inherit;
color: var(--accent);
}
input:focus {
outline: 2px solid currentColor;
outline-offset: 2px;
}
.uppy-Dashboard {
max-width: 90vw;
}
.uppy-Dashboard-innerWrap {
background-color: var(--secondary);
border: var(--primary) 2px dashed;
}
.uppy-Dashboard-AddFiles {
border: 0 !important;
}
.uppy-Dashboard-poweredBy,
.uppy-Dashboard-poweredByIcon {
color: var(--primary) !important;
stroke: var(--primary);
}
.uppy-Dashboard-AddFiles-title,
.uppy-DashboardTab-name {
color: var(--primary);
}
.uppy-DashboardTab-btn:hover {
background-color: var(--accent-highlight) !important;
}
.uppy-Dashboard-browse,
.uppy-ProviderIconBg,
.uppy-DashboardContent-back,
.uppy-StatusBar-actionBtn {
color: var(--accent);
fill: var(--accent);
}
.uppy-DashboardContent-bar,
.uppy-StatusBar-actions,
.uppy-StatusBar,
.uppy-StatusBar::before {
border: none !important;
background-color: transparent !important;
}
.uppy-StatusBar-actionBtn--upload {
background-color: var(--accent) !important;
color: var(--secondary) !important;
border: none;
border-radius: 5px;
}
Même s’il peut paraître intimidant, l’essentiel de notre CSS ne sert qu’à restyler notre composant Dashboard d’Uppy. Pour le reste, nous utilisons simplement une palette de couleurs générée avec Coolors.
Voici à quoi notre page devrait maintenant ressembler :

JS
Passons maintenant à la partie amusante ! Après le code HTML, ajoutez le JavaScript suivant dans une
balise <script type="module">, en remplaçant les valeurs fictives de l’Auth Key et de l’identifiant du Template par
vos propres valeurs.
import {
Uppy,
Dashboard,
Transloadit,
ImageEditor,
} from 'https://releases.transloadit.com/uppy/v3.3.1/uppy.min.mjs'
const nameInput = document.getElementById('name')
const status = document.getElementById('status')
function cardMessage(name) {
const recipient = name.trim()
return recipient ? `Happy Valentine's Day, ${recipient}!` : "Happy Valentine's Day!"
}
const uppy = new Uppy({
restrictions: {
maxNumberOfFiles: 1,
allowedFileTypes: ['image/*'],
},
})
.use(Dashboard, {
inline: true,
target: '#drag-drop-area',
})
.use(ImageEditor, {
target: Dashboard,
quality: 0.8,
cropperOptions: {
aspectRatio: 1 / 1, // Same aspect ratio as our overlay
},
})
.use(Transloadit, {
waitForEncoding: true,
getAssemblyOptions: () => ({
params: {
auth: { key: 'YOUR_AUTH_KEY' },
template_id: 'YOUR_TEMPLATE_ID',
},
fields: { message: cardMessage(nameInput.value) },
}),
})
uppy.on('transloadit:complete', (assembly) => {
const url = assembly.results.add_text?.[0]?.ssl_url
if (typeof url !== 'string') {
status.textContent = 'No card was returned. Please try again.'
return
}
const resultImg = document.getElementById('result')
resultImg.src = url
resultImg.hidden = false
status.textContent = 'Your card is ready.'
})
uppy.on('upload', () => {
document.getElementById('result').hidden = true
status.textContent = 'Creating your card.'
})
uppy.on('error', () => {
status.textContent = 'Card generation failed. Please try again.'
})
Nous exploitons ici les composants Dashboard, ImageEditor et Transloadit d’Uppy, et heureusement, nous pouvons utiliser en grande partie les paramètres par défaut. Notons toutefois que nous réglons le rapport d’aspect de l’outil de recadrage d’ImageEditor sur celui de notre image de superposition. Dans notre cas, il est de 1:1.
La version épinglée d’Uppy appelle getAssemblyOptions au démarrage d’un envoi. Elle lit le nom actuel,
de sorte que vider le champ rétablit le message de salutation générique au lieu de conserver le
destinataire précédent.
Pour conclure
Combinez le HTML, le CSS et le script de module, configurez votre propre Template, puis servez la page en local pour l’essayer. La capture d’écran montre le prototype d’origine ; le code ci-dessus inclut l’URL de filigrane corrigée ainsi que la gestion du message et du résultat.
C’est tout pour le moment. Joyeuse Saint-Valentin, et n’oubliez pas d’envoyer à votre moitié une belle carte personnalisée. Et si vous avez réussi à pousser encore plus loin les outils utilisés dans cet article, nous serions ravis d’en entendre parler sur Twitter !
