Skip to main content

public 3d-motion repository

cv-santiago

// santifer/cv-santiago

Interactive CV with AI chat integration. Built with React 19, TypeScript, Claude API. Chat with my AI avatar about my experience.

$ git log --oneline --stat
stars:627forks:238updated:2026-06-05
README.md
readonly

santifer.io

:gb: English | :es: Español

Interactive portfolio with AI chatbot (text + voice), agentic RAG, 71 automated evals, LLMOps dashboard, and 6-layer prompt injection defense

Live Demo Built with Claude Code


santifer.io in motion


The Problem

Static CVs don't show what you can actually build. A PDF lists skills — it doesn't prove them.

The Solution

A production-grade interactive portfolio that demonstrates the skills it describes: dual-mode AI chatbot (text + voice) with agentic RAG, full LLMOps observability with custom dashboard, 71 automated evals as CI gate, prompt versioning, and a closed-loop that generates tests from production failures.

Key Features:

  • AI Chatbot "Santi" — Text (Claude Sonnet) + Voice (OpenAI Realtime API). Responds in first person as Santiago. Agentic RAG with hybrid search (pgvector + BM25) and Haiku reranking
  • 6-Layer Defense — Keyword detection, canary tokens, fingerprinting, anti-extraction, online safety scoring, adversarial red team. Real-time jailbreak email alerts
  • 71 Automated Evals — 10 categories: factual accuracy, persona, boundaries, quality, safety, language, RAG quality, multi-turn, source badges, voice quality. CI gate on every push
  • LLMOps Dashboard — Private /ops with 8 tabs: Overview, Conversations, Costs, RAG, Security, Evals, Voice, System. Real data from Langfuse + Supabase
  • Closed Loop — Trace → online scoring → quality < 0.7 → auto-generate test → CI gate blocks deploy
  • Voice Mode — OpenAI Realtime API, audio-to-audio, shared RAG pipeline, ~$0.25/session
  • 6 Published Case Studies — Bilingual (ES/EN) with JSON-LD, prerendered HTML, cross-linked RAG, and interactive architecture diagrams
  • Interactive Architecture Diagram — GSAP-animated SVG with narrated audio, pan/zoom, dark mode sync. Explore it →
  • GEO-readyllms.txt, structured data (JSON-LD), AI crawler-friendly robots.txt

Tech Stack

React TypeScript Vite Tailwind Claude OpenAI Langfuse Supabase Vercel Recharts


Chatbot Architecture

Interactive Architecture Diagram

Explore the interactive diagram → 10 phases · narrated audio · zoom + pan

User message → FloatingChat.tsx → api/chat.js (Vercel Edge)
                                    ├── System prompt (Langfuse registry + fallback)
                                    ├── Claude Sonnet (tool_use decision)
                                    ├── Agentic RAG (if needed):
                                    │     ├── OpenAI embeddings (text-embedding-3-small)
                                    │     ├── Supabase pgvector (semantic) + full-text (BM25)
                                    │     └── Claude Haiku (reranking + diversification)
                                    ├── Claude Sonnet (streaming generation)
                                    ├── Langfuse tracing (every span with cost)
                                    └── waitUntil → Haiku scoring (0ms added latency)

Voice mode → useVoiceMode.ts → api/voice-token.js → OpenAI Realtime WebSocket
                                  └── api/rag-search.js (function calling for RAG)

Key Files

FilePathDescription
Chat edge functionapi/chat.jsMain chatbot — RAG, tracing, scoring, streaming, defense
RAG pipelineapi/_shared/rag.jsHybrid search, reranking, cost tracking, intent classification
Prompt managementapi/_shared/prompt.jsLangfuse prompt registry with file fallback
Voice tokenapi/voice-token.jsOpenAI Realtime ephemeral token + rate limiting
Voice RAGapi/rag-search.jsRAG search for voice mode function calling
Voice traceapi/voice-trace.jsVoice session tracing with cost estimation
Chat widgetsrc/FloatingChat.tsxReact widget — streaming SSE, quick prompts, contact CTA
Voice hooksrc/useVoiceMode.tsWebSocket management, audio capture, transcript persistence
System promptchatbot-prompt.txtFallback prompt (production uses Langfuse v5)

