Saltar al contenido

ImageKit y Astro

ImageKit es una plataforma de optimización y entrega de medios en tiempo real con una CDN global, un gestor de assets digitales (DAM) integrado, y una API de transformación basada en URL para imágenes y videos.

Al entregar a través de ImageKit, obtienes conversión automática de formato (AVIF, WebP), calidad automática, imágenes responsivas, transformaciones con IA (eliminación de fondo, relleno generativo, escalado), y streaming de video adaptativo.

El ImageKit Astro SDK registra un servicio de imágenes personalizado que redirige los componentes integrados <Image /> y <Picture /> de Astro, además de las imágenes Markdown y MDX, a través de ImageKit. Las importaciones locales siguen siendo procesadas por el servicio Sharp integrado de Astro. Esto significa que un proyecto existente puede añadir la integración sin romper los assets existentes.

El SDK también proporciona un componente <Video />, un componente <OgImage /> para tarjetas sociales, y un helper del lado del servidor para emitir tokens de subida del lado del cliente.

Para construcción pura de URLs o subidas desde el navegador en cualquier framework, también puedes usar el ImageKit JavaScript SDK de nivel inferior. Para gestión de assets del lado del servidor (subidas, listado, eliminación, metadatos), usa el ImageKit Node.js SDK.

Instala el SDK ejecutando el comando apropiado para tu gestor de paquetes:

Ventana de la terminal
npm install @imagekit/astro

Crea un nuevo archivo .env en la raíz de tu proyecto y añade tus credenciales de ImageKit:

.env
IMAGEKIT_URL_ENDPOINT="https://ik.imagekit.io/<your_imagekit_id>"
# Only needed if you generate upload auth tokens on the server
PUBLIC_IMAGEKIT_PUBLIC_KEY="<Your Public Key>"
IMAGEKIT_PRIVATE_KEY="<Your Private Key>"

Luego registra la integración en astro.config.mjs:

astro.config.mjs
import { defineConfig } from 'astro/config';
import imagekit from '@imagekit/astro/integration';
export default defineConfig({
integrations: [imagekit()],
});

También puedes pasar urlEndpoint directamente a la integración en lugar de usar la variable de entorno:

astro.config.mjs
imagekit({
urlEndpoint: 'https://ik.imagekit.io/<your_imagekit_id>',
}),

Con la integración instalada, los componentes integrados <Image /> y <Picture /> de Astro dirigen las solicitudes a través de ImageKit y aplican optimización automática de formato y calidad, srcset responsivo, y lazy loading.

Component.astro
---
import { Image } from 'astro:assets';
---
<Image
src="/sample.jpg"
width={800}
height={600}
alt="A sample image"
/>

La integración añade una prop adicional transformation en <Image />, <Picture />, y getImage() para aplicar cualquier transformación de ImageKit (p. ej. recorte, enfoque, efectos de IA, superposiciones):

Component.astro
---
import { Image } from 'astro:assets';
---
<Image
src="/portrait.jpg"
width={500}
height={500}
alt="Cropped portrait"
transformation={[{ width: 500, height: 500, focus: 'face' }]}
/>

El width y height a nivel de componente establecen las dimensiones HTML renderizadas. Los valores dentro de transformation controlan el redimensionamiento del lado del servidor de ImageKit.

Las transformaciones de ImageKit incluyen efectos de IA que se pueden aplicar a través de la misma prop transformation:

Component.astro
---
import { Image } from 'astro:assets';
---
<!-- Remove background -->
<Image
src="/product.jpg"
width={500}
height={500}
alt="Product with background removed"
transformation={[{ aiRemoveBackground: true }]}
/>
<!-- Upscale a low-resolution image -->
<Image
src="/thumbnail.jpg"
width={1024}
height={1024}
alt="Upscaled image"
transformation={[{ aiUpscale: true }]}
/>
<!-- Generative fill to extend an image to a new aspect ratio -->
<Image
src="/portrait.jpg"
width={1600}
height={900}
alt="Image extended with generative fill"
transformation={[
{ width: 1600, height: 900, cropMode: 'pad_resize', background: 'genfill' },
]}
/>
<!-- AI drop shadow -->
<Image
src="/product.png"
width={500}
height={500}
alt="Product with AI drop shadow"
transformation={[{ aiDropShadow: true }]}
/>

