From e14d089ee8ff781eec1a3b284ac9486e9332a334 Mon Sep 17 00:00:00 2001 From: Michael Villalba Sotelo Date: Fri, 10 Apr 2026 10:37:10 -0600 Subject: [PATCH] fix(server): remove legacy /og/ route and related files - Remove the /og/:locale/:page/ redirect from the gateway server - Delete apps/website/src/pages/og (legacy OG image page renderer) - Delete apps/website/src/content/og-content.ts (its data source) - The canonical og:image URLs are now /images/seo/:locale/:page.png --- apps/server/src/main.ts | 17 - apps/website/src/content/og-content.ts | 107 ------ .../src/pages/og/[locale]/[page].astro | 311 ------------------ 3 files changed, 435 deletions(-) delete mode 100644 apps/website/src/content/og-content.ts delete mode 100644 apps/website/src/pages/og/[locale]/[page].astro diff --git a/apps/server/src/main.ts b/apps/server/src/main.ts index 4cd7957..9d8d10e 100644 --- a/apps/server/src/main.ts +++ b/apps/server/src/main.ts @@ -13,11 +13,6 @@ type AstroMiddlewareModule = { handler?: (req: Request, res: Response, next: NextFunction) => Promise | void; }; -const supportedSocialImageLocales = new Set(['en', 'es']); -const supportedSocialImagePages = new Set(['contact', 'home', 'journey', 'projects', 'resume']); - -const readRouteParam = (value: string | string[] | undefined) => (typeof value === 'string' ? value : null); - const host = process.env.HOST ?? '0.0.0.0'; const port = process.env.PORT ? Number(process.env.PORT) : 8080; @@ -88,18 +83,6 @@ const bootstrap = async () => { app.use('/images/seo', socialImageRuntime.staticMiddleware); } - app.get('/og/:locale/:page/', (req: Request, res: Response, next: NextFunction) => { - const locale = readRouteParam(req.params['locale']); - const page = readRouteParam(req.params['page']); - - if (!locale || !page || !supportedSocialImageLocales.has(locale) || !supportedSocialImagePages.has(page)) { - next(); - return; - } - - res.redirect(301, `/images/seo/${locale}/${page}.png`); - }); - app.use('/api', apiApp); app.use( express.static(astroClientFolder, { diff --git a/apps/website/src/content/og-content.ts b/apps/website/src/content/og-content.ts deleted file mode 100644 index 4dfd545..0000000 --- a/apps/website/src/content/og-content.ts +++ /dev/null @@ -1,107 +0,0 @@ -import type { Locale, PageId } from '../i18n/translations'; - -type OgContent = { - accent: string; - cta: string; - eyebrow: string; - highlights: string[]; - subtitle: string; - title: string; -}; - -const ogContentByPage: Record> = { - 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: 'Canal directo para arquitectura, advisory y colaboracion de producto.', - cta: 'Iniciar conversacion', - eyebrow: 'VISOMI.DEV / CONTACTO', - highlights: ['Consultoria tecnica', 'Liderazgo', 'Respuesta rapida'], - subtitle: 'Consultoria de arquitectura, liderazgo tecnico y colaboracion en productos de alto impacto.', - 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 claras y sistemas duraderos.', - cta: 'Explorar portafolio', - eyebrow: 'VISOMI.DEV / INICIO', - highlights: ['Plataformas escalables', 'Flujos con IA', 'Liderazgo tecnico'], - subtitle: 'Ingenieria full-stack senior, arquitectura reutilizable y flujos de trabajo potenciados por IA.', - title: 'Software pensado para salir a produccion y escalar.', - }, - }, - journey: { - en: { - accent: 'From fintech to internal platforms, with the architecture decisions behind the work.', - 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 journey through scale, teams, and platforms.', - }, - es: { - accent: 'De fintech a plataformas internas, con las decisiones de arquitectura detras del trabajo.', - cta: 'Ver la linea de tiempo', - eyebrow: 'VISOMI.DEV / TRAYECTORIA', - highlights: ['Fintech', 'Plataformas internas', 'Liderazgo'], - subtitle: 'Una linea de tiempo entre fintech, plataformas internas, sistemas de producto y liderazgo tecnico.', - title: 'Trayectoria en escala, equipos y plataformas.', - }, - }, - projects: { - en: { - accent: 'Editorial case studies covering delivery constraints, interface decisions, and 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 built with real delivery constraints.', - }, - es: { - accent: 'Casos de estudio editoriales con restricciones reales, decisiones de interfaz y diseno de sistemas.', - cta: 'Abrir casos de estudio', - eyebrow: 'VISOMI.DEV / PROYECTOS', - highlights: ['Fintech', 'SaaS', 'Arquitectura de producto'], - subtitle: 'Casos de estudio en fintech, SaaS, herramientas internas y arquitectura de producto escalable.', - title: 'Proyectos seleccionados construidos 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: 'Un resumen claro de experiencia, liderazgo y profundidad tecnica en distintas etapas de producto.', - cta: 'Revisar curriculum', - eyebrow: 'VISOMI.DEV / CURRICULUM', - highlights: ['Experiencia', 'Liderazgo', 'Pensamiento sistemico'], - subtitle: 'Experiencia, liderazgo, pensamiento sistemico y ejecucion a traves de multiples etapas de producto.', - title: 'Resumen de experiencia profesional.', - }, - }, -}; - -const getOgContent = (page: PageId, locale: Locale) => ogContentByPage[page][locale]; - -export { getOgContent }; diff --git a/apps/website/src/pages/og/[locale]/[page].astro b/apps/website/src/pages/og/[locale]/[page].astro deleted file mode 100644 index 03c8170..0000000 --- a/apps/website/src/pages/og/[locale]/[page].astro +++ /dev/null @@ -1,311 +0,0 @@ ---- -export const prerender = true; - -import { getOgContent } from '../../../content/og-content'; -import type { Locale, PageId } from '../../../i18n/translations'; - -type OgViewModel = { - accent: string; - cta: string; - eyebrow: string; - highlights: string[]; - subtitle: string; - title: string; -}; - -type Params = { - locale: Locale; - page: PageId; -}; - -export const getStaticPaths = () => - (['en', 'es'] as const satisfies readonly Locale[]).flatMap((locale) => - (['home', 'journey', 'projects', 'resume', 'contact'] as const satisfies readonly PageId[]).map( - (page) => ({ params: { locale, page } } satisfies { params: Params }), - ), - ); - -const { locale, page } = Astro.params as Params; -const content = getOgContent(page, locale) as OgViewModel; -const accent = content.accent; -const cta = content.cta; -const eyebrow = content.eyebrow; -const highlights: string[] = content.highlights; -const subtitle = content.subtitle; -const title = content.title; ---- - - - - - - - {content.title} - - - -
-
-
-

{eyebrow}

-

{title}

-

{subtitle}

-

{accent}

-
- - {cta} -
-
- - -
- - -
- -