LLMOps Dashboard (/ops)

Private, password-protected dashboard with 8 tabs showing real production data:

TabWhat it showsData source
OverviewKPIs, timelines, donuts, intent distributionLangfuse traces
ConversationsFilter + list + detail with spans, cost, latency, scoresLangfuse traces + observations
CostsBreakdown per component (toolDecision/embedding/reranking/generation/voice)trace.metadata.cost
RAGActivation rate, chunks per articleLangfuse tags + Supabase
SecurityDefense funnel, safety distribution, jailbreak listLangfuse tags + scores
EvalsPass rates by category (embedded from real eval reports)evals/results/ via build
VoiceSessions, text/voice split, latency P50/P95, cost per minuteLangfuse tags
SystemPrompt versions, RAG document stats, model pricingLangfuse prompts API + Supabase

Dashboard API Layer

EndpointPathDescription
Authapi/ops/auth.jsLogin (validates OPS_DASHBOARD_SECRET)
Statsapi/ops/stats.jsAggregated stats, server-side compute from traces
Tracesapi/ops/traces.jsList traces with filters (lang, mode, RAG, jailbreak)
Trace detailapi/ops/trace/[id].jsFull trace with observations, scores, Langfuse link
Evalsapi/ops/evals.jsEval results embedded from build
Promptsapi/ops/prompts.jsPrompt versions from Langfuse
RAG statsapi/ops/rag-stats.jsDocument stats from Supabase

Evals & Testing

71 automated tests across 10 categories. ~70% deterministic (contains, regex, word count), ~30% LLM-as-Judge (Haiku).

CategoryTestsType
factual_accuracy9Deterministic
persona_adherence4Deterministic
boundary_testing7Deterministic
response_quality7Mixed
safety_jailbreak7Deterministic
language_handling5Deterministic
rag_quality16Mixed
multi_turn5Mixed
source_badges5Deterministic
voice_quality6Mixed

Scripts & CLI Tools

All scripts live in scripts/ and run via npm run:

Chatbot Operations

CommandScriptDescription
npm run evalsevals/runner.tsRun 71 automated evals
npm run adversarialscripts/adversarial-test.tsRed team: 20+ auto-generated attacks
npm run chatsscripts/chats.tsView last 50 conversations from Langfuse
npm run chats -- --fullscripts/chats.tsFull conversations with messages
npm run chats -- --jailbreakscripts/chats.tsOnly jailbreak attempts
npm run evaluate-tracesscripts/evaluate-traces.tsBatch eval with Haiku (quality, safety, intent)
npm run diagnose:ragscripts/diagnose-rag.tsRAG quality diagnostic — detects retrieval misses

Prompt & RAG Management

CommandScriptDescription
npm run prompt:syncscripts/sync-prompt-to-langfuse.tsSync prompt to Langfuse (hash-based, skip if unchanged)
npm run prompt:regressionscripts/prompt-regression.tsCompare two prompt versions side by side
npm run rag:syncscripts/export-chunks.ts + scripts/ingest-rag.tsRe-export articles + ingest to Supabase

Contract & Integration Tests

CommandScriptDescription
npm run test:contracttests/ops-contract.test.tsValidate trace metadata matches dashboard contract (67 tests)
npm run test:opstests/ops-dashboard.test.tsTest all 7 dashboard API endpoints (102 tests)

Build Pipeline

CommandScriptDescription
npm run build(chained)rag:sync → prompt:sync → embed-evals → reddit-stats → tsc → vite → sitemap → validate → prerender
scripts/embed-evals.tsParse eval reports → embed in dashboard
scripts/generate-sitemap.tsGenerate sitemap.xml with lastmod
scripts/validate-articles.tsSEO validation (dates, keywords, OG images)
scripts/validate-llms-txt.tsValidate llms.txt consistency
scripts/prerender.tsxSSR prerender all pages with critical CSS
scripts/indexnow-ping.tsPing Bing/Yandex on deploy

