Volver al blog
BunTypeScriptCódigo abiertoHacker News

HackerTube y Bun: un YouTube hecho con la curaduría de HN

01 de noviembre de 2026·6 min de lectura·Diego Horvatti

Ves un video sobre Postgres y, al día siguiente, YouTube te ofrece "10 frameworks que van a morir en 2027". HackerTube parte de esa molestia con una respuesta simple: un YouTube armado con videos recomendados por la comunidad de Hacker News. La idea aparece en el blog de Andrej Karpathy, y los detalles del proyecto están allí. Aquí quiero hablar de lo que enseña y de cómo montar tu versión con Bun.

¿Qué es HackerTube?

El concepto cabe en una frase: en lugar de que un modelo decida lo que ves, lo deciden las personas que publican, votan y comentan en HN.

Fíjate en lo que cambia. El video sigue en YouTube. El reproductor sigue en YouTube. Solo se reemplazó la capa de descubrimiento.

Y esa es la parte interesante. Solemos tratar "el feed" como si fuera el producto entero. No lo es. El feed es una consulta, y una consulta se puede reescribir.

El feed es solo una consulta. Y una consulta se puede reescribir.

Por qué la curaduría de Hacker News importa a quien programa

El algoritmo de YouTube optimiza lo que puede medir, como los clics y el tiempo de pantalla. Tiene sentido para su negocio, pero tiempo de pantalla no es lo mismo que aprender.

HN ofrece una señal distinta. Alguien pensó que el video era lo bastante bueno para publicarlo. Otras personas votaron. Después, mucha gente debatió. Una charla de 50 minutos sobre un asignador de memoria tiene una posibilidad real de subir ahí, incluso sin una miniatura con la boca abierta.

Hay otra ventaja que me parece subestimada: la señal es legible. Ves los puntos y abres los comentarios. Muchas veces, el debate vale tanto como el video, porque alguien que trabajó en el tema aparece para corregir al ponente.

Ahora bien, sin romantizar. HN tiene sus vicios:

  • Tiene un sesgo fuerte: inglés, Silicon Valley, startups, Rust y nostalgia por las computadoras antiguas.
  • Un voto no prueba que la persona haya visto el video. Mucha gente vota por el título.
  • Los puntos dependen del horario y de la suerte. Un video excelente puede morir en la cola de novedades.

O sea, cambias un sesgo opaco por uno visible. Yo me quedo con el visible, porque se puede compensar un sesgo que ves.

Cómo montar tu versión con Bun

Lo que sigue es mi versión, no la implementación del proyecto original. Elegí Bun por un motivo sin glamour: ejecuta TypeScript directamente, ya trae fetch, servidor HTTP y SQLite, y no necesita configuración. Para un proyecto de una tarde, eso es lo que importa.

La API pública de búsqueda de HN, mantenida por Algolia, no pide clave. Se pueden filtrar historias por URL y puntuación:

// coleta.ts
const url = new URL("https://hn.algolia.com/api/v1/search");
url.searchParams.set("query", "youtube.com");
url.searchParams.set("restrictSearchableAttributes", "url");
url.searchParams.set("tags", "story");
url.searchParams.set("numericFilters", "points>=100");
url.searchParams.set("hitsPerPage", "200");

function extrairId(link: string): string | null {
  if (!URL.canParse(link)) return null;
  const u = new URL(link);
  if (u.hostname === "youtu.be") return u.pathname.slice(1) || null;
  return u.searchParams.get("v");
}

const { hits } = await fetch(url).then((r) => r.json());

const videos = hits.flatMap((h: any) => {
  const id = extrairId(h.url ?? "");
  if (!id) return [];
  return [{
    id,
    titulo: h.title,
    pontos: h.points,
    comentarios: h.num_comments,
    criadoEm: h.created_at_i,
    hn: `https://news.ycombinator.com/item?id=${h.objectID}`,
  }];
});

await Bun.write("videos.json", JSON.stringify(videos, null, 2));

Ejecútalo con bun coleta.ts y listo, ya tienes un archivo JSON.

Enseguida aparecen tres trampas:

  • Enlaces cortos: la búsqueda por youtube.com no encuentra youtu.be. Haz una segunda consulta y une los resultados.
  • Duplicados: el mismo video se publica varias veces a lo largo de los años. Agrupa por id y suma los puntos.
  • Paginación: la búsqueda no devuelve todo el historial de una vez. Divídelo por período, filtrando created_at_i en numericFilters.

Ranking: los puntos solos no bastan

Si ordenas solo por puntos, la parte de arriba se convierte en un museo. Los mismos clásicos se quedan ahí para siempre.

Se puede robar la idea del propio HN: una fórmula que penaliza la antigüedad. Para un archivo de videos, sin embargo, la penalización debe ser mucho más leve, porque una buena charla no caduca como una noticia:

