Crea tarjetas de San Valentín a medida con Transloadit & Uppy
Con la llegada de San Valentín, queremos compartir un proyecto divertido que puedes construir con Transloadit y Uppy. Usaremos el Robot /image/resize para crear un generador de tarjetas personalizadas de San Valentín. Añade también un nombre a la tarjeta y tendrás una tarjeta personalizada para enviársela a tu ser querido.

Nuestras Assembly Instructions
Primero, echemos un vistazo a las Assembly Instructions que vamos a usar.
{
"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"
},
"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",
"result": true
}
}
}
Aquí necesitamos usar dos Steps distintos de /image/resize. Nuestro primer Step añade un marco decorativo alrededor de la imagen original, a la vez que la recorta y la redimensiona para que encaje. El segundo Step añade luego texto sobre nuestra imagen con marca de agua, que modificaremos más adelante con JavaScript. Si hiciéramos esto en el mismo Step, el marco de la imagen quedaría delante del texto, ocultándolo en nuestro resultado final.
Guarda estas Instructions como un Template. El JavaScript de abajo envía el mensaje como un campo, manteniendo las Instructions de procesamiento en un solo lugar. Antes de desplegarlo públicamente, usa firmas generadas en el servidor y valida el mensaje en tu servidor. Nunca pongas un Auth Secret en el código del navegador.
La URL de la tarjeta generada es temporal y caduca después de 24 horas. Guarda la tarjeta antes de que caduque o añade un Robot de exportación como /s3/store para un almacenamiento duradero.
HTML & CSS
Lamentablemente, no tenemos dónde lucir nuestro nuevo Template. ¡Vamos a solucionarlo! Copia el siguiente HTML en un nuevo archivo HTML.
Algo a tener en cuenta es nuestro elemento input. Lo usaremos en la siguiente sección para permitir
que el usuario cambie el nombre que se añade a su tarjeta.
<!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>
Ahora, vamos a añadir un poco de estilo a nuestra página. Dentro de la etiqueta style, añade el siguiente CSS.
: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;
}
Aunque pueda parecer intimidante, la mayor parte de nuestro CSS aquí existe solo para cambiar el estilo de nuestro componente Dashboard de Uppy. Aparte de eso, solo usamos una paleta de colores generada con Coolors.
Así es como debería verse ahora nuestra página:

JS
¡Ahora viene la parte divertida! Después del HTML, añade el siguiente JavaScript dentro de una etiqueta <script type="module">,
reemplazando los marcadores de posición de la Auth Key y del Template ID por tus propios valores.
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.'
})
Aquí aprovechamos los componentes Dashboard, ImageEditor y Transloadit de Uppy y, por suerte, en su mayor parte podemos usar la configuración predeterminada. Sin embargo, cabe destacar que fijamos la relación de aspecto de la herramienta de recorte de ImageEditor para que sea la misma que la de nuestra imagen superpuesta. En nuestro caso, es 1:1.
La versión fijada de Uppy llama a getAssemblyOptions cuando comienza una subida. Lee el nombre actual,
por lo que borrar el campo restaura el saludo genérico en lugar de conservar el destinatario anterior.
Para terminar
Combina el HTML, el CSS y el script de módulo, configura tu propio Template y sirve la página en local para probarla. La captura de pantalla muestra el prototipo original; el código de arriba incluye la URL corregida de la marca de agua, el manejo del mensaje y el manejo del resultado.
Eso es todo por nuestra parte por ahora. ¡Feliz San Valentín, y no dejes de enviarle a esa persona especial una tarjeta bonita y personalizada! Y si lograste llevar aún más lejos las herramientas usadas en esta entrada del blog, ¡nos encantaría saberlo en Twitter!