Quick Start

git clone https://github.com/santifer/cv-santiago.git
cd cv-santiago
npm install
npm run dev

Open localhost:5173

Environment Variables

# Core
ANTHROPIC_API_KEY=           # Claude API (chatbot)
OPENAI_API_KEY=              # Embeddings + Voice

# RAG
SUPABASE_URL=                # Supabase project URL
SUPABASE_SERVICE_ROLE_KEY=   # Supabase service key

# Observability
LANGFUSE_PUBLIC_KEY=         # Langfuse tracing
LANGFUSE_SECRET_KEY=         # Langfuse tracing

# Alerts & Dashboard
RESEND_API_KEY=              # Jailbreak email alerts
OPS_DASHBOARD_SECRET=        # Dashboard password (/ops)

Project Structure

src/
├── App.tsx                  # Full CV — all sections
├── FloatingChat.tsx         # Chat widget (text mode)
├── useVoiceMode.ts          # Voice mode hook (OpenAI Realtime)
├── VoiceOrb.tsx             # Voice UI (orb + transcript)
├── GlobalNav.tsx            # Navigation with breadcrumbs
├── main.tsx                 # React Router + lazy loading
├── i18n.ts                  # Bilingual translations
├── articles/
│   ├── registry.ts          # Centralized article config
│   ├── components.tsx       # Shared article components
│   └── json-ld.ts           # JSON-LD builder
├── ops/                     # LLMOps Dashboard
│   ├── OpsDashboard.tsx     # Shell + Overview tab
│   ├── OpsAuth.tsx          # Login screen
│   ├── types.ts             # Shared TypeScript interfaces
│   ├── hooks/               # useOpsApi, useTraces
│   ├── components/          # KpiCard, MetricChart, FilterBar, etc.
│   └── tabs/                # Conversations, Costs, Security, Evals, etc.
├── [Article].tsx             # Case study components (5 articles)
└── [article]-i18n.ts         # Bilingual content per article

api/
├── chat.js                  # Main chatbot edge function
├── voice-token.js           # Voice ephemeral token + rate limit
├── voice-trace.js           # Voice session tracing
├── rag-search.js            # RAG for voice function calling
├── _shared/
│   ├── rag.js               # RAG pipeline (search, rerank, cost)
│   ├── prompt.js            # Prompt versioning (Langfuse)
│   └── ops-auth.js          # Dashboard auth helper
└── ops/                     # Dashboard API proxy layer
    ├── auth.js              # Login
    ├── stats.js             # Aggregated stats
    ├── traces.js            # Trace list with filters
    ├── trace/[id].js        # Trace detail
    ├── evals.js             # Eval results
    ├── prompts.js           # Prompt versions
    └── rag-stats.js         # RAG document stats

evals/
├── datasets/                # 10 JSON datasets (71 test cases)
├── assertions.ts            # Deterministic assertions
├── llm-judge.ts             # LLM-as-Judge (Haiku)
└── runner.ts                # Eval runner

scripts/                     # See "Scripts & CLI Tools" section above
tests/
├── ops-contract.test.ts     # Contract tests (67 assertions)
└── ops-dashboard.test.ts    # Dashboard API tests (102 assertions)

chatbot-prompt.txt           # System prompt (fallback, prod uses Langfuse)

Case Studies

ArticleSlugsType
Self-Healing Chatbot/chatbot-que-se-cura-solo /self-healing-chatbotcase-study
Career-Ops/career-ops /career-ops-systemcase-study
Jacobo AI Agent/agente-ia-jacobo /ai-agent-jacobocase-study
Business OS/business-os-para-airtable /business-os-for-airtablecase-study
Programmatic SEO/seo-programatico /programmatic-seocase-study
n8n for PMs/n8n-para-pms /n8n-for-pmscollab
Santifer iRepair/santifer-irepair /santifer-irepair-founderbridge

