Home
Softono
s

santifer

Professional software vendor delivering innovative solutions on the Softono platform. Specialized in both open-source and proprietary software development.

Total Products
4

Software by santifer

career-ops
Open Source

career-ops

# Career-Ops [English](README.md) | [Español](README.es.md) | [Português (Brasil)](README.pt-BR.md) | [한국어](README.ko-KR.md) | [日本語](README.ja.md) | [简体中文](README.cn.md) | [繁體中文](README.zh-TW.md) | [Українська](README.ua.md) | [Русский](README.ru.md) <p align="center"> <a href="https://x.com/santifer"><img src="docs/hero-banner.jpg" alt="Career-Ops Multi-Agent Job Search System" width="800"></a> </p> <p align="center"> <em>I spent months applying to jobs the hard way. So I engineered the system I wish I had.</em><br> Companies use AI to filter candidates. <strong>I just gave candidates AI to <em>choose</em> companies.</strong><br> <em>Now it's open source.</em> </p> <p align="center"> <a href="https://trendshift.io/repositories/25195" target="_blank"><img src="https://trendshift.io/api/badge/repositories/25195" alt="santifer%2Fcareer-ops | Trendshift" style="width: 245px; height: 54px; vertical-align: middle;" width="245" height="54"/></a> &nbsp;&nbsp; <a href="https://www.producthunt.com/products/santifer-io?utm_source=badge-featured&utm_medium=badge" target="_blank"><img src="docs/press/producthunt.svg" alt="Career-Ops on Claude | Product Hunt" style="width: 206px; height: 54px; vertical-align: middle;" width="206" height="54"/></a> </p> <p align="center"><sub>FEATURED IN</sub></p> <p align="center"> <a href="https://wired.com.gr/article/to-ai-ergaleio-pou-fernei-epanastasi-ston-tropo-pou-psachnoume-douleia/" rel="noopener noreferrer nofollow"><picture><source media="(prefers-color-scheme: dark)" srcset="docs/press/wired-dark.svg"><img src="docs/press/wired.svg" alt="WIRED" height="32"></picture></a> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <a href="https://www.businessinsider.com/how-i-built-tool-filter-job-listings-landed-head-ai-2026-4" rel="noopener noreferrer nofollow"><picture><source media="(prefers-color-scheme: dark)" srcset="docs/press/business-insider-dark.svg"><img src="docs/press/business-insider.svg" alt="Business Insider" height="32"></picture></a> </p> --- <p align="center"> <img src="docs/demo.gif" alt="Career-Ops Demo" width="800"> </p> <p align="center"><strong>740+ job listings evaluated · 100+ personalized CVs · 1 dream role landed</strong></p> <p align="center"><a href="https://discord.gg/8pRpHETxa4"><img src="https://img.shields.io/badge/Join_the_community-Discord-5865F2?style=for-the-badge&logo=discord&logoColor=white" alt="Discord"></a></p> <p align="center"> <sub>Built with</sub><br> <img src="https://img.shields.io/badge/Claude_Code-000?style=flat&logo=anthropic&logoColor=white" alt="Claude Code"> <img src="https://img.shields.io/badge/OpenCode-111827?style=flat&logo=terminal&logoColor=white" alt="OpenCode"> <img src="https://img.shields.io/badge/Gemini_CLI-4285F4?style=flat&logo=google&logoColor=white" alt="Gemini CLI"> <img src="https://img.shields.io/badge/Codex-412991?style=flat&logo=openai&logoColor=white" alt="Codex"> <img src="https://img.shields.io/badge/Qwen-615CED?style=flat" alt="Qwen"> <img src="https://img.shields.io/badge/GitHub_Copilot-000?style=flat&logo=githubcopilot&logoColor=white" alt="GitHub Copilot"> <br> <img src="https://img.shields.io/badge/Node.js-339933?style=flat&logo=node.js&logoColor=white" alt="Node.js"> <img src="https://img.shields.io/badge/Go-00ADD8?style=flat&logo=go&logoColor=white" alt="Go"> <img src="https://img.shields.io/badge/Playwright-2EAD33?style=flat&logo=playwright&logoColor=white" alt="Playwright"> <img src="https://img.shields.io/badge/Bubble_Tea-FF75B5?style=flat&logo=go&logoColor=white" alt="Bubble Tea"> <img src="https://img.shields.io/badge/License-MIT-blue.svg" alt="MIT"> <a href="TRADEMARK.md"><img src="https://img.shields.io/badge/Trademark-Policy-blue.svg" alt="Trademark Policy"></a> </p> ## What Is This Career-Ops ([career-ops.org](https://career-ops.org), also known as **careerops**) turns any AI coding CLI into a full job search command center. Instead of manually tracking applications in a spreadsheet, you get an AI-powered pipeline that: - **Evaluates offers** with a structured A-F scoring system (10 weighted dimensions) - **Generates tailored PDFs** -- ATS-optimized CVs customized per job description - **Scans portals** automatically (Greenhouse, Ashby, Lever, company pages) - **Processes in batch** -- evaluate 10+ offers in parallel with sub-agents - **Tracks everything** in a single source of truth with integrity checks > **Important: This is NOT a spray-and-pray tool.** Career-ops is a filter -- it helps you find the few offers worth your time out of hundreds. The system strongly recommends against applying to anything scoring below 4.0/5. Your time is valuable, and so is the recruiter's. Always review before submitting. Career-ops is agentic: Claude Code navigates career pages with Playwright, evaluates fit by reasoning about your CV vs the job description (not keyword matching), and adapts your resume per listing. > **Heads up: the first evaluations won't be great.** The system doesn't know you yet. Feed it context -- your CV, your career story, your proof points, your preferences, what you're good at, what you want to avoid. The more you nurture it, the better it gets. Think of it as onboarding a new recruiter: the first week they need to learn about you, then they become invaluable. Built by someone who used it to evaluate 740+ job offers, generate 100+ tailored CVs, and land a Head of Applied AI role. [Read the full case study](https://santifer.io/career-ops-system). ## Features | Feature | Description | | ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------- | | **Auto-Pipeline** | Paste a URL, get a full evaluation + PDF + tracker entry | | **6-Block Evaluation** | Role summary, CV match, level strategy, comp research, personalization, interview prep (STAR+R) | | **Interview Story Bank** | Accumulates STAR+Reflection stories across evaluations -- 5-10 master stories that answer any behavioral question | | **Negotiation Scripts** | Salary negotiation frameworks, geographic discount pushback, competing offer leverage | | **ATS PDF Generation** | Keyword-injected CVs with Space Grotesk + DM Sans design | | **Portal Scanner** | 45+ companies pre-configured (Anthropic, OpenAI, ElevenLabs, Retool, n8n...) + custom queries across Ashby, Greenhouse, Lever, Wellfound | | **Batch Processing** | Parallel evaluation with `claude -p` workers | | **Dashboard TUI** | Terminal UI to browse, filter, and sort your pipeline | | **Human-in-the-Loop** | AI evaluates and recommends, you decide and act. The system never submits an application -- you always have the final call | | **Pipeline Integrity** | Automated merge, dedup, status normalization, health checks | ## Quick Start ```bash # 1. Clone and install git clone https://github.com/santifer/career-ops.git cd career-ops && npm install npx playwright install chromium # Required for PDF generation # 2. Check setup npm run doctor # Validates all prerequisites # 3. Configure cp config/profile.example.yml config/profile.yml # Edit with your details cp templates/portals.example.yml portals.yml # Customize companies # 4. Add your CV # Create cv.md in the project root with your CV in markdown # 5. Personalize with Claude claude # Open Claude Code in this directory # Then ask Claude to adapt the system to you: # "Change the archetypes to backend engineering roles" # "Translate the modes to English" # "Add these 5 companies to portals.yml" # "Update my profile with this CV I'm pasting" # 6. Start using # Paste a job URL or run /career-ops ``` > **The system is designed to be customized by Claude itself.** Modes, archetypes, scoring weights, negotiation scripts -- just ask Claude to change them. It reads the same files it uses, so it knows exactly what to edit. See [docs/SETUP.md](docs/SETUP.md) for the full setup guide. ## Gemini CLI Integration Career-ops supports [Gemini CLI](https://github.com/google-gemini/gemini-cli) natively, the same way it supports Claude Code and OpenCode. All 15 slash commands are available, using the same `modes/*.md` evaluation logic. ### Option A: Native Gemini CLI (Recommended) ```bash # 1. Install Gemini CLI npm install -g @google/gemini-cli # or: npx @google/gemini-cli --version # 2. Authenticate (free, uses your Google account) gemini auth # 3. Run in the career-ops directory cd career-ops gemini # 4. Use slash commands just like Claude Code /career-ops "Senior AI Engineer at Anthropic..." /career-ops-evaluate --file ./jds/openai.txt /career-ops-scan /career-ops-pdf /career-ops-tracker ``` The `GEMINI.md` file is auto-loaded as context. All 15 commands are defined in `.gemini/commands/*.toml`. ### Option B: Standalone API Script (No CLI install needed) ```bash # 1. Get a free API key at https://aistudio.google.com/apikey cp .env.example .env # Edit .env, set GEMINI_API_KEY=your_key_here # 2. Install dependencies npm install # 3. Evaluate a job description node gemini-eval.mjs "We are looking for a Senior AI Engineer..." node gemini-eval.mjs --file ./jds/my-job.txt npm run gemini:eval -- "JD text here" ``` > **Free tier:** Both options work without billing. Native CLI uses Google OAuth; the API script uses `gemini-2.5-flash` (15 RPM, 1M tokens/day free). ## Usage Career-ops is a single slash command with multiple modes: ``` /career-ops → Show all available commands /career-ops {paste a JD} → Full auto-pipeline (evaluate + PDF + tracker) /career-ops scan → Scan portals for new offers /career-ops pdf → Generate ATS-optimized CV /career-ops batch → Batch evaluate multiple offers /career-ops tracker → View application status /career-ops apply → Fill application forms with AI /career-ops pipeline → Process pending URLs /career-ops contacto → LinkedIn outreach message /career-ops deep → Deep company research /career-ops training → Evaluate a course/cert /career-ops project → Evaluate a portfolio project ``` Or just paste a job URL or description directly -- career-ops auto-detects it and runs the full pipeline. ## How It Works ``` You paste a job URL or description │ ▼ ┌──────────────────┐ │ Archetype │ Classifies: LLMOps / Agentic / PM / SA / FDE / Transformation │ Detection │ └────────┬─────────┘ │ ┌────────▼─────────┐ │ A-F Evaluation │ Match, gaps, comp research, STAR stories │ (reads cv.md) │ └────────┬─────────┘ │ ┌────┼────┐ ▼ ▼ ▼ Report PDF Tracker .md .pdf .tsv ``` ## Pre-configured Portals The scanner comes with **45+ companies** ready to scan and **19 search queries** across major job boards. Copy `templates/portals.example.yml` to `portals.yml` and add your own: **AI Labs:** Anthropic, OpenAI, Mistral, Cohere, LangChain, Pinecone **Voice AI:** ElevenLabs, PolyAI, Parloa, Hume AI, Deepgram, Vapi, Bland AI **AI Platforms:** Retool, Airtable, Vercel, Temporal, Glean, Arize AI **Contact Center:** Ada, LivePerson, Sierra, Decagon, Talkdesk, Genesys **Enterprise:** Salesforce, Twilio, Gong, Dialpad **LLMOps:** Langfuse, Weights & Biases, Lindy, Cognigy, Speechmatics **Automation:** n8n, Zapier, Make.com **European:** Factorial, Attio, Tinybird, Clarity AI, Travelperk **Job boards searched:** Ashby, Greenhouse, Lever, Wellfound, Workable, RemoteFront By default `node scan.mjs` (a.k.a. `npm run scan`) trusts what each ATS feed returns. Some companies leave stale postings in their public API even after the role is closed, so those expired entries can leak into `pipeline.md`. Pass `--verify` to launch Playwright after the API pass and drop expired postings before they hit the pipeline: ```bash node scan.mjs --verify # zero-token discovery + Playwright liveness check ``` The verification is sequential and only runs against new offers (after dedup), so the cost stays bounded. ## Dashboard TUI The built-in terminal dashboard lets you browse your pipeline visually: ```bash cd dashboard go build -o career-dashboard . ./career-dashboard --path .. ``` Features: 6 filter tabs, 4 sort modes, grouped/flat view, lazy-loaded previews, inline status changes. ## Project Structure ``` career-ops/ ├── AGENTS.md # Canonical agent instructions (all CLIs) ├── CLAUDE.md # Claude Code wrapper (imports AGENTS.md) ├── cv.md # Your CV (create this) ├── article-digest.md # Your proof points (optional) ├── config/ │ └── profile.example.yml # Template for your profile ├── modes/ # 14 skill modes │ ├── _shared.md # Shared context (customize this) │ ├── oferta.md # Single evaluation │ ├── pdf.md # PDF generation │ ├── scan.md # Portal scanner │ ├── batch.md # Batch processing │ └── ... ├── templates/ │ ├── cv-template.html # ATS-optimized CV template │ ├── portals.example.yml # Scanner config template │ └── states.yml # Canonical statuses ├── batch/ │ ├── batch-prompt.md # Self-contained worker prompt │ └── batch-runner.sh # Orchestrator script ├── dashboard/ # Go TUI pipeline viewer ├── data/ # Your tracking data (gitignored) ├── reports/ # Evaluation reports (gitignored) ├── output/ # Generated PDFs (gitignored) ├── fonts/ # Space Grotesk + DM Sans ├── docs/ # Setup, customization, architecture └── examples/ # Sample CV, report, proof points ``` ## Tech Stack ![Claude Code](https://img.shields.io/badge/Claude_Code-000?style=flat&logo=anthropic&logoColor=white) ![Node.js](https://img.shields.io/badge/Node.js-339933?style=flat&logo=node.js&logoColor=white) ![Playwright](https://img.shields.io/badge/Playwright-2EAD33?style=flat&logo=playwright&logoColor=white) ![Go](https://img.shields.io/badge/Go-00ADD8?style=flat&logo=go&logoColor=white) ![Bubble Tea](https://img.shields.io/badge/Bubble_Tea-FF75B5?style=flat&logo=go&logoColor=white) - **Agent**: Claude Code with custom skills and modes - **PDF**: Playwright/Puppeteer + HTML template - **Scanner**: Playwright + Greenhouse API + WebSearch - **Dashboard**: Go + Bubble Tea + Lipgloss (Catppuccin Mocha theme) - **Data**: Markdown tables + YAML config + TSV batch files ## Also Open Source - **[cv-santiago](https://github.com/santifer/cv-santiago)** -- The portfolio website (santifer.io) with AI chatbot, LLMOps dashboard, and case studies. If you need a portfolio to showcase alongside your job search, fork it and make it yours. ## About the Author I'm Santiago -- Head of Applied AI, former founder (built and sold a business that still runs with my name on it). I built career-ops to manage my own job search. It worked: I used it to land my current role. My portfolio and other open source projects → [santifer.io](https://santifer.io) ## Star History <a href="https://www.star-history.com/?repos=santifer%2Fcareer-ops&type=timeline&legend=top-left"> <picture> <source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/chart?repos=santifer/career-ops&type=timeline&theme=dark&legend=top-left" /> <source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/chart?repos=santifer/career-ops&type=timeline&legend=top-left" /> <img alt="Star History Chart" src="https://api.star-history.com/chart?repos=santifer/career-ops&type=timeline&legend=top-left" /> </picture> </a> ## Disclaimer **career-ops is a local, open-source tool, NOT a hosted service.** By using this software, you acknowledge: 1. **You control your data.** Your CV, contact info, and personal data stay on your machine and are sent directly to the AI provider you choose (Anthropic, OpenAI, etc.). We do not collect, store, or have access to any of your data. 2. **You control the AI.** The default prompts instruct the AI not to auto-submit applications, but AI models can behave unpredictably. If you modify the prompts or use different models, you do so at your own risk. **Always review AI-generated content for accuracy before submitting.** 3. **You comply with third-party ToS.** You must use this tool in accordance with the Terms of Service of the career portals you interact with (Greenhouse, Lever, Workday, LinkedIn, etc.). Do not use this tool to spam employers or overwhelm ATS systems. 4. **No guarantees.** Evaluations are recommendations, not truth. AI models may hallucinate skills or experience. The authors are not liable for employment outcomes, rejected applications, account restrictions, or any other consequences. See [LEGAL_DISCLAIMER.md](LEGAL_DISCLAIMER.md) for full details. This software is provided under the [MIT License](LICENSE) "as is", without warranty of any kind. ## Contributors <a href="https://github.com/santifer/career-ops/graphs/contributors"> <img src="https://contrib.rocks/image?repo=santifer/career-ops" /> </a> Got hired using career-ops? [Share your story!](https://github.com/santifer/career-ops/issues/new?template=i-got-hired.yml) ## License & Trademark The code is licensed under [MIT](LICENSE). The "career-ops" name and brand are governed by the [Trademark Policy](TRADEMARK.md), permissive for community use, reserved for commercial product naming and endorsement. ## Let's Connect [![Website](https://img.shields.io/badge/santifer.io-000?style=for-the-badge&logo=safari&logoColor=white)](https://santifer.io) [![LinkedIn](https://img.shields.io/badge/LinkedIn-0A66C2?style=for-the-badge&logo=linkedin&logoColor=white)](https://linkedin.com/in/santifer) [![X](https://img.shields.io/badge/X-000?style=for-the-badge&logo=x&logoColor=white)](https://x.com/santifer) [![Discord](https://img.shields.io/badge/Discord-5865F2?style=for-the-badge&logo=discord&logoColor=white)](https://discord.gg/8pRpHETxa4) [![Email](https://img.shields.io/badge/Email-EA4335?style=for-the-badge&logo=gmail&logoColor=white)](mailto:[email protected])