function nota(v: { pontos: number; comentarios: number; criadoEm: number }) {
  const anos = (Date.now() / 1000 - v.criadoEm) / (365 * 24 * 3600);
  const engajamento = v.pontos + v.comentarios * 0.5;
  return engajamento / Math.pow(anos + 2, 0.5);
}

Aquí los pesos son a ojo, y lo digo sin vergüenza. Un comentario vale medio punto porque indica debate, pero también puede indicar pelea. El exponente 0.5 solo evita que 2012 domine la página. Ajústalo mirando el resultado, no una hoja de cálculo.

Este es el mejor efecto secundario de tener tu propio feed: la regla de recomendación se convierte en diez líneas que lees, cambias y versionas en Git. Intenta hacer eso con el algoritmo de YouTube.

Servirlo todo: ¿necesitas backend?

En la mayoría de los casos, no. Un videos.json generado por un cron y una página estática resuelven el problema. Si quieres un servidor local, Bun lo hace sin dependencias:

// server.ts
const videos = await Bun.file("videos.json").json();

Bun.serve({
  port: 3000,
  fetch() {
    const cards = videos.map((v: any) => `
      <article>
        <a href="https://www.youtube.com/watch?v=${v.id}">
          <img loading="lazy" alt=""
            src="https://img.youtube.com/vi/${v.id}/hqdefault.jpg">
        </a>
        <h2>${Bun.escapeHTML(v.titulo)}</h2>
        <a href="${v.hn}">${v.pontos} puntos, ${v.comentarios} comentarios</a>
      </article>`);

    return new Response(cards.join(""), {
      headers: { "Content-Type": "text/html; charset=utf-8" },
    });
  },
});

Fíjate en el Bun.escapeHTML del título. Ese contenido viene de internet, así que nunca confíes en él al montar HTML. Hasta un proyecto de juguete merece ese cuidado.

Si el juego crece, con filtro por tema o una marca de "ya lo vi", bun:sqlite entra sin que instales nada. Antes de eso, es colección de JSON y felicidad.

Una advertencia: no descargues videos, no los alojes y no hagas scraping de YouTube. Enlaza o usa el reproductor integrado oficial. Así el creador sigue recibiendo la visualización, y tu proyecto no se convierte en un dolor de cabeza con los términos de uso.

Qué cambia esto en tu flujo de trabajo

Nadie va a dejar YouTube por esto. Yo tampoco. La ganancia real es otra.

Primero, consigues una mejor cola de estudio. En lugar de abrir la app y aceptar lo que venga, abres una lista filtrada por gente a la que le importa el tema.

Segundo, el patrón sirve para otras fuentes. Cambia HN por Lobsters, por los enlaces del Slack de tu equipo o por la newsletter a la que estás suscrito. El diseño es el mismo: recopilar enlaces, extraer señal, ordenar y mostrar.

Tercero, la barrera de entrada bajó. Una herramienta personal de este tipo tiene menos de 100 líneas. Con un asistente de código, sale en una tarde. El software hecho para un solo usuario, tú mismo, por fin compensa el esfuerzo.

Mi opinión sobre HackerTube

Me gusta HackerTube por lo que cuestiona, más que por lo que es. La recomendación que consumimos todos los días se diseñó para el objetivo de otra empresa. Cambiar esa capa no exige un producto nuevo ni un equipo de machine learning. Exige una API pública, un archivo JSON y media docena de decisiones tuyas.

Esto no va a arreglar internet. Solo te va a ahorrar "10 frameworks que van a morir". Para una tarde de trabajo, ya es un gran negocio. Si te gusta este tipo de herramienta pequeña y útil, hay más cosas así en mis proyectos.

Resumen para LinkedIn

YouTube te muestra un video sobre Postgres y, al día siguiente, te ofrece "10 frameworks que van a morir en 2027".

El feed parece el producto entero, pero es solo una consulta. Y una consulta se puede reescribir.

Eso fue lo que me llamó la atención de HackerTube, una idea que apareció en el blog de Andrej Karpathy: lo que ves lo deciden las personas que publican, votan y debaten en Hacker News, no un modelo optimizado para el tiempo de pantalla.

HN tiene sus vicios, claro. Pero prefiero un sesgo que veo a un sesgo oculto, porque el visible se puede compensar.

Monté mi versión con Bun: API pública, un archivo JSON y un ranking de diez líneas que leo, cambio y versiono en Git. Menos de 100 líneas, una tarde de trabajo.

Escribí el paso a paso con el código completo en el artículo. Si tú también quieres recuperar el control de lo que ves, vale la pena leerlo.

#Bun #TypeScript #HackerNews #Programación #Desarrollo