Cost

  • <$0.005 per text conversation (5 models in the pipeline)
  • ~$0.25 per voice session (OpenAI Realtime)
  • $0 infrastructure (free tiers: Vercel, Supabase, Langfuse)
  • ~$30/month estimated at 200 conversations/day

License

MIT



:es: Versión en Español

Portfolio interactivo con chatbot IA (texto + voz), RAG agéntico, 71 evals automatizados, dashboard LLMOps y defensa anti-inyección en 6 capas

Demo en vivo


santifer.io en movimiento


El Problema

Los CVs estáticos no demuestran lo que realmente sabes construir. Un PDF lista habilidades — no las prueba.

La Solución

Un portfolio interactivo de nivel producción que demuestra las habilidades que describe: chatbot IA dual (texto + voz) con RAG agéntico, observabilidad LLMOps completa con dashboard custom, 71 evals automatizados como CI gate, versionado de prompts, y un closed-loop que genera tests de fallos en producción.

Funcionalidades:

  • Chatbot IA "Santi" — Texto (Claude Sonnet) + Voz (OpenAI Realtime API). Responde en primera persona como Santiago. RAG agéntico con búsqueda híbrida (pgvector + BM25) y reranking con Haiku
  • Defensa en 6 capas — Keyword detection, canary tokens, fingerprinting, anti-extraction, online safety scoring, adversarial red team. Alertas de jailbreak por email en tiempo real
  • 71 Evals automatizados — 10 categorías: factual, persona, boundaries, quality, safety, language, RAG, multi-turn, source badges, voice. CI gate en cada push
  • Dashboard LLMOps/ops privado con 8 pestañas: Overview, Conversations, Costs, RAG, Security, Evals, Voice, System. Datos reales de Langfuse + Supabase
  • Closed Loop — Traza → scoring online → quality < 0.7 → auto-genera test → CI gate bloquea deploy
  • Modo voz — OpenAI Realtime API, audio-to-audio, mismo pipeline RAG, ~$0.25/sesión
  • 6 Case Studies publicados — Bilingües (ES/EN) con JSON-LD, HTML prerenderizado, RAG cross-linked y diagramas de arquitectura interactivos
  • Diagrama de Arquitectura Interactivo — SVG animado con GSAP, audio narrado, pan/zoom, sync dark mode. Explorar →
  • GEO-readyllms.txt, datos estructurados (JSON-LD), robots.txt amigable con crawlers IA

Stack Técnico

React TypeScript Vite Tailwind Claude OpenAI Langfuse Supabase Vercel Recharts


Arquitectura del Chatbot

Diagrama Interactivo de Arquitectura

Explorar el diagrama interactivo → 10 fases · audio narrado · zoom + pan

Mensaje → FloatingChat.tsx → api/chat.js (Vercel Edge)
                               ├── System prompt (Langfuse registry + fallback)
                               ├── Claude Sonnet (decisión tool_use)
                               ├── RAG Agéntico (si necesario):
                               │     ├── OpenAI embeddings (text-embedding-3-small)
                               │     ├── Supabase pgvector (semántico) + full-text (BM25)
                               │     └── Claude Haiku (reranking + diversificación)
                               ├── Claude Sonnet (generación streaming)
                               ├── Langfuse tracing (cada span con coste)
                               └── waitUntil → Haiku scoring (0ms de latencia añadida)

Modo voz → useVoiceMode.ts → api/voice-token.js → OpenAI Realtime WebSocket
                                └── api/rag-search.js (function calling para RAG)

Archivos Clave