Consulta la referencia de transformaciones soportadas en la documentación de ImageKit para la lista completa, incluyendo superposiciones, recorte inteligente (focus: 'auto', focus: 'face'), y otros efectos.

Añade videos a tus componentes .astro con el componente <Video />. Acepta atributos estándar de video HTML junto con props específicas de ImageKit como transformation y urlEndpoint.

Component.astro
---
import { Video } from '@imagekit/astro';
---
<Video
src="/sample.mp4"
width={1280}
height={720}
controls
/>

Para redimensionar el video del lado de ImageKit, pasa las dimensiones dentro de transformation:

Component.astro
<Video
src="/sample.mp4"
width={640}
height={360}
transformation={[{ width: 640, height: 360 }]}
controls
/>

El paquete @imagekit/video-player exporta una integración dedicada de Astro a través del subpath @imagekit/video-player/astro. Proporciona un componente nativo de Astro IKVideoPlayer con tipos completos de TypeScript (IKPlayerOptions, SourceOptions). Puedes usarlo directamente en archivos .astro sin ningún adaptador de framework.

El reproductor está construido sobre Video.js e incluye subtítulos y capítulos generados por IA, traducción automática a más de 50 idiomas, resaltado estilo karaoke a nivel de palabra, miniaturas de búsqueda, un reproductor flotante fijo, y streaming adaptativo de bitrate (HLS/DASH). No se requiere trabajo manual de transcripción.

Instala el paquete:

Ventana de la terminal
npm install @imagekit/video-player

Luego usa el componente IKVideoPlayer en cualquier archivo .astro:

VideoPlayer.astro
---
import { IKVideoPlayer } from '@imagekit/video-player/astro';
import '@imagekit/video-player/styles.css';
const ikOptions = {
imagekitId: 'YOUR_IMAGEKIT_ID',
seekThumbnails: true,
};
const source = {
src: 'https://ik.imagekit.io/your_imagekit_id/video.mp4',
chapters: true, // AI-generated chapter markers
textTracks: [{
autoGenerate: true, // AI speech-to-text subtitles
default: true,
highlightWords: true, // word-level highlighting
translations: [
{ langCode: 'es', label: 'Spanish' },
{ langCode: 'fr', label: 'French' },
],
}],
};
---
<IKVideoPlayer ikOptions={ikOptions} source={source} />

Con chapters: true, el reproductor auto-genera marcadores de capítulo a partir del contenido del video. Establecer autoGenerate: true en textTracks crea subtítulos de IA de voz a texto sin ningún archivo .srt. Cada entrada en translations añade una pista de subtítulos generada automáticamente en ese idioma.

Usa el componente <OgImage /> para renderizar etiquetas <meta> de OpenGraph y Twitter Card que apuntan a una imagen optimizada por ImageKit. Colócalo dentro del <head> de tu layout.

Layout.astro
---
import { OgImage } from '@imagekit/astro';
---
<html>
<head>
<OgImage
src="/og-banner.jpg"
title="My page title"
description="Preview description for social cards"
alt="OG image description"
/>
</head>
<body><slot /></body>
</html>

Si necesitas solo una URL en lugar de las etiquetas renderizadas, usa el helper getOgImageUrl():

Layout.astro
---
import { getOgImageUrl } from '@imagekit/astro';
const ogImage = getOgImageUrl({
src: '/og-banner.jpg',
transformation: [{ width: 1200, height: 630 }],
});
---
<meta property="og:image" content={ogImage} />

Consulta la documentación del componente OG de ImageKit para una lista completa de props soportadas.

Para subir archivos directamente desde el navegador, genera un token de autenticación de corta duración en el servidor usando el helper getUploadAuthParams() de @imagekit/astro/server. La clave privada permanece del lado del servidor y nunca se envía al navegador.

Esto requiere un adaptador para que el endpoint se ejecute bajo demanda:

src/pages/api/upload-auth.ts
import type { APIRoute } from 'astro';
import { getUploadAuthParams } from '@imagekit/astro/server';
export const prerender = false; // Not needed in 'server' mode
export const GET: APIRoute = () => {
const authParams = getUploadAuthParams({
privateKey: import.meta.env.IMAGEKIT_PRIVATE_KEY,
publicKey: import.meta.env.PUBLIC_IMAGEKIT_PUBLIC_KEY,
});
return new Response(JSON.stringify(authParams), {
headers: { 'Content-Type': 'application/json' },
});
};

