${escapeHtml(card.eyebrow)}
-${escapeHtml(card.title)}
-${escapeHtml(card.subtitle)}
-${escapeHtml(card.accent)}
-diff --git a/apps/api-e2e/src/support/global-teardown.ts b/apps/api-e2e/src/support/global-teardown.ts index 4d45f4a..be7bce1 100644 --- a/apps/api-e2e/src/support/global-teardown.ts +++ b/apps/api-e2e/src/support/global-teardown.ts @@ -1,7 +1,7 @@ import { readFile, rm } from 'node:fs/promises'; import { resolve } from 'node:path'; -/* eslint-disable */ + const API_SERVER_PID_PATH = resolve(__dirname, '../../.api-e2e-server.pid'); module.exports = async function () { diff --git a/apps/api-e2e/src/support/test-setup.ts b/apps/api-e2e/src/support/test-setup.ts index c185541..2afb465 100644 --- a/apps/api-e2e/src/support/test-setup.ts +++ b/apps/api-e2e/src/support/test-setup.ts @@ -1,4 +1,4 @@ -/* eslint-disable */ + import axios from 'axios'; module.exports = async function () { diff --git a/apps/server/src/social-images.ts b/apps/server/src/social-images.ts index 2919f0b..24d4468 100644 --- a/apps/server/src/social-images.ts +++ b/apps/server/src/social-images.ts @@ -10,7 +10,7 @@ import { type GenerateWebsiteSocialImagesJob, promoteSocialImageRun, readSocialImageManifest, -} from '@visomi-dev/shared-social-images'; +} from '@visomi.dev/shared-social-images'; const createRedisConnection = () => { const redisUrl = process.env['REDIS_URL']?.trim(); diff --git a/apps/website/db/config.ts b/apps/website/db/config.ts index fbaf9ad..d177b21 100644 --- a/apps/website/db/config.ts +++ b/apps/website/db/config.ts @@ -1,4 +1,4 @@ -/* eslint-disable import-x/no-unresolved */ + import { column, defineDb, defineTable, NOW } from 'astro:db'; const ContactSubmission = defineTable({ diff --git a/apps/website/src/actions/index.ts b/apps/website/src/actions/index.ts index 9e63bcd..48a0724 100644 --- a/apps/website/src/actions/index.ts +++ b/apps/website/src/actions/index.ts @@ -1,4 +1,4 @@ -/* eslint-disable import-x/no-unresolved */ + import { ActionError, defineAction } from 'astro:actions'; import { ContactSubmission, db } from 'astro:db'; import { z } from 'astro/zod'; diff --git a/scripts/generate-social-images.mjs b/scripts/generate-social-images.mjs index 23bface..fc3c349 100644 --- a/scripts/generate-social-images.mjs +++ b/scripts/generate-social-images.mjs @@ -1,4 +1,4 @@ -import { copyFile, mkdir, writeFile } from 'node:fs/promises'; +import { copyFile, mkdir, readFile } from 'node:fs/promises'; import { dirname, resolve } from 'node:path'; import { fileURLToPath } from 'node:url'; @@ -14,304 +14,6 @@ const SOCIAL_IMAGE_HEIGHT = 630; const locales = ['en', 'es']; const pages = ['home', 'journey', 'projects', 'resume', 'contact']; -const socialImageContentByPage = { - contact: { - en: { - accent: 'Direct line for architecture, advisory, and product collaboration.', - cta: 'Start the conversation', - eyebrow: 'VISOMI.DEV / CONTACT', - highlights: ['Architecture consulting', 'Technical leadership', 'Fast response'], - subtitle: 'Architecture consulting, technical leadership, and high-impact product collaboration.', - title: 'Initialize connection.', - }, - es: { - accent: 'Un canal directo para conversar sobre arquitectura, producto y decisiones tecnicas clave.', - cta: 'Conversemos', - eyebrow: 'VISOMI.DEV / CONTACTO', - highlights: ['Arquitectura de software', 'Liderazgo tecnico', 'Respuesta agil'], - subtitle: 'Arquitectura de software, liderazgo tecnico y colaboracion en productos con impacto real.', - title: 'Iniciemos la conexion.', - }, - }, - home: { - en: { - accent: 'Senior engineering for products that need clear foundations and durable systems.', - cta: 'Explore the portfolio', - eyebrow: 'VISOMI.DEV / HOME', - highlights: ['Scalable platforms', 'AI workflows', 'Technical leadership'], - subtitle: 'Senior full-stack engineering, reusable architecture, and AI-enabled workflows.', - title: 'Architecting software that ships and scales.', - }, - es: { - accent: 'Ingenieria senior para productos que necesitan bases solidas, claridad tecnica y sistemas duraderos.', - cta: 'Explorar portafolio', - eyebrow: 'VISOMI.DEV / INICIO', - highlights: ['Plataformas escalables', 'Flujos con IA', 'Direccion tecnica'], - subtitle: 'Ingenieria full-stack senior, arquitectura reutilizable y flujos de trabajo potenciados por IA.', - title: 'Software listo para producir impacto y escalar.', - }, - }, - journey: { - en: { - accent: 'Work across fintech and internal platforms, guided by the architecture behind each system.', - cta: 'See the timeline', - eyebrow: 'VISOMI.DEV / JOURNEY', - highlights: ['Fintech', 'Internal platforms', 'Leadership'], - subtitle: 'A career timeline across fintech, internal platforms, product systems, and technical leadership.', - title: 'Engineering across scale, teams, and platforms.', - }, - es: { - accent: 'Un recorrido entre fintech y plataformas internas, guiado por decisiones de arquitectura con contexto.', - cta: 'Ver trayectoria', - eyebrow: 'VISOMI.DEV / TRAYECTORIA', - highlights: ['Fintech', 'Plataformas internas', 'Liderazgo tecnico'], - subtitle: 'Una trayectoria entre fintech, plataformas internas, sistemas de producto y liderazgo tecnico.', - title: 'Trayectoria en escala, equipos y plataformas.', - }, - }, - projects: { - en: { - accent: 'Editorial case studies shaped by delivery constraints, interface choices, and practical system design.', - cta: 'Open the case studies', - eyebrow: 'VISOMI.DEV / PROJECTS', - highlights: ['Fintech', 'SaaS', 'Product architecture'], - subtitle: 'Case studies across fintech, SaaS, internal tools, and scalable product architecture.', - title: 'Selected projects under real delivery constraints.', - }, - es: { - accent: 'Casos de estudio construidos desde restricciones reales, decisiones de interfaz y diseno de sistemas.', - cta: 'Ver casos de estudio', - eyebrow: 'VISOMI.DEV / PROYECTOS', - highlights: ['Fintech', 'SaaS', 'Arquitectura de producto'], - subtitle: 'Casos de estudio sobre fintech, SaaS, herramientas internas y arquitectura de producto escalable.', - title: 'Proyectos con restricciones reales de entrega.', - }, - }, - resume: { - en: { - accent: 'A focused snapshot of roles, leadership, and engineering depth across multiple product stages.', - cta: 'Review the resume', - eyebrow: 'VISOMI.DEV / RESUME', - highlights: ['Experience', 'Leadership', 'Systems thinking'], - subtitle: 'Experience, leadership, systems thinking, and delivery across multiple product stages.', - title: 'Resume and experience snapshot.', - }, - es: { - accent: 'Una vista clara de experiencia, liderazgo y criterio tecnico en distintas etapas de producto.', - cta: 'Ver experiencia', - eyebrow: 'VISOMI.DEV / EXPERIENCIA', - highlights: ['Experiencia', 'Liderazgo', 'Vision sistemica'], - subtitle: 'Experiencia, liderazgo, vision sistemica y ejecucion en distintas etapas de producto.', - title: 'Resumen de experiencia profesional.', - }, - }, -}; - -const clampText = (value, maxLength) => { - const normalizedValue = value.replace(/\s+/g, ' ').trim(); - if (normalizedValue.length <= maxLength) return normalizedValue; - return `${normalizedValue.slice(0, maxLength - 1).trimEnd()}…`; -}; - -const normalizeCard = (card, page, locale) => ({ - accent: clampText(card.accent, 96), - cta: clampText(card.cta, 26), - eyebrow: card.eyebrow, - highlights: card.highlights.map((h) => clampText(h, 28)).slice(0, 3), - locale, - page, - previewLabel: locale === 'es' ? 'vista previa' : 'preview state', - subtitle: clampText(card.subtitle, 140), - title: clampText(card.title, 72), -}); - -const escapeHtml = (value) => - value - .replace(/&/g, '&') - .replace(//g, '>') - .replace(/"/g, '"') - .replace(/'/g, '''); - -const renderHtml = (card) => { - const highlightsMarkup = card.highlights.map((h) => `${escapeHtml(h)}`).join(''); - const highlightsLabel = card.locale === 'es' ? 'claves' : 'highlights'; - - return ` - -
- - -${escapeHtml(card.eyebrow)}
-${escapeHtml(card.subtitle)}
-${escapeHtml(card.accent)}
-