ArchivoRutaDescripción
Chat edge functionapi/chat.jsChatbot principal — RAG, tracing, scoring, streaming, defensa
Pipeline RAGapi/_shared/rag.jsBúsqueda híbrida, reranking, coste, clasificación de intención
Gestión de promptapi/_shared/prompt.jsLangfuse prompt registry con fallback local
Token de vozapi/voice-token.jsToken efímero OpenAI Realtime + rate limiting
RAG vozapi/rag-search.jsBúsqueda RAG para function calling de voz
Trace vozapi/voice-trace.jsTracing de sesiones de voz con estimación de coste
Widget chatsrc/FloatingChat.tsxWidget React — streaming SSE, quick prompts, CTA de contacto
Hook de vozsrc/useVoiceMode.tsGestión WebSocket, captura audio, persistencia de transcript
System promptchatbot-prompt.txtPrompt fallback (producción usa Langfuse v5)

Dashboard LLMOps (/ops)

Dashboard privado protegido por contraseña con 8 pestañas mostrando datos reales:

PestañaQué muestraFuente de datos
OverviewKPIs, timelines, donuts, distribución de intentsTrazas Langfuse
ConversationsFiltros + lista + detalle con spans, coste, latencia, scoresTrazas + observaciones
CostsDesglose por componente (toolDecision/embedding/reranking/generation/voice)trace.metadata.cost
RAGTasa de activación, chunks por artículoTags Langfuse + Supabase
SecurityFunnel de defensa, distribución de safety, lista de jailbreaksTags + scores
EvalsPass rates por categoría (embebidos de reports reales)evals/results/ via build
VoiceSesiones, split texto/voz, latencia P50/P95, coste por minutoTags Langfuse
SystemVersiones de prompt, stats de documentos RAG, precios de modelosAPI prompts Langfuse + Supabase

Evals y Testing

71 tests automatizados en 10 categorías. ~70% deterministas, ~30% LLM-as-Judge (Haiku).

CategoríaTestsTipo
factual_accuracy9Determinista
persona_adherence4Determinista
boundary_testing7Determinista
response_quality7Mixto
safety_jailbreak7Determinista
language_handling5Determinista
rag_quality16Mixto
multi_turn5Mixto
source_badges5Determinista
voice_quality6Mixto

Scripts y Herramientas CLI

Todos los scripts están en scripts/ y se ejecutan con npm run:

Operaciones del Chatbot

ComandoScriptDescripción
npm run evalsevals/runner.tsEjecutar 71 evals automatizados
npm run adversarialscripts/adversarial-test.tsRed team: 20+ ataques auto-generados
npm run chatsscripts/chats.tsVer últimas 50 conversaciones de Langfuse
npm run chats -- --fullscripts/chats.tsConversaciones completas con mensajes
npm run chats -- --jailbreakscripts/chats.tsSolo intentos de jailbreak
npm run evaluate-tracesscripts/evaluate-traces.tsEval batch con Haiku (calidad, seguridad, intención)
npm run diagnose:ragscripts/diagnose-rag.tsDiagnóstico de calidad RAG — detecta retrieval misses

Gestión de Prompt y RAG

ComandoScriptDescripción
npm run prompt:syncscripts/sync-prompt-to-langfuse.tsSync prompt a Langfuse (basado en hash, skip si no cambió)
npm run prompt:regressionscripts/prompt-regression.tsComparar dos versiones del prompt
npm run rag:syncscripts/export-chunks.ts + scripts/ingest-rag.tsRe-exportar artículos + ingestar en Supabase

Tests de Contrato e Integración

ComandoScriptDescripción
npm run test:contracttests/ops-contract.test.tsValidar que metadata de trazas coincide con contrato del dashboard (67 tests)
npm run test:opstests/ops-dashboard.test.tsTestear los 7 endpoints API del dashboard (102 tests)

Inicio Rápido

git clone https://github.com/santifer/cv-santiago.git
cd cv-santiago
npm install
npm run dev

Abrir localhost:5173

Variables de Entorno

# Core
ANTHROPIC_API_KEY=           # Claude API (chatbot)
OPENAI_API_KEY=              # Embeddings + Voz

# RAG
SUPABASE_URL=                # URL del proyecto Supabase
SUPABASE_SERVICE_ROLE_KEY=   # Clave de servicio Supabase