AI Agents Recruitment & ATS
51K Github Stars
cv-santiago
Open Source

cv-santiago

# santifer.io **[:gb: English](#the-problem)** | **[:es: Español](#es-versión-en-español)** > Interactive portfolio with AI chatbot (text + voice), agentic RAG, 71 automated evals, LLMOps dashboard, and 6-layer prompt injection defense [![Live Demo](https://img.shields.io/badge/demo-santifer.io-blue?style=flat-square)](https://santifer.io) [![Built with Claude Code](https://img.shields.io/badge/built%20with-Claude%20Code-blueviolet?style=flat-square)](https://claude.ai/code) --- <p align="center"> <img src="docs/hero.gif" alt="santifer.io in motion" width="100%" /> </p> --- ## 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 →](https://santifer.io/self-healing-chatbot#architecture) - **GEO-ready** — `llms.txt`, structured data (JSON-LD), AI crawler-friendly robots.txt --- ## Tech Stack ![React](https://img.shields.io/badge/React_19-61DAFB?style=flat&logo=react&logoColor=black) ![TypeScript](https://img.shields.io/badge/TypeScript-3178C6?style=flat&logo=typescript&logoColor=white) ![Vite](https://img.shields.io/badge/Vite_7-646CFF?style=flat&logo=vite&logoColor=white) ![Tailwind](https://img.shields.io/badge/Tailwind_v4-06B6D4?style=flat&logo=tailwindcss&logoColor=white) ![Claude](https://img.shields.io/badge/Claude_Sonnet-191919?style=flat&logo=anthropic&logoColor=white) ![OpenAI](https://img.shields.io/badge/OpenAI_Realtime-412991?style=flat&logo=openai&logoColor=white) ![Langfuse](https://img.shields.io/badge/Langfuse-000000?style=flat&logoColor=white) ![Supabase](https://img.shields.io/badge/Supabase-3FCF8E?style=flat&logo=supabase&logoColor=white) ![Vercel](https://img.shields.io/badge/Vercel_Edge-000000?style=flat&logo=vercel&logoColor=white) ![Recharts](https://img.shields.io/badge/Recharts-FF6384?style=flat&logoColor=white) --- ## Chatbot Architecture [![Interactive Architecture Diagram](public/chatbot/diagram-thumbnail.webp)](https://santifer.io/self-healing-chatbot#architecture) > **[Explore the interactive diagram →](https://santifer.io/self-healing-chatbot#architecture)** 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 | File | Path | Description | |------|------|-------------| | Chat edge function | `api/chat.js` | Main chatbot — RAG, tracing, scoring, streaming, defense | | RAG pipeline | `api/_shared/rag.js` | Hybrid search, reranking, cost tracking, intent classification | | Prompt management | `api/_shared/prompt.js` | Langfuse prompt registry with file fallback | | Voice token | `api/voice-token.js` | OpenAI Realtime ephemeral token + rate limiting | | Voice RAG | `api/rag-search.js` | RAG search for voice mode function calling | | Voice trace | `api/voice-trace.js` | Voice session tracing with cost estimation | | Chat widget | `src/FloatingChat.tsx` | React widget — streaming SSE, quick prompts, contact CTA | | Voice hook | `src/useVoiceMode.ts` | WebSocket management, audio capture, transcript persistence | | System prompt | `chatbot-prompt.txt` | Fallback prompt (production uses Langfuse v5) | --- ## LLMOps Dashboard (`/ops`) Private, password-protected dashboard with 8 tabs showing real production data: | Tab | What it shows | Data source | |-----|---------------|-------------| | Overview | KPIs, timelines, donuts, intent distribution | Langfuse traces | | Conversations | Filter + list + detail with spans, cost, latency, scores | Langfuse traces + observations | | Costs | Breakdown per component (toolDecision/embedding/reranking/generation/voice) | `trace.metadata.cost` | | RAG | Activation rate, chunks per article | Langfuse tags + Supabase | | Security | Defense funnel, safety distribution, jailbreak list | Langfuse tags + scores | | Evals | Pass rates by category (embedded from real eval reports) | `evals/results/` via build | | Voice | Sessions, text/voice split, latency P50/P95, cost per minute | Langfuse tags | | System | Prompt versions, RAG document stats, model pricing | Langfuse prompts API + Supabase | ### Dashboard API Layer | Endpoint | Path | Description | |----------|------|-------------| | Auth | `api/ops/auth.js` | Login (validates `OPS_DASHBOARD_SECRET`) | | Stats | `api/ops/stats.js` | Aggregated stats, server-side compute from traces | | Traces | `api/ops/traces.js` | List traces with filters (lang, mode, RAG, jailbreak) | | Trace detail | `api/ops/trace/[id].js` | Full trace with observations, scores, Langfuse link | | Evals | `api/ops/evals.js` | Eval results embedded from build | | Prompts | `api/ops/prompts.js` | Prompt versions from Langfuse | | RAG stats | `api/ops/rag-stats.js` | Document stats from Supabase | --- ## Evals & Testing 71 automated tests across 10 categories. ~70% deterministic (contains, regex, word count), ~30% LLM-as-Judge (Haiku). | Category | Tests | Type | |----------|-------|------| | factual_accuracy | 9 | Deterministic | | persona_adherence | 4 | Deterministic | | boundary_testing | 7 | Deterministic | | response_quality | 7 | Mixed | | safety_jailbreak | 7 | Deterministic | | language_handling | 5 | Deterministic | | rag_quality | 16 | Mixed | | multi_turn | 5 | Mixed | | source_badges | 5 | Deterministic | | voice_quality | 6 | Mixed | --- ## Scripts & CLI Tools All scripts live in `scripts/` and run via `npm run`: ### Chatbot Operations | Command | Script | Description | |---------|--------|-------------| | `npm run evals` | `evals/runner.ts` | Run 71 automated evals | | `npm run adversarial` | `scripts/adversarial-test.ts` | Red team: 20+ auto-generated attacks | | `npm run chats` | `scripts/chats.ts` | View last 50 conversations from Langfuse | | `npm run chats -- --full` | `scripts/chats.ts` | Full conversations with messages | | `npm run chats -- --jailbreak` | `scripts/chats.ts` | Only jailbreak attempts | | `npm run evaluate-traces` | `scripts/evaluate-traces.ts` | Batch eval with Haiku (quality, safety, intent) | | `npm run diagnose:rag` | `scripts/diagnose-rag.ts` | RAG quality diagnostic — detects retrieval misses | ### Prompt & RAG Management | Command | Script | Description | |---------|--------|-------------| | `npm run prompt:sync` | `scripts/sync-prompt-to-langfuse.ts` | Sync prompt to Langfuse (hash-based, skip if unchanged) | | `npm run prompt:regression` | `scripts/prompt-regression.ts` | Compare two prompt versions side by side | | `npm run rag:sync` | `scripts/export-chunks.ts` + `scripts/ingest-rag.ts` | Re-export articles + ingest to Supabase | ### Contract & Integration Tests | Command | Script | Description | |---------|--------|-------------| | `npm run test:contract` | `tests/ops-contract.test.ts` | Validate trace metadata matches dashboard contract (67 tests) | | `npm run test:ops` | `tests/ops-dashboard.test.ts` | Test all 7 dashboard API endpoints (102 tests) | ### Build Pipeline | Command | Script | Description | |---------|--------|-------------| | `npm run build` | (chained) | rag:sync → prompt:sync → embed-evals → reddit-stats → tsc → vite → sitemap → validate → prerender | | — | `scripts/embed-evals.ts` | Parse eval reports → embed in dashboard | | — | `scripts/generate-sitemap.ts` | Generate sitemap.xml with lastmod | | — | `scripts/validate-articles.ts` | SEO validation (dates, keywords, OG images) | | — | `scripts/validate-llms-txt.ts` | Validate llms.txt consistency | | — | `scripts/prerender.tsx` | SSR prerender all pages with critical CSS | | — | `scripts/indexnow-ping.ts` | Ping Bing/Yandex on deploy | --- ## Quick Start ```bash git clone https://github.com/santifer/cv-santiago.git cd cv-santiago npm install npm run dev ``` Open [localhost:5173](http://localhost:5173) ### Environment Variables ```bash # 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 | Article | Slugs | Type | |---------|-------|------| | Self-Healing Chatbot | `/chatbot-que-se-cura-solo` `/self-healing-chatbot` | case-study | | Career-Ops | `/career-ops` `/career-ops-system` | case-study | | Jacobo AI Agent | `/agente-ia-jacobo` `/ai-agent-jacobo` | case-study | | Business OS | `/business-os-para-airtable` `/business-os-for-airtable` | case-study | | Programmatic SEO | `/seo-programatico` `/programmatic-seo` | case-study | | n8n for PMs | `/n8n-para-pms` `/n8n-for-pms` | collab | | Santifer iRepair | `/santifer-irepair` `/santifer-irepair-founder` | bridge | --- ## 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](https://img.shields.io/badge/demo-santifer.io-blue?style=flat-square)](https://santifer.io) --- <p align="center"> <img src="docs/hero.gif" alt="santifer.io en movimiento" width="100%" /> </p> --- ## 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 →](https://santifer.io/chatbot-que-se-cura-solo#architecture) - **GEO-ready** — `llms.txt`, datos estructurados (JSON-LD), robots.txt amigable con crawlers IA --- ## Stack Técnico ![React](https://img.shields.io/badge/React_19-61DAFB?style=flat&logo=react&logoColor=black) ![TypeScript](https://img.shields.io/badge/TypeScript-3178C6?style=flat&logo=typescript&logoColor=white) ![Vite](https://img.shields.io/badge/Vite_7-646CFF?style=flat&logo=vite&logoColor=white) ![Tailwind](https://img.shields.io/badge/Tailwind_v4-06B6D4?style=flat&logo=tailwindcss&logoColor=white) ![Claude](https://img.shields.io/badge/Claude_Sonnet-191919?style=flat&logo=anthropic&logoColor=white) ![OpenAI](https://img.shields.io/badge/OpenAI_Realtime-412991?style=flat&logo=openai&logoColor=white) ![Langfuse](https://img.shields.io/badge/Langfuse-000000?style=flat&logoColor=white) ![Supabase](https://img.shields.io/badge/Supabase-3FCF8E?style=flat&logo=supabase&logoColor=white) ![Vercel](https://img.shields.io/badge/Vercel_Edge-000000?style=flat&logo=vercel&logoColor=white) ![Recharts](https://img.shields.io/badge/Recharts-FF6384?style=flat&logoColor=white) --- ## Arquitectura del Chatbot [![Diagrama Interactivo de Arquitectura](public/chatbot/diagram-thumbnail.webp)](https://santifer.io/chatbot-que-se-cura-solo#architecture) > **[Explorar el diagrama interactivo →](https://santifer.io/chatbot-que-se-cura-solo#architecture)** 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 | Archivo | Ruta | Descripción | |---------|------|-------------| | Chat edge function | `api/chat.js` | Chatbot principal — RAG, tracing, scoring, streaming, defensa | | Pipeline RAG | `api/_shared/rag.js` | Búsqueda híbrida, reranking, coste, clasificación de intención | | Gestión de prompt | `api/_shared/prompt.js` | Langfuse prompt registry con fallback local | | Token de voz | `api/voice-token.js` | Token efímero OpenAI Realtime + rate limiting | | RAG voz | `api/rag-search.js` | Búsqueda RAG para function calling de voz | | Trace voz | `api/voice-trace.js` | Tracing de sesiones de voz con estimación de coste | | Widget chat | `src/FloatingChat.tsx` | Widget React — streaming SSE, quick prompts, CTA de contacto | | Hook de voz | `src/useVoiceMode.ts` | Gestión WebSocket, captura audio, persistencia de transcript | | System prompt | `chatbot-prompt.txt` | Prompt fallback (producción usa Langfuse v5) | --- ## Dashboard LLMOps (`/ops`) Dashboard privado protegido por contraseña con 8 pestañas mostrando datos reales: | Pestaña | Qué muestra | Fuente de datos | |---------|-------------|-----------------| | Overview | KPIs, timelines, donuts, distribución de intents | Trazas Langfuse | | Conversations | Filtros + lista + detalle con spans, coste, latencia, scores | Trazas + observaciones | | Costs | Desglose por componente (toolDecision/embedding/reranking/generation/voice) | `trace.metadata.cost` | | RAG | Tasa de activación, chunks por artículo | Tags Langfuse + Supabase | | Security | Funnel de defensa, distribución de safety, lista de jailbreaks | Tags + scores | | Evals | Pass rates por categoría (embebidos de reports reales) | `evals/results/` via build | | Voice | Sesiones, split texto/voz, latencia P50/P95, coste por minuto | Tags Langfuse | | System | Versiones de prompt, stats de documentos RAG, precios de modelos | API prompts Langfuse + Supabase | --- ## Evals y Testing 71 tests automatizados en 10 categorías. ~70% deterministas, ~30% LLM-as-Judge (Haiku). | Categoría | Tests | Tipo | |-----------|-------|------| | factual_accuracy | 9 | Determinista | | persona_adherence | 4 | Determinista | | boundary_testing | 7 | Determinista | | response_quality | 7 | Mixto | | safety_jailbreak | 7 | Determinista | | language_handling | 5 | Determinista | | rag_quality | 16 | Mixto | | multi_turn | 5 | Mixto | | source_badges | 5 | Determinista | | voice_quality | 6 | Mixto | --- ## Scripts y Herramientas CLI Todos los scripts están en `scripts/` y se ejecutan con `npm run`: ### Operaciones del Chatbot | Comando | Script | Descripción | |---------|--------|-------------| | `npm run evals` | `evals/runner.ts` | Ejecutar 71 evals automatizados | | `npm run adversarial` | `scripts/adversarial-test.ts` | Red team: 20+ ataques auto-generados | | `npm run chats` | `scripts/chats.ts` | Ver últimas 50 conversaciones de Langfuse | | `npm run chats -- --full` | `scripts/chats.ts` | Conversaciones completas con mensajes | | `npm run chats -- --jailbreak` | `scripts/chats.ts` | Solo intentos de jailbreak | | `npm run evaluate-traces` | `scripts/evaluate-traces.ts` | Eval batch con Haiku (calidad, seguridad, intención) | | `npm run diagnose:rag` | `scripts/diagnose-rag.ts` | Diagnóstico de calidad RAG — detecta retrieval misses | ### Gestión de Prompt y RAG | Comando | Script | Descripción | |---------|--------|-------------| | `npm run prompt:sync` | `scripts/sync-prompt-to-langfuse.ts` | Sync prompt a Langfuse (basado en hash, skip si no cambió) | | `npm run prompt:regression` | `scripts/prompt-regression.ts` | Comparar dos versiones del prompt | | `npm run rag:sync` | `scripts/export-chunks.ts` + `scripts/ingest-rag.ts` | Re-exportar artículos + ingestar en Supabase | ### Tests de Contrato e Integración | Comando | Script | Descripción | |---------|--------|-------------| | `npm run test:contract` | `tests/ops-contract.test.ts` | Validar que metadata de trazas coincide con contrato del dashboard (67 tests) | | `npm run test:ops` | `tests/ops-dashboard.test.ts` | Testear los 7 endpoints API del dashboard (102 tests) | --- ## Inicio Rápido ```bash git clone https://github.com/santifer/cv-santiago.git cd cv-santiago npm install npm run dev ``` Abrir [localhost:5173](http://localhost:5173) ### Variables de Entorno ```bash # 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ículo | Slugs | Tipo | |----------|-------|------| | Chatbot que se cura solo | `/chatbot-que-se-cura-solo` `/self-healing-chatbot` | case-study | | Career-Ops | `/career-ops` `/career-ops-system` | case-study | | Agente IA Jacobo | `/agente-ia-jacobo` `/ai-agent-jacobo` | case-study | | Business OS | `/business-os-para-airtable` `/business-os-for-airtable` | case-study | | SEO Programático | `/seo-programatico` `/programmatic-seo` | case-study | | n8n para PMs | `/n8n-para-pms` `/n8n-for-pms` | collab | | Santifer iRepair | `/santifer-irepair` `/santifer-irepair-founder` | bridge | --- ## 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](https://img.shields.io/badge/santifer.io-000?style=for-the-badge&logo=safari&logoColor=white)](https://santifer.io) [![LinkedIn](https://img.shields.io/badge/LinkedIn-0A66C2?style=for-the-badge&logo=linkedin&logoColor=white)](https://linkedin.com/in/santifer) [![Email](https://img.shields.io/badge/Email-EA4335?style=for-the-badge&logo=gmail&logoColor=white)](mailto:[email protected])