El navegador luego solicita este endpoint y pasa los signature, token, expire, y publicKey devueltos a la función upload() de @imagekit/javascript. Instálalo como dependencia directa:

Ventana de la terminal
npm install @imagekit/javascript

Un formulario de subida minimalista en una página .astro:

src/pages/upload.astro
<input type="file" id="file-input" />
<button id="upload-btn">Upload</button>
<progress id="upload-progress" value="0" max="100"></progress>
<script>
import { upload } from '@imagekit/javascript';
const fileInput = document.getElementById('file-input') as HTMLInputElement;
const uploadBtn = document.getElementById('upload-btn') as HTMLButtonElement;
const progress = document.getElementById('upload-progress') as HTMLProgressElement;
uploadBtn.addEventListener('click', async () => {
const file = fileInput.files?.[0];
if (!file) return;
const auth = await fetch('/api/upload-auth').then((r) => r.json());
const result = await upload({
...auth,
file,
fileName: file.name,
onProgress: (e) => {
progress.value = (e.loaded / e.total) * 100;
},
});
console.log('Uploaded:', result);
});
</script>

Consulta la guía de ImageKit para manejo completo de errores y señales de aborto.

Puedes usar Astro Content Collections junto con el SDK @imagekit/nodejs para impulsar páginas de galería y listado directamente desde tu ImageKit Media Library.

Instala el Node SDK como dependencia de desarrollo:

Ventana de la terminal
npm install -D @imagekit/nodejs

Luego define una colección respaldada por client.assets.list(). El Node SDK devuelve un array de objetos File | Folder. Para limitar los resultados a imágenes, pasa type: 'file' para excluir carpetas y fileType: 'image'. Usa el type guard Files.File para que cada entrada esté correctamente tipada antes de mapearla al esquema de tu colección:

src/content.config.ts
import { defineCollection } from 'astro:content';
import { z } from 'astro/zod';
import ImageKit from '@imagekit/nodejs';
import type { Files } from '@imagekit/nodejs/resources/files/files';
const client = new ImageKit({
privateKey: import.meta.env.IMAGEKIT_PRIVATE_KEY,
});
const gallery = defineCollection({
loader: async () => {
const assets = await client.assets.list({
type: 'file', // exclude folders
fileType: 'image', // only image files
skip: 0,
limit: 50,
});
return assets
.filter((asset): asset is Files.File =>
asset.type === 'file' && !!asset.fileId && !!asset.url
)
.map((asset) => ({
id: asset.fileId ?? '',
url: asset.url ?? '',
width: asset.width ?? 0,
height: asset.height ?? 0,
name: asset.name ?? '',
tags: asset.tags ?? [],
}));
},
schema: z.object({
url: z.string().url(),
width: z.number(),
height: z.number(),
name: z.string(),
tags: z.array(z.string()),
}),
});
export const collections = { gallery };

Después de añadir la colección, ejecuta astro sync (o inicia el servidor de desarrollo) para generar los tipos de colección usados por getCollection().

Renderiza la colección con <Image> de astro:assets. La integración genera la URL del CDN de ImageKit con las transformaciones solicitadas:

src/pages/gallery.astro
---
import { Image } from 'astro:assets';
import { getCollection } from 'astro:content';
const photos = await getCollection('gallery');
---
{photos.map(({ data }) => (
<Image
src={data.url}
width={data.width}
height={data.height}
alt={data.name}
transformation={[{ width: 400, height: 300, focus: 'auto' }]}
/>
))}

Para flujos de trabajo del lado del servidor como subidas en lote, listado de assets, o eliminación de archivos, usa el SDK oficial @imagekit/nodejs directamente:

src/pages/api/upload.ts
import ImageKit from '@imagekit/nodejs';
const client = new ImageKit({
privateKey: import.meta.env.IMAGEKIT_PRIVATE_KEY,
});
await client.files.upload({
file: '<file path, buffer, or URL>',
fileName: 'sample.jpg',
});

Más guías de medios alojados

Contribuir Comunidad Patrocinar