# Observabilidad
LANGFUSE_PUBLIC_KEY=         # Tracing Langfuse
LANGFUSE_SECRET_KEY=         # Tracing Langfuse

# Alertas y Dashboard
RESEND_API_KEY=              # Alertas de jailbreak por email
OPS_DASHBOARD_SECRET=        # Contraseña del dashboard (/ops)

Estructura del Proyecto

src/
├── App.tsx                  # CV completo — todas las secciones
├── FloatingChat.tsx         # Widget de chat (modo texto)
├── useVoiceMode.ts          # Hook de modo voz (OpenAI Realtime)
├── VoiceOrb.tsx             # UI de voz (orbe + transcript)
├── GlobalNav.tsx            # Navegación con breadcrumbs
├── main.tsx                 # React Router + lazy loading
├── i18n.ts                  # Traducciones bilingües
├── articles/
│   ├── registry.ts          # Config centralizada de artículos
│   ├── components.tsx        # Componentes compartidos
│   └── json-ld.ts           # Builder de JSON-LD
├── ops/                     # Dashboard LLMOps
│   ├── OpsDashboard.tsx     # Shell + pestaña Overview
│   ├── OpsAuth.tsx          # Pantalla de login
│   ├── types.ts             # Interfaces TypeScript compartidas
│   ├── hooks/               # useOpsApi, useTraces
│   ├── components/          # KpiCard, MetricChart, FilterBar, etc.
│   └── tabs/                # Conversations, Costs, Security, Evals, etc.
├── [Articulo].tsx            # Componentes de case studies (5 artículos)
└── [articulo]-i18n.ts        # Contenido bilingüe por artículo

api/
├── chat.js                  # Edge function principal del chatbot
├── voice-token.js           # Token efímero de voz + rate limit
├── voice-trace.js           # Tracing de sesiones de voz
├── rag-search.js            # RAG para function calling de voz
├── _shared/
│   ├── rag.js               # Pipeline RAG (búsqueda, rerank, coste)
│   ├── prompt.js            # Versionado de prompt (Langfuse)
│   └── ops-auth.js          # Helper de auth del dashboard
└── ops/                     # Capa API proxy del dashboard
    ├── auth.js, stats.js, traces.js, trace/[id].js
    ├── evals.js, prompts.js, rag-stats.js

evals/
├── datasets/                # 10 datasets JSON (71 test cases)
├── assertions.ts            # Assertions deterministas
├── llm-judge.ts             # LLM-as-Judge (Haiku)
└── runner.ts                # Runner de evaluaciones

scripts/                     # Ver sección "Scripts y Herramientas CLI"
tests/
├── ops-contract.test.ts     # Tests de contrato (67 assertions)
└── ops-dashboard.test.ts    # Tests API del dashboard (102 assertions)

chatbot-prompt.txt           # System prompt (fallback, producción usa Langfuse)

Case Studies

ArtículoSlugsTipo
Chatbot que se cura solo/chatbot-que-se-cura-solo /self-healing-chatbotcase-study
Career-Ops/career-ops /career-ops-systemcase-study
Agente IA Jacobo/agente-ia-jacobo /ai-agent-jacobocase-study
Business OS/business-os-para-airtable /business-os-for-airtablecase-study
SEO Programático/seo-programatico /programmatic-seocase-study
n8n para PMs/n8n-para-pms /n8n-for-pmscollab
Santifer iRepair/santifer-irepair /santifer-irepair-founderbridge

Coste

  • <$0.005 por conversación de texto (5 modelos en el pipeline)
  • ~$0.25 por sesión de voz (OpenAI Realtime)
  • $0 infraestructura (free tiers: Vercel, Supabase, Langfuse)
  • ~$30/mes estimado a 200 conversaciones/día

Licencia

MIT


Let's Connect

Website LinkedIn Email

metadata.json
HTMLaichatbotclaudelangfusellmllmopsobservabilityPortfoliosreacttailwindcsstypescriptvercelvite

[INFO] 1 topic link to curated motion topic pages.