Frontend Templates LLM Tools & Chat UIs
645 Github Stars
jacobo-workflows
Open Source

jacobo-workflows

# Jacobo AI Agent — Production n8n Workflows **[:gb: English](#the-system)** | **[:es: Español](#es-versión-en-español)** > 7 real production workflows from a multi-agent AI system that handled ~90% of customer interactions for a phone repair business. Open source by default. ## The System Jacobo is an omnichannel AI agent (WhatsApp + phone) built with n8n, orchestrating specialized sub-agents via tool calling. These workflows ran in production for 2 years at [Santifer iRepair](https://santifer.io/ai-agent-jacobo). ## Workflows | File | Original Name (ES) | Description | Nodes | LLM | |------|-------------------|-------------|-------|-----| | `jacobo-chatbot-v2.json` | Jacobo Chatbot V2 | Central router — classifies intent, selects sub-agent, maintains 20-message memory window | 37 | GPT-4.1 | | `subagente-citas.json` | subagenteCitas | Appointment booking — parses natural language time preferences into calendar slots via YouCanBookMe | 18 | MiniMax M2.5 | | `presupuesto-modelo.json` | Presupuesto Modelo | Quote agent — looks up exact model + repair in Airtable, returns real price with stock status | 11 | GPT-4.1 mini | | `hacer-pedido.json` | hacerPedido | Order creation — creates repair orders in Airtable when parts are out of stock | 3 | No LLM | | `calculadora-santifer.json` | CalculadoraSantifer | Discount calculator — pure business logic for combo repair pricing | 3 | No LLM | | `contactar-agente-humano.json` | contactarAgenteHumano | HITL handoff — escalates to human via Slack with conversation summary and deep-link | 5 | No LLM | | `enviar-mensaje-wati.json` | EnviarMensajeWati | WhatsApp sender — cross-channel bridge so the voice agent can send WhatsApp messages | 3 | No LLM | ## Key Metrics - **~90% self-service** — most interactions resolved without human intervention - **~80h/month automated** — equivalent to a part-time employee - **<30s response time** — from customer message to resolution - **<€200/month** — total infrastructure cost ## How to Import into n8n 1. Open your n8n instance and go to **Workflows** 2. Click **"..."** → **"Import from file"** 3. Select any `.json` file from this folder 4. Update credentials (API keys, webhooks) with your own values > **Note:** These workflows are sanitized — all API keys, webhook URLs, and personal data have been removed. You'll need to configure your own credentials after importing. ## Full Case Study Read the complete architecture breakdown, prompt engineering techniques, and production learnings: - [Jacobo AI Agent — Case Study (EN)](https://santifer.io/ai-agent-jacobo) - [Agente IA Jacobo — Case Study (ES)](https://santifer.io/agente-ia-jacobo) --- # :es: Versión en Español > 7 workflows reales de producción de un sistema multi-agente IA que gestionó ~90% de las interacciones de clientes en un negocio de reparación de móviles. Open source by default. ## El Sistema Jacobo es un agente IA omnicanal (WhatsApp + teléfono) construido con n8n, que orquesta sub-agentes especializados vía tool calling. Estos workflows corrieron en producción durante 2 años en [Santifer iRepair](https://santifer.io/agente-ia-jacobo). ## Workflows | Archivo | Nombre Original | Descripción | Nodos | LLM | |---------|----------------|-------------|-------|-----| | `jacobo-chatbot-v2.json` | Jacobo Chatbot V2 | Router central — clasifica intent, elige sub-agente, mantiene ventana de memoria de 20 mensajes | 37 | GPT-4.1 | | `subagente-citas.json` | subagenteCitas | Reserva de citas — parsea preferencias temporales en lenguaje natural a slots de calendario vía YouCanBookMe | 18 | MiniMax M2.5 | | `presupuesto-modelo.json` | Presupuesto Modelo | Agente de presupuestos — busca modelo + reparación en Airtable, devuelve precio real con estado de stock | 11 | GPT-4.1 mini | | `hacer-pedido.json` | hacerPedido | Creación de pedidos — crea órdenes de reparación en Airtable cuando no hay stock | 3 | Sin LLM | | `calculadora-santifer.json` | CalculadoraSantifer | Calculadora de descuentos — lógica de negocio pura para precios combo de multi-reparación | 3 | Sin LLM | | `contactar-agente-humano.json` | contactarAgenteHumano | HITL handoff — escala a humano vía Slack con resumen de conversación y deep-link | 5 | Sin LLM | | `enviar-mensaje-wati.json` | EnviarMensajeWati | Envío WhatsApp — puente cross-channel para que el agente de voz envíe mensajes por WhatsApp | 3 | Sin LLM | ## Métricas Clave - **~90% autoservicio** — la mayoría de interacciones resueltas sin intervención humana - **~80h/mes automatizadas** — equivalente a un empleado a media jornada - **<30s tiempo de respuesta** — del mensaje del cliente a la resolución - **<200€/mes** — coste total de infraestructura ## Cómo Importar en n8n 1. Abre tu instancia de n8n y ve a **Workflows** 2. Haz click en **"..."** → **"Import from file"** 3. Selecciona cualquier archivo `.json` de esta carpeta 4. Actualiza las credenciales (API keys, webhooks) con tus propios valores > **Nota:** Estos workflows están sanitizados — todas las API keys, URLs de webhooks y datos personales han sido eliminados. Necesitarás configurar tus propias credenciales después de importar. ## Case Study Completo Lee el desglose completo de arquitectura, técnicas de prompt engineering y aprendizajes de producción: - [Agente IA Jacobo — Case Study (ES)](https://santifer.io/agente-ia-jacobo) - [Jacobo AI Agent — Case Study (EN)](https://santifer.io/ai-agent-jacobo) --- ## Let's Connect [![Website](https://img.shields.io/badge/santifer.io-000?style=for-the-badge&logo=safari&logoColor=white)](https://santifer.io) [![LinkedIn](https://img.shields.io/badge/LinkedIn-0A66C2?style=for-the-badge&logo=linkedin&logoColor=white)](https://linkedin.com/in/santifer) [![Email](https://img.shields.io/badge/Email-EA4335?style=for-the-badge&logo=gmail&logoColor=white)](mailto:[email protected])

