Buscador de empleo open source que indexa 3.3M+ vacantes IT en vivo directamente desde las career pages y ATS de las empresas: sin recruiters, sin reposts, sin links muertos. Todo normalizado, deduplicado y buscable con facetas. MIT y self-hosteable.
Un motor de búsqueda de empleo que crawlea la fuente original: la página de carreras o el ATS de cada empresa. No es un agregador que repite lo que otro agregador publicó.
Straight from the source: Workday, Greenhouse, Lever, Ashby, iCIMS y una cola larga de ATS. Cada listing enlaza al posting original.
Un schema, deduplicado: el mismo rol publicado en tres boards colapsa en una sola entrada, con clave estable.
Búsqueda que entiende empleos: full-text con facetas por región, modalidad, seniority, skills y salario, derivadas de diccionarios curados (no adivinadas).
Realmente abierto: MIT, pipeline y datos en abierto, self-hosteable.
Construible encima: API HTTP pública, CLI, digests de Telegram y un workspace completo.
Escala del catálogo (snapshot 2026-10-20)
3,371,563 vacantes únicas · 477,323 empresas · 320 fuentes (304 con postings ese día).
Los reposts entre boards se colapsan, así que la cifra refleja lo que realmente muestra freehire.me/jobs.
De dónde salen las vacantes
Tipo de fuente
Plataformas con postings
Vacantes abiertas
ATS platforms
117
2,936,676
Aggregators & job boards (incl. 97 canales de Telegram)
133
444,654
Company career sites (Amazon, Apple, Google, Yandex, Sber…)
52
23,293
🧰 Qué hay más allá del catálogo
Fase
Funciones
Find
Búsqueda facetada, colecciones curadas, búsquedas guardadas con digests por email/Telegram, boards compartidos, analytics de mercado, señal de ghost job
Apply
CV builder con templates PDF ATS-safe, scoring determinista CV↔vacante, análisis de fit con IA, tailoring que no inventa nada, tracer links, referidos
Track
Board de aplicaciones con etapas, inbox que vincula respuestas de recruiters a su aplicación, ledger de eventos append-only, recordatorios
Ask
Agente in-process con cinco presets: chat, browse, profile, CV tailoring, interview rehearsal
Build on
API pública sin API key, CLI, MCP server para Claude Desktop/Code, extensión de Chrome, ChatGPT Actions
🏗️ Stack
Capa
Tecnología
Backend
Go + Fiber v2
Base de datos
PostgreSQL + pgvector (filtros y embeddings semánticos)
Acceso a datos
sqlc (SQL tipado, sin ORM)
Búsqueda
Meilisearch (full-text + facetas)
LLM
langchaingo sobre cualquier endpoint compatible con OpenAI
Gateway LLM
Bifrost (virtual keys por usuario, fallback entre providers, spend tracking)
# api + web + postgres + meilisearch + redis + s3make up# Verificarcurl localhost:8080/healthcurl localhost:8080/api/v1/jobs
Si el puerto 8080 está ocupado:
HIRE_HOST_PORT=8090 make up
Migraciones y volúmenes
Las migraciones corren solas al inicializar el volumen de Postgres por primera vez. Si cambias una migración y el volumen ya existe, no se re-aplica: recrea con docker compose down -v && make up, o aplica pendientes con make migrate.
Desarrollo local
# Solo la base de datosdocker compose up -d db# Servidor en el host, leyendo DATABASE_URLmake run
Copiar .env.example a .env. JWT_SECRET es obligatorio para arrancar; OAuth y credenciales LLM son opcionales (sus features quedan deshabilitadas si faltan).
🧰 Comandos
Comando
Para qué
make help
Listar todos los comandos
make up
Build + start de todo el stack
make sqlc
Regenerar código desde SQL (vía Docker)
make tidy
go mod tidy
make psql
psql dentro del contenedor
make reindex
Rebuild del índice de Meilisearch desde Postgres
make migrate
Aplicar migraciones a un volumen existente
⚙️ Workers
El server solo sirve la API. Todo lo demás — crawl, enriquecimiento, indexado, notificaciones — son workers standalone de una sola corrida, pensados para cron:
go run ./cmd/migrate # migraciones pendientes (antes de deployar código nuevo)go run ./cmd/ingest greenhouse # crawlear un provider y hacer upsertgo run ./cmd/enrich # drenar cola de enriquecimiento LLMgo run ./cmd/embed # drenar cola semántica hacia pgvectorgo run ./cmd/search-drain # empujar writes al índice (cada 1-2 min)go run ./cmd/reindex # rebuild completo de Meilisearchgo run ./cmd/tg-ingest # crawlear canales activos de Telegramgo run ./cmd/tg-extract # extraer vacantes de posts con LLMgo run ./cmd/capture-apply-form # capturar formularios ATS encoladosgo run ./cmd/backfill-derive # re-derivar facetas, fingerprints y slugs
Todos necesitan DATABASE_URL y salen con código distinto de cero si fallan. Ningún worker borra jobs: el ciclo de vida solo los cierra suavemente (soft-close).
🗂️ Layout del repo
cmd/ server + workersmigrations/ schema SQL (fuente para sqlc e initdb)web/ frontend SvelteKitextension/ extensión Chrome (side panel)design-system/ tokens y componentes compartidosinternal/ ~130 paquetes de dominio sources/ adapters por ATS + registry boardcatalog/ qué empresa se crawlea en qué ATS y con qué board id pipeline/ ingest: fetch → normalize → dedup → upsert search/ indexado y query en Meilisearch embed/ embeddings hacia pgvector ghost/ señal de "¿esta vacante es real?" cv/ cvedit/ CVs estructurados + render PDF cvmatch/ scoring determinista CV↔vacante assistant/ agente in-process: loop, tools, transcripts
La arquitectura completa (topología crawl-to-search, auth, notificaciones, ciclo de vida del job) está en docs/architecture.md. Cada paquete tiene su propio AGENTS.md.
Jobs y companies se direccionan por slug público. La referencia completa — endpoints, parámetros, auth y vocabulario de filtros — está en freehire.me/docs/api.
➕ Agregar una fuente
Agregar una empresa: una fila en el catálogo boards (company + provider + board), vía el formulario “contribute a board” del sitio o con go run ./cmd/add-board.
Agregar una plataforma ATS: un adapter nuevo en internal/ingest/sources + una línea en sources.All. Todos hablan la misma interfaz Source; el board se valida contra el registry antes del crawl.
Para la mayoría de empresas el ATS ya está soportado, así que agregarlas es solo una fila.
🧩 Frontend y extensión
Web: SvelteKit 2 server-rendered (adapter-node) bajo web/, consume la API same-origin.
Design system: paquete hermano enlazado por symlink, no copiado. Instalarlo antes de buildear web/ o extension/.
Extensión Chrome: side panel junto al posting; lee la página, muestra skill-coverage contra tu perfil de freehire y puede llenar el formulario. Disponible en la Chrome Web Store.
⚠️ Notas prácticas
No es solo un job board: es un producto full-stack con API, CLI, MCP, extensión y agente propio. Buen repo de referencia para arquitectura Go + SvelteKit.
LLM opcional: las features de IA dependen de configurar LLM_*; sin eso, el catálogo y la búsqueda siguen funcionando.
Self-host con datos: el crawl consume recursos y las fuentes pueden tener sus propios ToS. Revisar antes de correrlo a escala.
MCP server aparte:freehire-mcp conecta el catálogo a Claude Desktop/Code.
Calidad de datos: las facetas salen de diccionarios curados; si un campo no se puede derivar, se emite vacío en vez de adivinar.
🔗 Enlaces relacionados
📊 CodeGraph — para explorar este repo (Go + SvelteKit) sin leer archivo por archivo.