AI Agents Workflow Automation
148 Github Stars
santifer-irepair
Open Source

santifer-irepair

# Santifer iRepair — Programmatic SEO Website **[:gb: English](#the-problem)** | **[:es: Español](#el-problema)** > Astro-based programmatic SEO website that generated 15,500+ unique pages from an Airtable ERP, reaching 2.26M impressions and 2,000 monthly clicks in Google Spain. [![Case Study](https://img.shields.io/badge/Case_Study-santifer.io-000?style=for-the-badge&logo=safari&logoColor=white)](https://santifer.io/programmatic-seo) [![Live Site](https://img.shields.io/badge/Live_Site-santiferirepair.es-BC52EE?style=for-the-badge&logo=astro&logoColor=white)](https://santiferirepair.es) --- ![Santifer iRepair Homepage](docs/ss-homepage.webp) --- ## The Problem Local repair shops have thousands of potential service pages (every brand x model x repair type), but creating them manually is impossible. Existing solutions either generate thin, duplicate content or require expensive CMS platforms. ## The Solution A fully automated pipeline that reads device data from an Airtable ERP, uses DataForSEO to decide which pages deserve to exist based on real search volume, generates optimized images with Sharp, and builds 15,500+ unique Astro pages with structured data, breadcrumbs, and internal linking. **Key Features:** - **DataForSEO-powered indexability engine** — not every possible page gets indexed. A decision layer queries real search volume data to determine which combinations (model x repair x city) justify a page. Pages below threshold get `noindex`. - **9 Node.js scripts** that generate images, sitemaps, and metadata from Airtable - **Parametric Astro routes** — one layout generates thousands of unique pages - **EXIF injection** for Google Images ranking (geo-coordinates, descriptions) - **Crawl budget optimization** — selective `noindex`, filtered sitemaps (4,084 URLs from thousands possible), 700+ redirect rules for Squarespace migration, and strategic internal linking --- ## Tech Stack ![Astro](https://img.shields.io/badge/Astro-BC52EE?style=flat&logo=astro&logoColor=white) ![TypeScript](https://img.shields.io/badge/TypeScript-3178C6?style=flat&logo=typescript&logoColor=white) ![Tailwind CSS](https://img.shields.io/badge/Tailwind_CSS-06B6D4?style=flat&logo=tailwindcss&logoColor=white) ![Node.js](https://img.shields.io/badge/Node.js-339933?style=flat&logo=nodedotjs&logoColor=white) ![Airtable](https://img.shields.io/badge/Airtable-18BFFF?style=flat&logo=airtable&logoColor=white) ![DataForSEO](https://img.shields.io/badge/DataForSEO-FF6B00?style=flat&logo=data:image/svg+xml;base64,&logoColor=white) ![Sharp](https://img.shields.io/badge/Sharp-99CC00?style=flat&logo=sharp&logoColor=white) ![Vercel](https://img.shields.io/badge/Vercel-000?style=flat&logo=vercel&logoColor=white) --- ## Architecture Decisions ### DataForSEO as Decision Engine The pipeline doesn't blindly generate pages for every possible combination. Before a page is built, DataForSEO's keyword data API is queried to check real search volume for that specific `{brand} + {model} + {repair} + {city}` combination. Pages below the volume threshold are either not generated or marked `noindex`, concentrating crawl budget on pages that actually drive traffic. This is visible in Airtable's `indexable` field and in `src/lib/airtable.ts` where the indexability logic lives. ### Crawl Budget Optimization With 15,500+ possible pages, controlling what Google crawls is critical: - **Selective noindex** — low-volume pages exist for UX completeness but don't waste crawl budget - **Filtered sitemaps** — only 4,084 URLs submitted out of thousands possible (`public/sitemap-0.xml`) - **700+ redirects** — bridge rules in `vercel.json` for the Squarespace-to-Astro migration, preserving link equity - **JSON-LD structured data** — LocalBusiness, BreadcrumbList, Organization on every page --- ## How It Works ``` Airtable (ERP) → DataForSEO → Node.js Scripts → Astro SSG → Vercel/Cloudflare 300+ models search volume image pipeline 15,500+ CDN + Edge 50+ brands indexability EXIF injection pages reviews decisions sitemaps ``` Every device model, brand, and repair type stored in Airtable flows through a decision layer (DataForSEO search volume data), then through a pipeline of Node.js scripts that generate optimized images with SEO metadata. Finally, Astro builds parametric pages using dynamic routes like: - `/reparar-movil/samsung/galaxy-s24/` — model page - `/reparar-movil/samsung/sevilla` — brand + city - `/reparar-movil/cambiar-pantalla/sevilla` — repair type + city - `/reparar-apple-watch/serie-4/40mm` — Apple product family + model ![Generated repair page example](docs/ss-repair-page.webp) --- ## Installation ```bash # 1. Install dependencies npm install # 2. Configure environment cp .env.example .env # Add your Airtable API key and base ID ``` --- ## Usage ```bash # Run image pipeline (requires Airtable data) node scripts/generarImagenesReparacionesModelos.mjs node scripts/ExifLocal.mjs node scripts/sitemaps.mjs # Start dev server npm run dev # Build for production npm run build ``` --- ## Configuration | Variable | Description | Required | |----------|-------------|----------| | `AIRTABLE_API_KEY` | Airtable personal access token | Yes | | `AIRTABLE_BASE_ID` | Airtable base containing device data | Yes | --- ## The Pipeline Scripts The core of the pSEO approach — 9 Node.js scripts that transform Airtable data into optimized web assets: | Script | What it does | |--------|-------------| | `generarImagenesReparacionesModelos.mjs` | Generates device-specific images with model overlays | | `generarImagenesReparacionesMarcas.mjs` | Creates brand-level repair guide images and thumbnails | | `generarImagenesReparacionesTipos.cjs` | Converts device type templates to optimized WebP | | `generarImagenesBackgroundPasosReparacion.mjs` | Generates repair step illustrations with branding | | `generarImagenesReseñas.mjs` | Creates review/testimonial profile images | | `CasosExito.mjs` | Downloads and optimizes before/after case study images | | `ExifLocal.mjs` | Injects EXIF metadata (description, GPS) for Google Images SEO | | `scriptImagenesGoogle.mjs` | Fetches and processes external device images | | `sitemaps.mjs` | Generates XML sitemaps organized by device type and category | The ~15,000 generated images are not included in this repo — they are pipeline output, not source code. --- ## Project Structure ``` ├── src/ │ ├── pages/ # Astro dynamic routes (parametric SEO pages) │ │ ├── reparar-[paramTipo]/ # /reparar-movil, /reparar-tablet, /reparar-smartwatch │ │ ├── [paramMarcaApple]/ # Apple-specific product family routes │ │ ├── cambiar-[paramRep]/ # Repair type pages │ │ └── blog/ # Blog with markdown content │ ├── layouts/ # Page templates per hierarchy level │ │ ├── TipoLayout.astro # Device type (mobile/tablet/watch) │ │ ├── MarcaLayout.astro # Brand (Samsung, Apple, Xiaomi...) │ │ ├── ModeloLayout.astro # Specific model │ │ └── ReparacionLayout.astro# Repair type (screen, battery...) │ ├── components/ # 60+ Astro components │ │ ├── metadatos/ # JSON-LD structured data │ │ ├── FAQs.astro # Auto-generated FAQ sections │ │ └── Buscador.astro # Client-side device search │ ├── lib/ # Airtable client, data caching, indexability logic │ └── content/blog/ # 16 markdown blog posts ├── scripts/ # Image generation pipeline │ ├── plantillas/ # Base templates for image compositing │ └── src/ # Script-specific type definitions ├── public/ │ ├── marcas/ # Brand logos (50+) │ ├── scripts/ # Client-side JS (search, modals, reviews) │ └── fonts/ # Graphik typeface └── vercel.json # 700+ redirect rules + headers ``` --- ## Results ![Google Search Console growth — 0 to 2K clicks in 12 months](docs/ss-gsc-growth.webp) | Metric | Value | |--------|-------| | Pages generated | 15,500+ | | Impressions (total) | 2,260,000+ | | Google-indexed keywords | 1,800+ | | Monthly organic clicks (peak) | 2,000 | | Sitemap URLs (curated) | 4,084 of thousands possible | | Google Search Console growth | 0 → 2K clicks in 12 months | | Business outcome | Successful exit (Sep 2025) | --- ## License This project is shared as a portfolio piece and educational reference. The code structure and automation patterns are freely available for learning. Brand assets and business-specific content remain property of their respective owners. --- --- # :es: Version en Español > Web de SEO programatico construida con Astro que genero 15.500+ paginas unicas desde un ERP en Airtable, alcanzando 2,26M impresiones y 2.000 clics mensuales en Google España. [![Caso de Estudio](https://img.shields.io/badge/Caso_de_Estudio-santifer.io-000?style=for-the-badge&logo=safari&logoColor=white)](https://santifer.io/seo-programatico) [![Sitio en Vivo](https://img.shields.io/badge/Sitio_en_Vivo-santiferirepair.es-BC52EE?style=for-the-badge&logo=astro&logoColor=white)](https://santiferirepair.es) --- ## El Problema Las tiendas de reparacion locales tienen miles de paginas de servicio potenciales (cada marca x modelo x tipo de reparacion), pero crearlas manualmente es imposible. Las soluciones existentes generan contenido duplicado o requieren plataformas CMS caras. ## La Solucion Un pipeline completamente automatizado que lee datos de dispositivos desde un ERP en Airtable, usa DataForSEO para decidir que paginas merecen existir basandose en volumen de busqueda real, genera imagenes optimizadas con Sharp, y construye 15.500+ paginas unicas con Astro, incluyendo structured data, breadcrumbs y enlazado interno. **Funcionalidades:** - **Motor de indexabilidad con DataForSEO** — no todas las paginas posibles se indexan. Una capa de decision consulta datos reales de volumen de busqueda para determinar que combinaciones (modelo x reparacion x ciudad) justifican una pagina. Las que no alcanzan el umbral reciben `noindex`. - **9 scripts Node.js** que generan imagenes, sitemaps y metadatos desde Airtable - **Rutas parametricas en Astro** — un layout genera miles de paginas unicas - **Inyeccion EXIF** para posicionar en Google Images (coordenadas, descripciones) - **Optimizacion de crawl budget** — `noindex` selectivo, sitemaps filtrados (4.084 URLs de miles posibles), 700+ reglas de redireccion para la migracion desde Squarespace, y enlazado interno estrategico --- ## Stack Tecnico ![Astro](https://img.shields.io/badge/Astro-BC52EE?style=flat&logo=astro&logoColor=white) ![TypeScript](https://img.shields.io/badge/TypeScript-3178C6?style=flat&logo=typescript&logoColor=white) ![Tailwind CSS](https://img.shields.io/badge/Tailwind_CSS-06B6D4?style=flat&logo=tailwindcss&logoColor=white) ![Node.js](https://img.shields.io/badge/Node.js-339933?style=flat&logo=nodedotjs&logoColor=white) ![Airtable](https://img.shields.io/badge/Airtable-18BFFF?style=flat&logo=airtable&logoColor=white) ![DataForSEO](https://img.shields.io/badge/DataForSEO-FF6B00?style=flat&logo=data:image/svg+xml;base64,&logoColor=white) ![Sharp](https://img.shields.io/badge/Sharp-99CC00?style=flat&logo=sharp&logoColor=white) ![Vercel](https://img.shields.io/badge/Vercel-000?style=flat&logo=vercel&logoColor=white) --- ## Decisiones de Arquitectura ### DataForSEO como Motor de Decision El pipeline no genera paginas a ciegas para cada combinacion posible. Antes de construir una pagina, se consulta la API de keyword data de DataForSEO para verificar el volumen de busqueda real de esa combinacion `{marca} + {modelo} + {reparacion} + {ciudad}`. Las paginas por debajo del umbral no se generan o se marcan como `noindex`, concentrando el crawl budget en las paginas que realmente generan trafico. Esto es visible en el campo `indexable` de Airtable y en `src/lib/airtable.ts` donde vive la logica de indexabilidad. ### Optimizacion de Crawl Budget Con 15.500+ paginas posibles, controlar lo que Google rastrea es critico: - **Noindex selectivo** — las paginas de bajo volumen existen para completitud de UX pero no desperdician crawl budget - **Sitemaps filtrados** — solo 4.084 URLs enviadas de miles posibles (`public/sitemap-0.xml`) - **700+ redirecciones** — reglas puente en `vercel.json` para la migracion de Squarespace a Astro, preservando link equity - **JSON-LD structured data** — LocalBusiness, BreadcrumbList, Organization en cada pagina --- ## Como Funciona ``` Airtable (ERP) → DataForSEO → Scripts Node.js → Astro SSG → Vercel/Cloudflare 300+ modelos volumen de pipeline de 15.500+ CDN + Edge 50+ marcas busqueda imagenes paginas reseñas indexabilidad EXIF + sitemaps ``` Cada modelo de dispositivo, marca y tipo de reparacion almacenado en Airtable pasa por una capa de decision (datos de volumen de busqueda de DataForSEO), luego por un pipeline de scripts Node.js que generan imagenes optimizadas con metadatos SEO. Finalmente, Astro construye paginas parametricas con rutas dinamicas como: - `/reparar-movil/samsung/galaxy-s24/` — pagina de modelo - `/reparar-movil/samsung/sevilla` — marca + ciudad - `/reparar-movil/cambiar-pantalla/sevilla` — tipo de reparacion + ciudad - `/reparar-apple-watch/serie-4/40mm` — familia de producto Apple + modelo ![Ejemplo de pagina de reparacion generada](docs/ss-repair-page.webp) --- ## Instalacion ```bash # 1. Instalar dependencias npm install # 2. Configurar entorno cp .env.example .env # Añade tu API key de Airtable y base ID ``` --- ## Uso ```bash # Ejecutar pipeline de imagenes (requiere datos en Airtable) node scripts/generarImagenesReparacionesModelos.mjs node scripts/ExifLocal.mjs node scripts/sitemaps.mjs # Servidor de desarrollo npm run dev # Build de produccion npm run build ``` --- ## Configuracion | Variable | Descripcion | Requerida | |----------|-------------|-----------| | `AIRTABLE_API_KEY` | Token de acceso personal de Airtable | Si | | `AIRTABLE_BASE_ID` | Base de Airtable con datos de dispositivos | Si | --- ## Los Scripts del Pipeline | Script | Que hace | |--------|----------| | `generarImagenesReparacionesModelos.mjs` | Genera imagenes por modelo de dispositivo con overlays | | `generarImagenesReparacionesMarcas.mjs` | Crea imagenes de guia de reparacion por marca | | `generarImagenesReparacionesTipos.cjs` | Convierte plantillas por tipo de dispositivo a WebP | | `generarImagenesBackgroundPasosReparacion.mjs` | Genera ilustraciones de pasos de reparacion | | `generarImagenesReseñas.mjs` | Crea imagenes de perfil para reseñas desde Airtable | | `CasosExito.mjs` | Descarga y optimiza imagenes antes/despues | | `ExifLocal.mjs` | Inyecta metadatos EXIF para SEO en Google Images | | `scriptImagenesGoogle.mjs` | Obtiene y procesa imagenes externas de dispositivos | | `sitemaps.mjs` | Genera sitemaps XML por tipo de dispositivo y categoria | --- ## Estructura del Proyecto ``` ├── src/ │ ├── pages/ # Rutas dinamicas Astro (paginas SEO parametricas) │ │ ├── reparar-[paramTipo]/ # /reparar-movil, /reparar-tablet, /reparar-smartwatch │ │ ├── [paramMarcaApple]/ # Rutas de familias de productos Apple │ │ ├── cambiar-[paramRep]/ # Paginas por tipo de reparacion │ │ └── blog/ # Blog con contenido markdown │ ├── layouts/ # Templates de pagina por nivel de jerarquia │ │ ├── TipoLayout.astro # Tipo de dispositivo (movil/tablet/watch) │ │ ├── MarcaLayout.astro # Marca (Samsung, Apple, Xiaomi...) │ │ ├── ModeloLayout.astro # Modelo especifico │ │ └── ReparacionLayout.astro# Tipo de reparacion (pantalla, bateria...) │ ├── components/ # 60+ componentes Astro │ │ ├── metadatos/ # JSON-LD structured data │ │ ├── FAQs.astro # Secciones FAQ auto-generadas │ │ └── Buscador.astro # Buscador de dispositivos del lado cliente │ ├── lib/ # Cliente Airtable, cache, logica de indexabilidad │ └── content/blog/ # 16 posts de blog en markdown ├── scripts/ # Pipeline de generacion de imagenes │ ├── plantillas/ # Templates base para composicion de imagenes │ └── src/ # Tipos TypeScript de los scripts ├── public/ │ ├── marcas/ # Logos de marcas (50+) │ ├── scripts/ # JS del lado cliente (buscador, modales, reseñas) │ └── fonts/ # Tipografia Graphik └── vercel.json # 700+ reglas de redireccion + headers ``` --- ## Resultados ![Crecimiento en Google Search Console — de 0 a 2K clics en 12 meses](docs/ss-gsc-growth.webp) | Metrica | Valor | |---------|-------| | Paginas generadas | 15.500+ | | Impresiones (total) | 2.260.000+ | | Keywords indexadas en Google | 1.800+ | | Clics organicos mensuales (pico) | 2.000 | | URLs en sitemap (curadas) | 4.084 de miles posibles | | Crecimiento en GSC | 0 → 2K clics en 12 meses | | Resultado de negocio | Venta exitosa (sep 2025) | --- ## Licencia Este proyecto se comparte como pieza de portfolio y referencia educativa. La estructura del codigo y los patrones de automatizacion estan disponibles para aprendizaje. Los activos de marca y contenido especifico del negocio pertenecen a sus respectivos propietarios. --- ## Let's Connect [![Website](https://img.shields.io/badge/santifer.io-000?style=for-the-badge&logo=safari&logoColor=white)](https://santifer.io) [![LinkedIn](https://img.shields.io/badge/LinkedIn-0A66C2?style=for-the-badge&logo=linkedin&logoColor=white)](https://linkedin.com/in/santifer) [![Email](https://img.shields.io/badge/Email-EA4335?style=for-the-badge&logo=gmail&logoColor=white)](mailto:[email protected])

SEO Tools Static Site Generators
34 Github Stars