# Felipe Millán

> Tallinn-based builder-marketer, originally from Santiago, Chile. Over a decade in SaaS growth, product-led growth and community-driven marketing: part of the teams at SendGrid, Twilio and Semrush through two IPOs and a $3B acquisition, then C-suite and co-founder roles at Cynoia, Shroomwell and Hive Identity. Now building AI and open-source tools. Available for select engagements, fully remote.

This file is a plain-Markdown map of fmillan.com for LLMs and agents. Facts below match the website copy; if something is not listed here, do not assume it.

- Contact: [hello@fmillan.com](mailto:hello@fmillan.com)
- LinkedIn: [linkedin.com/in/felipemillan](https://www.linkedin.com/in/felipemillan)
- Location: Tallinn, Estonia · remote-first
- Focus: go-to-market, product-led growth, community-led growth, AI search visibility (GEO), building with AI-assisted development

## Pages

- [About](https://fmillan.com/about/): Self-taught, remote-first, still building.
- [Experience](https://fmillan.com/experience/): From co-founding Chile's first entrepreneurship agency to leading marketing and sales for Cynoia across 13 countries. Pick any role to go in depth.
- [Cynoia — Chief Marketing & Sales Officer](https://fmillan.com/experience/cynoia/): Led marketing and sales for Africa's all-in-one team workspace.
- [Shroomwell — Chief Marketing Officer](https://fmillan.com/experience/shroomwell/): Built the marketing division for a mycotechnology wellness brand.
- [Hive Identity — Co-founder & Chief Marketing Officer](https://fmillan.com/experience/hive-identity/): Co-founded a B2B KYC platform and ran marketing as CMO.
- [Semrush — Global Brand Evangelist & Influencer Marketing Manager](https://fmillan.com/experience/semrush/): First Global Brand Evangelist; part of the team through the ~$2B IPO.
- [Twilio — Senior Community Development Manager, EMEA](https://fmillan.com/experience/twilio/): Stayed on after the $3B acquisition to keep the startup program running.
- [SendGrid — Senior Community Development Manager, EMEA](https://fmillan.com/experience/sendgrid/): Nurtured and expanded the Accelerate program internationally.
- [Founder years — Chile and the early web](https://fmillan.com/experience/founder-years/): PymeFacil, Guubie, Biletu, SubmitMyStartup, Lanuu, Orange Media Labs.
- [Mentor, advisor, judge, organizer](https://fmillan.com/experience/mentoring/): Techstars, Startup Wise Guys, Katapult, Founder Institute and more.
- [GTM](https://fmillan.com/gtm/): I'm a builder-marketer. I run GTM — positioning, community, partnerships, product marketing — and I ship the product too.
- [Projects](https://fmillan.com/projects/): Nine projects. Pick one to go in depth.
- [Testimonials](https://fmillan.com/testimonials/): Recommendations from colleagues, founders and investors at SendGrid / Twilio, Semrush, Katapult Accelerator, Startup Wise Guys and more.
- [Contact](https://fmillan.com/contact/): If you think I could help your team, or you've got something interesting going on, just reach out. No formal pitch needed.

## Experience

- **Cynoia** — Chief Marketing & Sales Officer, 09/2024 – 03/2026. Led marketing and sales for a team workspace built for African distributed teams: native African languages, partnerships with telecoms and universities, cross-functional teams across Tunisia, Estonia, Senegal and Morocco. 6,000+ users across 13 countries, 10+ enterprise partners, 2 new markets.
- **Shroomwell** — Chief Marketing Officer, 09/2023 – 04/2024. Built a net-new marketing division for mycotechnology wellness products.
- **Hive Identity** — Co-founder & CMO, 05/2021 – 05/2023. KYC platform for startups. Raised a $500K seed round led by Isaac Saldana, founder of SendGrid. Built PLG from scratch until the war in Ukraine disrupted the team.
- **Semrush** — Global Brand Evangelist & Influencer Marketing Manager, 10/2019 – 04/2021. Worked with a 20,000+ member marketing influencer network; part of the team through the ~$2B IPO.
- **Twilio** — Senior Community Development Manager (EMEA), 02/2019 – 05/2019. Stayed on after the $3B acquisition of SendGrid to keep the startup program running.
- **SendGrid** — Senior Community Development Manager (EMEA), 05/2016 – 02/2019. Nurtured and expanded the Accelerate startup program out of Europe into Africa, the Middle East and Latin America: 550+ startup accounts, 50+ accelerator partners, 14.2M social reach. Part of the team through the ~$1.5B IPO.
- **Founder years (2000 – 2016)** — CTO & co-founder of PymeFacil (2010 – 2012), the first entrepreneurship agency in Chile: 93 startups helped launch, about 65% made it off the ground. Founder & CEO of Guubie.com (marketing automation for startups, 2011 – 2015), founder of Biletu.com (peer payments app, 2012 – 2015), SubmitMyStartup.com (2014), Lanuu.co (web builder, 2015 – 2016) and Orange Media Labs (web development, 2000 – 2016).
- **Mentor & advisor** — Startup Wise Guys (2016 – 2023), Katapult Accelerator (2017 – 2023), Techstars (2018 – 2020), Founder Institute Chisinau (2017 – 2020), TheFactory Oslo (2018 – 2020), Storytek Creative Hub (2018 – 2020), Fincube Istanbul (2019 – 2020), Global Innovation Catalyst (2021 – 2023). Judge for Start-Up Chile (2018 – 2021); board advisor for the SXSW Pitch competition (2018 – 2019).
- **Community** — Startup Grind Tallinn chapter director (2017 – 2019); Fuckup Nights Tallinn co-organizer (2017 – 2019). Investor in Mati Foods (2023 – present).

## Go-to-market, the way I see it

I'm a builder-marketer. I run GTM — positioning, community, partnerships, product marketing — and I ship the product too. It's carried a lot of titles: product marketing, growth, developer relations, community and ecosystem, partnerships, market entry, founding GTM. I care more about the work than the label.

- **Build an audience, don't rent one.** Community-driven growth is building an audience around your product instead of paying for attention.
- **Metrics that connect to revenue.** I know the difference between metrics that matter and vanity.
- **Product-led by default.** PLG is how I naturally think.
- **Close the loop between field and product.** What users experience goes back to the product team.
- **Different markets, same fundamentals.** The basics of building trust and communicating clearly work everywhere.

How it evolved: founder GTM in Chile with tight budgets (2010 – 2015) → ecosystems and communities at scale at SendGrid and Semrush (2016 – 2021) → owning the whole funnel as a co-founder and C-suite at Hive Identity and Cynoia (2021 – 2026) → builder-marketer in the AI era (2026 →). People increasingly ask AI assistants for "best tools for X" instead of running a search; if a site isn't structured for AI crawlers, it isn't in the answer. That gap is why I built BoostLLMs. Eight products this past year: web apps, macOS apps, Chrome extensions, AI agent systems, services on Cloudflare's edge. On Perch and AstroEdge, most of the code was written by AI agents directed against written specs — the agents are fast; the discipline is what keeps the output coherent.

## Projects

- [BoostLLMs](https://fmillan.com/projects/boostllms/): AI readiness scores for any website — and the fixes. Live product · free scan.
- [CheckLLMs](https://fmillan.com/projects/checkllms/): Audit your domain against 23 AI crawlers, graded 0–100. In development.
- [AstroEdge](https://fmillan.com/projects/astroedge/): Landing pages personalized per visitor at the edge. Pre-launch · MIT.
- [Perch](https://fmillan.com/projects/perch/): Your Chrome tabs, scored. Close the ones that don't matter. macOS · MIT · 65 tests.
- [Coruro](https://fmillan.com/projects/coruro/): Your local Git repos as a readable Kanban board. macOS · open source · MIT.
- [Jooby](https://fmillan.com/projects/jooby/): A native macOS app for your job search pipeline. macOS · open source.
- [accesy](https://fmillan.com/projects/accesy/): One-line accessibility preference widget. 12 controls, 6 profiles. Open source · MIT · v0.1.0.
- [Artkive](https://fmillan.com/projects/artkive/) (formerly Rolodex): Save every artist. Find them again fast. Free Chrome extension · in Web Store review.
- [Consentinel](https://fmillan.com/projects/consentinel/) (formerly Galletas4All): Self-hosted cookie consent on Cloudflare Workers + D1. npm · MIT · 54 tests.

## Optional

- [Full content for agents](https://fmillan.com/llms-full.txt): every project page in Markdown, plus experience and testimonials.
- [Resume in Markdown](https://fmillan.com/index.md)

---

# Projects in depth

## BoostLLMs

**AI readiness scores for your website — and the fixes.**

Status: Live product · free scan. Page: https://fmillan.com/projects/boostllms/

Scan any domain in 15 seconds. See exactly what's blocking AI crawlers from finding you — and get the fixes.

BoostLLMs is an AI readiness tool that scans any website domain and returns a 0–100 score across six categories that decide whether AI crawlers can read, understand, and surface your content. The free scan runs in about 15 seconds with no account required.

Tags: 19 AI crawlers checked · Score in ~15 seconds · Schema kept current automatically · llms.txt auto-generated

- [Run a free scan](https://boostllms.com)
- [Original page on fmillan.com](https://fmillan.com/projects/boostllms/)

### The gap — Obsessing over SEO while blocking GPTBot.

Somewhere around late 2024, I started noticing a pattern: companies spending real budget on SEO rankings while their robots.txt was quietly blocking GPTBot. The AI search channel was live and most sites were dark to it — not by design, just by neglect.

People increasingly ask AI assistants for "best tools for X" instead of running a search. If your site isn't structured for AI crawlers, you're not in the answer. No backlink strategy fixes that.

BoostLLMs starts with a free scan — paste a domain, get an AI-readiness score from 0–100 across six categories in about 15 seconds, no signup needed. The score isn't a vanity number: it's built from what blocks or helps AI crawlers.

### Features — What you get

- **Quick Scan — free** — No signup, no card · Paste a domain, get a score in ~15 seconds · Six categories: crawler access, sitemap, indexability, metadata, structured data, content depth · Per-category breakdown, not a single black-box number · Free forever. One domain.
- **Pro Scan — full site** — Every URL, per-page issues · Scans every URL in the project — 100, 400, 1,000+ pages · Per-page evidence, issue codes, and fix instructions · Score trends over time so you can see if it's improving · AI remediation prompt: one paste covers every issue found · $19/domain/month. 100-URL packs at $10 each.
- **Schema markup, generated for you** — No forms, nothing to maintain · Reads your existing content and generates accurate markup — nothing to configure · Delivered automatically — no manual updates or deploys needed · Updated markup goes live on its own as your content changes · No forms to fill or settings to map
- **llms.txt auto-generated** — The emerging standard, handled for you · Generates the Overview block, About section, and structured links · One click to regenerate when your content changes · Follows the llms.txt spec format · llms.txt isn't universally adopted yet — but early positioning in a new standard tends to matter.
- **Set and forget** — Install once, stay current · Install once — a single line added to your site · Schema stays current without touching your site again · Nothing to redo when your content changes
- **AI remediation prompt** — Ship every fix in one pass · After a Pro Scan, one ready-to-paste prompt · Covers every issue found across every page · Paste it into the AI tool you already use · Ship every fix in one pass

### How it works — Three steps.

- **Scan** — Paste your domain. Get an AI-readiness score in ~15 seconds across six categories. No account needed.
- **Audit** — Upgrade to Pro. Every URL on your site gets scanned, scored, and returned with per-page issue codes and fix instructions.
- **Fix** — Use the AI remediation prompt to ship every fix in one pass. Add one line to your site once — schema stays current from there.

### Motivation — Why I built it

Two things collided at the same time.

One: I kept seeing companies spending real budget on SEO while their robots.txt was quietly blocking GPTBot. The AI search channel was live and most sites were dark to it — not by design, just by neglect. That felt like a gap worth filling.

Two: I wanted to build a product where the hard part is invisible to the user but the output is meaningfully better because of it. The free scan takes 15 seconds. Getting that right — without asking anything of the user — was the interesting problem to solve.

The product is live. The free scan is genuinely free, no card required.

Built by Felipe Millán — a builder-marketer with over a decade in growth, SEO, and product, including time on the teams at SendGrid, Twilio, and Semrush.

### Honest limitations — Better up front than in the small print.

- **Some crawlers see updates later than others** — Schema updates are picked up when a crawler renders your pages dynamically. Crawlers that only read static content won't see the latest markup right away. Most major AI crawlers (GPTBot, ClaudeBot, PerplexityBot) handle this — but not all, and not on every crawl.
- **llms.txt is still an emerging standard** — Not all AI crawlers check for it yet. The spec exists, adoption is growing, but it isn't as established as robots.txt. I ship it anyway because early positioning in a new standard tends to matter.
- **URL credits are consumed on scan + schema generation** — A site with 500 URLs that you rescan weekly will burn through credits fast. The pricing page is explicit about this before you hit a billing surprise.
- **It's a live, improving product** — Scoring model, schema generation quality, and crawl depth are all actively being refined. There are rough edges I know about and am working through.

### Pricing — Scales with your site.

Free plan covers one domain forever. Pro adds full-site scanning and everything that fixes issues.

- **Free** — $0 · One domain, forever · Quick Scan — 0–100 score · Six-category breakdown · No signup required
- **Pro** — $19/domain/mo · 100 URLs included · +$10/100 URLs · Full-site scan — every URL · Per-page issue codes + fix instructions · Score trends over time · AI remediation prompt · Schema markup — generated and kept current automatically · llms.txt auto-generated

### FAQ — Common questions

**What exactly is an AI readiness score?**

It's a 0–100 composite score across six categories — crawler access, sitemap, indexability, metadata quality, structured data, and content depth — based on what blocks or helps AI crawlers read your site. Not a vanity metric: a low structured data score means AI can't extract entities from your pages. A blocked GPTBot means you're invisible to ChatGPT browsing.

**What AI crawlers do you check against?**

We check 19 known AI crawlers including GPTBot (OpenAI), ClaudeBot (Anthropic), PerplexityBot, Google-Extended, Amazonbot, and others. The full list is on the site.

**How does the schema update automatically?**

Once installed, schema is generated from your existing content and kept current as your pages change. The major AI crawlers — GPTBot, ClaudeBot, PerplexityBot — see updated markup without you touching your site again. The one caveat we're upfront about: not every crawler picks up updates on every crawl.

**What's llms.txt and why does it matter?**

llms.txt is a proposed standard — analogous to robots.txt — that gives AI crawlers a structured overview of your site: what it is, who it's for, and links to key content. It's not universally supported yet, but early adoption tends to matter when standards emerge. We generate the Overview block, About section, and structured links the spec defines.

**How are URL credits consumed?**

Credits are consumed on scan and on schema generation. A Pro plan includes 100 URLs. Additional packs are $10/100 URLs. If you rescan a 500-URL site frequently, do the math before committing — the pricing page is explicit about this.

**Is the free scan really free?**

Yes. Paste a domain, get a score. No signup, no card, no catch. The free plan covers one domain with the Quick Scan permanently. Pro adds full-site scanning, per-page issue codes, schema generation, and llms.txt.

### Find out if you're visible to AI crawlers. Free.

Paste a domain. Get a score in 15 seconds. No signup, no card. The free scan is genuinely free.

## CheckLLMs

**Which AI crawlers can reach your site?**

Status: In development. Page: https://fmillan.com/projects/checkllms/

Audit your domain against 23 AI scrapers — including GPTBot, ClaudeBot, and Google-Extended — and grade your exposure from 0 to 100.

Tags: In development · 23 Crawlers Indexed · CF Workers

- [Original page on fmillan.com](https://fmillan.com/projects/checkllms/)

- **23** — Known AI training, RAG, and search crawlers indexed
- **0–100** — Weighted protection score (Grade A–F)
- **100%** — Runs at the edge — no cookies, no tracking

CheckLLMs is a free AI crawler audit tool that checks any domain against 23 known AI training and search bots. It grades your exposure on a 0–100 scale (Grade A–F) and outputs ready-to-paste robots.txt, ai.txt, and edge config rules. No login, no account, results in under a minute.

### What it does — One scan. Clear fixes.

Most site owners configured their robots.txt before LLM bots became widespread. CheckLLMs resolves your domain and fetches your robots.txt and ai.txt files live, straight from your origin server.

It reads every directive, maps it against 23 scrapers (GPTBot, ClaudeBot, Google-Extended, Bytespider, CCBot, and more), and grades how well your domain is protected. Then it outputs clean, copy-paste config scripts for Nginx, Apache, Cloudflare WAF, and Next.js edge middleware.

### Scoring framework — Weighting critical bots

CheckLLMs grades your protection A–F using a weighted scoring model. Critical bots count 2× because they handle most of the LLM data ingestion happening today:

A crawler counts as protected if it is blocked either at the path level in robots.txt or at the purpose level via the newer ai.txt standard.

- GPTBot (OpenAI) · Weighted 2×
- ClaudeBot (Anthropic) · Weighted 2×
- Google-Extended (Google) · Weighted 2×
- Applebot-Extended (Apple) · Weighted 2×
- CCBot (Common Crawl) · Weighted 2×
- Bytespider (ByteDance) · Weighted 2×
- Meta-ExternalAgent (Meta) · Weighted 2×
- PerplexityBot (Perplexity) · Weighted 2×

### Features — Audit, grade, and fix in one scan

- **23-crawler directory** — Indexed database · - Training crawlers (GPTBot, ClaudeBot, CCBot) · - Inference and RAG crawlers (ChatGPT-User, Perplexity-User) · - Search indexers (OAI-SearchBot, PerplexityBot)
- **Fix generator** — Edge blocks and configs · - Generates standard robots.txt files · - Outputs ai.txt flags (No-Training, No-Inference) · - Provides edge rules for Cloudflare WAF, Nginx, and Next.js · - Outputs single-prompt configs you can hand to an AI agent
- **Edge native** — Fast, private execution · - Scans run from the Cloudflare Workers edge network · - DNS and domain ranking data via the Cloudflare Radar API · - Results cached per domain using Workers KV · - No user data saved to disk, no cookies

### Tech stack — How it's built

- **Edge Infrastructure** — Cloudflare Workers, Workers KV Caching, Cloudflare Radar API
- **Application** — Next.js 15 (App Router), TypeScript Strict Mode, Tailwind CSS
- **Security & Verification** — SHA-256 IP Hashing, Default-deny WAF generation, DNS record verification
- **Build Process** — Built with Claude Code, Built in the open, Deployed globally

### The builder — About CheckLLMs

CheckLLMs is built by Felipe Millán, who spent the past decade working at developer platforms (SendGrid, Twilio) and on SaaS go-to-market systems. He built it to give site owners clear visibility into which AI scrapers reach their content — and how to stop them.

The scanner runs on the same crawler database that powers BoostLLMs. One database, two tools: audit your exposure here, then work on your AI visibility over at BoostLLMs.

### FAQ — Common questions

**Is this another AI website builder?**

No. CheckLLMs is a security and crawling audit tool. It resolves your site's domain configuration, fetches robots.txt and ai.txt live, and checks whether AI scrapers are allowed to take your content for training or search indexing.

**What does "at the edge" mean for CheckLLMs?**

The audit runs on Cloudflare's edge functions (Cloudflare Workers). Requests go out from the same kind of network infrastructure AI bots use, so the result reflects what those bots would actually see — and it comes back fast.

**Do I need to know how to code?**

Not to audit your site. Just submit your URL. If gaps are found, CheckLLMs outputs ready-made code snippets for robots.txt and server configs (Nginx, Cloudflare WAF, and more) that you or your developer can paste in seconds.

**Is my visitors' data safe?**

Yes. CheckLLMs collects no personal data. Scan outputs are cached by domain in Cloudflare Workers KV, and visitor IPs are only hashed using SHA-256 for rate limiting purposes. Hashed IPs are purged automatically.

**What does it cost to run?**

CheckLLMs is free and requires no account. It runs on Cloudflare Workers, which falls within Cloudflare's free serverless tier. There are no paid plans.

Stack: Cloudflare Workers · Workers KV Caching · Cloudflare Radar API · Next.js 15 (App Router) · TypeScript Strict Mode · Tailwind CSS · SHA-256 IP Hashing · Default-deny WAF generation · DNS record verification · Built with Claude Code · Built in the open · Deployed globally

## AstroEdge

**Landing pages that know who's visiting — personalized at the edge.**

Status: Pre-launch · MIT. Page: https://fmillan.com/projects/astroedge/

What is AstroEdge? AstroEdge is a landing page engine that runs on Cloudflare's edge network. You describe a page in plain language, and it composes one from a locked set of sections and design tokens. Visitor personalization — name, A/B variant — happens in the response stream before the browser receives the HTML. No flicker, no client script, no server to manage.

Describe a page or pick a template. AstroEdge composes it from seven locked sections and a single design token file, then personalizes it per visitor in the edge response — ?firstName=Mike becomes "Hi, Mike" before the HTML reaches the browser. No flicker. No drift. No server to manage.

Honest note: AstroEdge is pre-launch. The engine works end to end. What you won't find here is a wall of customer logos — there aren't any yet. This is a real product, built in the open, still early.

Tags: Pre-launch · Built in the open · Cloudflare Pages · Cloudflare D1 · MIT license

- [Original page on fmillan.com](https://fmillan.com/projects/astroedge/)

### The problem — AI is good at writing a landing page once. It's bad at writing the same page twice.

Ask a model for a hero section three times and you get three different layouts, three color schemes, and a button that moved. That's fine for a mockup and a problem for a brand.

Personalization makes it worse. The usual fix — swap text with client-side JavaScript — means the visitor sees the generic version first, then a flicker as it rewrites. Search engines and link previews see the generic version and cache it.

AstroEdge takes a different path on both: the design kit is locked so the output stays consistent, and personalization runs in the edge response before the HTML reaches the browser.

### How it works — Four steps. Describe, compose, configure, ship.

- **Onboard your design** — Import a design you already have, or pick a starting palette from the gallery. Either way it lands as a locked set of tokens — colors, type, spacing, radii.
- **Describe the page** — "A waitlist page for a coffee subscription, urgent tone, one testimonial." AstroEdge doesn't invent a layout — it composes one from seven locked sections.
- **Drop in edge widgets** — Lead capture with spam protection and consent built in. A feedback board. An A/B test that runs at the edge with zero client JavaScript.
- **Ship to the edge** — One command builds, lint-gates, and deploys. Personalization happens in the response stream itself — the visitor's first paint is already personalized.

### What's inside — Personalization at the edge. Composition over creation.

- **Personalization at the edge — not in the browser** — `?firstName=Mike` becomes "Hi, Mike" before the HTML reaches the browser, rewritten in the response stream by Cloudflare's HTMLRewriter. First paint is correct. No flash of generic content, no client script, nothing for a scraper to cache wrong. Every token is allow-listed, length-capped, and encoded — a name field can't smuggle in a script.
- **Compose, don't create** — This is the core idea. Pages are assembled from seven locked sections — Header, Hero, Features, CTA, Testimonials, FAQ, Footer — each at a small set of approved variants, all sitting on one token-backed design system. Generation picks sections and variants. It never writes a novel layout, never invents a color, never reaches for an arbitrary pixel value. A lint gate fails the build if it tries. That's how you get AI speed without AI drift.
- **A shelf of edge widgets — integrated, not bolted on** — Lead capture, a social-proof counter, a feedback board, edge A/B testing. Each one is consent-gated by default: no consent, no write, no exception. The A/B test buckets visitors deterministically and swaps content in the same stream as personalization — so there's no flicker and the analytics attribute correctly from the very first view.
- **Consent the edge can enforce** — Most consent banners live in the browser and the server never hears about them. AstroEdge mirrors the visitor's choice into a first-party cookie the edge reads on every write. Default-deny: if the edge isn't sure, nothing gets stored. Lead capture, feedback, analytics linkage — all gated on a signal the server can verify.
- **Per-link analytics, no third-party pixel** — Views and conversions log to your own database at the edge. Visitor IDs are anonymous and hashed; referrers are stored host-only; there's no personal data in the analytics path. You can see how a variant performs without renting a tracking script from anyone.
- **Social assets, generated at the edge** — Open-graph images and carousel slides rendered on-brand from a page's own content, using the same design tokens. Pure JavaScript and WASM — no headless browser, no paid render service. (Honest caveat, stated plainly in the docs: personalized link previews are unreliable because platforms cache the canonical image and strip query params. The solid feature is downloadable, on-brand assets — not personalized unfurls.)
- **One engine, many surfaces** — The whole product is a headless engine that runs on its own. A desktop cockpit, a template gallery, and a Chrome design-extractor all drive the same engine — none of them reimplements it. Build from the command line, from the desktop app, or by extracting the bones of a page you like. Same engine underneath.
- **Runs on the free tier** — The default architecture fits inside Cloudflare's free limits, and every stage was checked against that budget. Static pages serve effectively unlimited; the edge functions are metered and the build was designed to stay well under the daily ceiling. Cheap to run is a feature, not an accident.

### Deep dive — Compose-don't-create

Most "AI website builder" tools let the model write whatever it wants and hope it looks good. It looks good once. Then you ask for a second page and the system has quietly drifted — new spacing, a slightly different blue, a font weight nobody chose.

AstroEdge fixes that by making generation a composition problem instead of a creation problem:

The result: pages that ship in minutes and still look like they came from the same company.

- Tokens are the source of truth — One file defines the design. Change it once, every page updates. There is no second place a color can come from.
- Sections are bounded — Seven of them, each with a handful of approved variants. The model picks from a menu; it doesn't paint on a blank canvas.
- A lint gate is the hard stop — Arbitrary values, inline styles, raw hex codes, stray CSS — the build fails on all of them. Not a warning. A failed build.

### Designed for — Three kinds of people this was built for

If you've ever shipped an AI-built page and then spent an hour fixing the parts that drifted, this is the part that's different.

- **Marketers** — who want personalized, on-brand landers without a ticket to engineering for every variant.
- **Solo founders** — who need fast pages that don't look AI-generated and don't cost anything to run.
- **Agencies** — that want a locked system so every page across every client stays on-brand.

### How I built it — About the build

AstroEdge was built solo, in the open, by one marketer who codes — not a team, not a funded startup. The interesting part is how: most of the code was written by Claude Code agents, but every decision — the architecture, the security model, the design lock, what to cut — was a human one.

It ran as 44 stages, one commit each, with a named cast of agents at different capability tiers, phase gates that didn't open until the work behind them was verified, and a review step before every high-stakes change. Less "let the AI vibe a website" and more "manage AI like a team that needs a manager."

If that approach is interesting to you — as a user, a collaborator, or otherwise — the door's open.

### FAQ — Common questions

**Is this another AI website builder?**

Sort of, but backwards. Most of them let AI design freely and you clean up the drift. AstroEdge locks the design first and lets AI only compose within it. Speed of AI, consistency of a design system.

**What does "at the edge" actually mean?**

Your page is served from Cloudflare's network, close to the visitor, and the personalization happens in that same response — not in a round-trip to a server, not in the browser after load. It's fast because there's no second step.

**Do I need to know how to code?**

To use the engine through the plugin: you describe pages in plain language and pick templates. To self-host and ship: you'll run a couple of commands. It's not no-code, but it's close to describe-and-ship.

**Is my visitors' data safe?**

Writes are consent-gated by default-deny, SQL is parameterized, personalization input is sanitized and encoded, visitor IDs are anonymous and hashed, and referrers are stored host-only. There's no third-party tracking pixel in the default build.

**What does it cost to run?**

The default setup is built to fit Cloudflare's free tier. No server, no fixed monthly infra bill for normal volume.

**Can I see real code?**

Yes. The whole thing was built in the open, one commit per stage.

**Is it production-ready?**

The engine is deployed and the security, consent, and personalization paths are all tested end to end. It's pre-launch, which means there are no paying customers yet and the feature set is still growing — honest about that. If you want to be one of the first real users, the GitHub repo is the place to start.

## Perch

**Your Chrome tabs, scored.**

Status: macOS · MIT · 65 tests. Page: https://fmillan.com/projects/perch/

Close the ones that don't matter.

Perch sits in your menu bar, tracks real tab usage, and surfaces the ones worth closing — with a reason for each. One click closes them.

Tags: macOS only · Tauri v2 + Rust · 65 tests · Local-first · MIT license

- [View on GitHub](https://github.com/felipemillan/perch)
- [Original page on fmillan.com](https://fmillan.com/projects/perch/)

Perch is a macOS menu-bar app built with Tauri v2 and Rust. It monitors your Chrome tabs through a local WebSocket extension, scores each tab against four staleness rules — Zombie, Duplicate, Stale, and Domain pileup — and shows a ranked list of tabs worth closing. Everything stays on your machine, with no account required.

### What it is — 20% of a tab manager. The part you'd actually use.

I keep ~180 Chrome tabs open. I'm not proud of it. Most tab managers either suspend memory or bury everything in a sidebar I never open. I wanted something smaller: a number in the menu bar, and an honest answer to "which of these can I close?"

Perch watches your tabs and tracks how much time you spend on each one — but only while Chrome is focused and you're not idle, so background tabs don't pad the numbers. Then it flags the ones that look closeable.

Each suggestion shows why it's flagged. Tabs you genuinely use a lot get demoted, not nagged. You close from the panel; the tab disappears in Chrome.

At the top, a single Health number sums all of that into one glanceable score — click it to see exactly how it's worked out.

- Stale — you haven't touched it in a day.
- Zombie — opened hours ago, never once looked at.
- Duplicate — the same page open in three tabs.
- Domain pileup — eleven GitHub tabs, again.

### What's in it — Six views. One panel.

- **Worth-closing list** — Every flagged tab with its reasons, ranked by score. The "Nuke all" button closes the lot in one shot. Each tab shows why it was flagged — Duplicate, Stale, Zombie, or Domain pileup — so nothing is a surprise.
- **All tabs — grouped, sortable, searchable** — Every open tab across every window, grouped by domain. Sort by last active, active time, or domain. A "Close all N" button beside each domain closes the whole cluster at once. Search filters by title or URL.
- **Windows view** — Tabs organized by Chrome window, collapsible. Windows with a high proportion of flagged tabs get a "Recommended to close" badge. Focus a window or close it entirely — one click.
- **Playing — only what makes sound** — A dedicated view that lists only tabs currently playing audio. The moment you hear an unexpected sound, one look tells you exactly which tab it is.
- **History + restore** — Recently-closed tabs listed with domain and time. One click restores any of them, Chrome-style. Accidentally nuked something? It's here.
- **Stats — where your time goes** — Lifetime tabs closed ("reclaimed") and a bar chart of active time by domain — only time while Chrome was focused and you weren't idle. The honest picture of what you use.

### Why I built it — Two reasons, honestly.

- **One — I wanted the tool.** — A glanceable tab count and a short "worth closing" list is the 20% of a tab manager I'd use every day.
- **Two — I wanted to find out how far AI agents have come.** — Not a to-do demo, but something with a Rust backend, a browser extension, a local database, and a wire protocol between them. So I treated it like a real build — with a PRD, frozen contracts, and parallel agents — and wrote about what worked and what didn't.

### How it works — Two processes, one loopback.

- **The extension is just a sensor** — It streams tab and idle events over a WebSocket bound to localhost. Minimal permissions — tabs, idle, alarms. No host access, no reading page content.
- **The app is the brain** — It stores everything locally in SQLite, works out active time, scores the tabs, and draws the panel under the tray icon. It rejects any WebSocket connection that isn't the extension.
- **Nothing leaves the machine** — No server, no accounts, no analytics, no network egress. The WebSocket is loopback-only. The SQLite database lives on your disk.

```
Chrome ──tabs/windows/idle──▶ MV3 extension (the sensor)
                                   │  loopback WebSocket (127.0.0.1)
                                   ▼
                         Tauri app (the brain + UI)
                          ├─ local SQLite
                          ├─ time attributor
                          ├─ close-suggestion heuristics
                          └─ AppleScript fallback (when extension drops)
                                   │
                                   ▼
                            menu-bar panel
```

### Health score — One number. Transparent maths.

Health answers a single question: what share of your open tabs are worth closing? It's three steps, all visible.

### The formula

100 means nothing is flagged. Lower means a bigger slice of what's open is clutter. No tabs open at all → Health 100. Clamped to 0–100.

- Example — 180 tabs open, 36 flagged worth closing → 100 − round(36 / 180 × 100) = 100 − 20 = Health 80

```
Health = 100 − round( worth_closing / open_tabs × 100 )
```

### Step 1 — Score each tab against four rules

Every open, non-pinned tab is checked against four rules. Rules stack — a tab can trip several, and the weights add up. Pinned tabs are skipped entirely.

- Zombie — Opened over 2h ago and never once focused (+1.5)
- Duplicate — The same page (normalized URL) is already open in another tab (+1.2)
- Stale — No focus for over 24h (+1.0)
- Domain pileup — More than 8 tabs on one domain (counts the overflow) (+1.0)

### Step 2 — Demote the tabs you actually use

A raw rule score isn't the final word. Perch keeps lifetime active-time per URL locally, and uses it to demote pages you genuinely live in — so your daily drivers don't get nagged just for sitting open.

The more you've actually used a URL over its lifetime, the lower the multiplier — down to a floor of 0.4×. A page you've never touched keeps its full score (1.0×).

```
multiplier = 1 − 0.6 × ( engagement / (1 + engagement) )
final_score = raw_score × multiplier
```

### Step 3 — Count what crosses the line

A tab is worth closing when its final score clears the threshold (default > 1.0). Deliberately tuned so a single soft signal on a page you use a lot won't trip it — but a never-opened zombie (1.5), or a couple of stacked reasons, will.

- **It's yours to tune** — The thresholds — stale hours, zombie hours, domain max — all live in Settings. Tighten or loosen them and Health re-scores live.

### The stack — What it's built with

- **App** — Tauri v2, Rust, macOS only, tray icon, no dock
- **Extension** — Chrome MV3, tabs, idle, alarms, no host access
- **Transport** — loopback WebSocket, 127.0.0.1 only, origin-checked
- **Storage** — SQLite (rusqlite), local-only, parameterized queries
- **UI** — Vanilla TypeScript, Vite, light/dark system-matched
- **Quality** — 65 unit tests, security audit, MIT licensed

### How I built Perch with AI agents — I didn't write most of this code. I directed it.

Here's the short version: I built Perch by directing AI agents against frozen contracts, and the discipline mattered more than the speed. Letting an agent "just build the app" gives you mush. What worked was treating it like running a small engineering team — a spec first, then parallel agents, then real use until it broke.

My job wasn't typing. It was scoping the problem, deciding the open questions, keeping the contracts honest, and using the thing until it broke. The agents are fast; the discipline is what keeps the output coherent.

- **01 — Spec before code** — I started with a PRD — goals, non-goals, the data model, the heuristics, acceptance criteria. No code until that was real.
- **02 — A Phase 0 gate** — Before anything got built, one pass verified every shaky assumption (Tauri APIs, MV3 service-worker lifecycle, the SQLite approach) against current docs — not from memory — and froze the interface contracts: the WebSocket protocol, the database schema, and the app's command layer.
- **03 — Frozen contracts made real parallelism possible** — With the interfaces nailed down, I fanned out several agents at once, each owning a separate set of files. They couldn't collide because they all coded against the same frozen source of truth — and I matched the model to each task's complexity.
- **04 — Integration, then real use** — I wired it together, ran it on my Mac with real Chrome, and found bugs the only way you ever really do — by clicking around. The Close button threw an error; the backend and frontend disagreed on one argument's shape. Found it, fixed it, in minutes.
- **05 — An audit before publishing** — I ran an AI-assisted security and OSS-readiness audit over the whole repo — secrets, dependencies, license, the works — and fixed what it flagged before making it public.

### Frequently asked questions about building Perch

### Honest limitations — Worth knowing before you run it.

- **macOS + Chrome only** — That's the scope, on purpose.
- **Not notarized or in the App Store** — It's a v1 and a portfolio project — it runs and it's tested.
- **No per-tab memory** — Chrome doesn't expose per-tab memory to installed extensions, so I left it out rather than fake it.
- **"Works on my machine" is verified** — Yours may differ. It's open source so you can read every line and run it yourself.

### FAQ

**How did you scope what to give each agent?**

I matched the model to the task's complexity. Boilerplate (struct definitions, test scaffolding) went to a faster model. Anything touching the heuristics or the scoring logic, where subtlety mattered, got a slower, more capable one. And I wrote the briefs with explicit file-scope boundaries so agents couldn't step on each other's work.

**What's the PRD actually look like?**

It's in the repo — have a look. It's a plain markdown document covering the problem, the non-goals (just as important), the data model, the scoring rules with rationale, the WebSocket schema, and the acceptance criteria for each feature. The frozen contracts live alongside it: the full message type union, the DB schema, and the Tauri command signatures.

That document was the single source of truth every agent brief referred back to.

**Did you hit any situations the agents couldn't handle?**

A few. When click-to-focus silently did nothing, the agents couldn't diagnose it — because it turned out to be a stale extension in Chrome, not a code problem. That kind of environment-level debugging required me to be at the machine and watch what happened.

The other category was anything requiring genuine product judgment: deciding the zombie threshold, tuning the engagement demoting curve so it felt right rather than just correct. Those stayed with me.

Stack: Tauri v2 · Rust · macOS only, tray icon, no dock · Chrome MV3 · tabs · idle · alarms · no host access · loopback WebSocket · 127.0.0.1 only · origin-checked · SQLite (rusqlite) · local-only · parameterized queries · Vanilla TypeScript · Vite · light/dark system-matched · 65 unit tests · security audit · MIT licensed

## Coruro

**Coruro — your Git repos as a readable board.**

Status: macOS · open source · MIT. Page: https://fmillan.com/projects/coruro/

Scans a local folder, reads every repo, and shows each as a card — on-device AI, no upload, no account.

Coruro is an open-source macOS app that scans a local folder of Git repositories and shows each one as a card on a five-column Kanban board. On-device AI summaries, via Apple FoundationModels, describe each repo without uploading your code or needing an API key.

Each card shows what the project is, what it's built in, whether it's in sync, and how alive it is — without opening anything. The AI summaries run locally, so your code never leaves the machine. Clone the repo and run your own build — no signed installer, no store, no account.

Tags: No account · No cloud — AI runs on your Mac · No API keys · MIT · Open source

- [Clone the repo](https://github.com/felipemillan/coruro)
- [Original page on fmillan.com](https://fmillan.com/projects/coruro/)

### The problem — A folder of repos is a graveyard.

Local clones, half-finished side projects, client work, things I starred and forgot. Names like app-final-2 tell me nothing, and opening each one to remember what it was is its own afternoon.

Coruro scans a root folder, finds every Git repo, and draws each as a card on a five-column board — Inbox · Backlog · Active · Review · Done. Drag a repo to where it lives. The card carries the rest.

Each card reads like a project's vital signs: what it is, what it's built in, whether it's in sync, and how alive it is — at a glance, without opening anything.

### The card — Vital signs, at a glance.

Each card adapts to what the repo is — GitHub repos get different stats than local-only ones.

- **What it is** — A one-line AI summary and a few topic tags, generated on-device by Apple FoundationModels. No network call, no API key.
- **What it's built in** — A language-tinted header so the stack registers before you read a word. Rust gets one color, TypeScript another.
- **Whether it's in sync** — Current branch, dirty / ahead / behind, and CI status — all read-only. Coruro never touches your working tree.
- **How alive it is** — GitHub repos show stars, issues, and forks. Local-only repos show commits, branches, and last-commit age. The grid decides which.

### What's inside — Six features, one board.

- **Editorial repo cards** — Information density, not decoration · White card, soft shadow, language-tint header · GitHub repos: stars, issues, forks · Local-only repos: commits, branches, last-commit age · Card decides which stat grid to show
- **On-device AI summaries** — Apple FoundationModels, no network · One-line description and topic tags per repo · Runs automatically after a scan · Content-hash cached — runs once per change · Works without summaries on unsupported Macs — cards still show all Git data · Requires Apple Silicon + macOS 26 + Apple Intelligence. Without it, the app still works fully.
- **Local Git status** — Read-only, always current · Current branch, clean or dirty · Ahead / behind upstream · Never touches your working tree · No git commands that modify state
- **GitHub enrichment** — Stars, issues, CI — cached locally · Stars, forks, open issues, PRs · CI status and latest release · Topics and license · Token lives in macOS Keychain, never on disk · Optional. Without a token you still get local Git status and AI summaries.
- **Kanban workflow** — Inbox · Backlog · Active · Review · Done · Drag repos between columns · Per-repo notes timeline · State stored in one JSON file alongside the repo · Quick-open in editor, terminal, Finder, or GitHub
- **Quick actions** — One click to context-switch · Open in your editor · Open in terminal · Reveal in Finder · Open on GitHub

### Architecture — How it works

The Rust backend reads local Git state and GitHub data. For the AI, it builds a small context per repo — a README excerpt, the languages, recent commit subjects, the top-level file names — capped to fit the model's window, and hands it to a standalone Swift binary. That binary runs Apple's on-device model and returns structured output. A serial, content-hash-cached queue runs it over each repo after a scan. Nothing about your code is sent to a server.

```
  Folder of repos
        │  scan
        ▼
  Tauri app (Rust) ──► local Git (read-only): branch, ahead/behind, stats
        │             └► GitHub API: stars, issues, CI, release (cached)
        │
        │  repo context (README excerpt, languages,
        │  recent commit subjects, top-level files)
        ▼
  Swift sidecar ──► Apple FoundationModels (on-device LLM)
        │           returns { summary, tags }
        ▼
  Editorial card on the board
```

### Motivation — Why I built it

Two reasons, honestly.

One: I wanted the tool. A wall of repos I can actually read beats a folder I have to excavate. The 20% of a repo manager I'd use every day is "tell me what this is without making me open it."

Two: I wanted to put Apple's on-device model to real work — not a toy prompt, but a summarizer wired into a Rust backend through a Swift sidecar, cached, bounded to the model's context window, and degrading gracefully on Macs that can't run it. Something with real moving parts. That half turned out to be as interesting as the app.

And because it's open source, you don't take my word for any of the privacy claims — you read the code, build it, and run it yourself.

### Build discipline — The vibe-code experience — the actual story.

I didn't hand-write most of this. I directed it — and that's the point. Letting an agent "just build the board" gives you mush. What worked was running it like a small engineering team.

- **Spec before code** — Each cycle — the card redesign, the AI analysis — started as a written design doc: goals, the data shape, acceptance criteria. No code until that was real.
- **Decompose, then fan out** — I broke each cycle into bite-sized tasks with frozen interfaces, then ran several agents in parallel — lighter models on the mechanical files, the strongest available model on the integration and the novel bits.
- **Verify independently** — The agents wrote and tested their files but never committed. I ran the full test suite, the Rust build, and the type-check myself, then committed in logical chunks.
- **Use it until it breaks** — The AI produced nothing on the first wired-up run. I traced it to four separate problems in the Swift-sidecar spawn path — found each by running the real app and watching, not by reading diffs.
- **A security pass before publishing** — An automated review flagged an over-broad argument permission on the sidecar. I tightened it before it went anywhere near a release.
- **The discipline is the product** — My job wasn't typing. It was scoping each cycle, freezing the contracts, picking which model does what, and using the thing until it broke. The agents do the volume; the discipline is what makes them produce something that holds together.

### Tech stack — For the curious

- **App framework** — Tauri v2, Rust, macOS only
- **Board UI** — React 19, TypeScript, Zustand, Tailwind CSS 4
- **AI summarizer** — Apple FoundationModels, Swift sidecar, @Generable structured output
- **Source data** — local Git (read-only), GitHub API, macOS Keychain
- **Data layer** — local-first, single JSON file, no server, no telemetry
- **Quality** — full unit-test suite, security-reviewed, MIT licensed

### Honest limitations — The things to know up front.

- **macOS only** — The AI needs Apple Silicon + macOS 26 + Apple Intelligence on. Without it the app works fully — you just don't get the summaries.
- **You build it from source** — There's no signed installer and there isn't meant to be. I don't run an Apple Developer account, and an open-source tool you compile yourself doesn't need one. Clone the repo, run the build script, launch it.
- **It's a v1 and a portfolio project** — It runs, it's tested, but it's a thing you build and run, not a product in a store.
- **GitHub enrichment needs a token** — Optional. It lives in your Keychain, never on disk.

### What's next — Roadmap

- Semantic search across repos, on-device (Apple NLContextualEmbedding)
- Repo relationships, inferred from AI tags and embeddings
- A statistics view that aggregates AI-derived insights
- Smoother build-from-source onboarding — one script, clear prerequisites

### Your code never leaves the machine.

The AI model runs locally through Apple's FoundationModels framework. The only optional network calls are to the GitHub API, going directly from your machine to GitHub. No intermediary, no telemetry, no server. And because the whole thing is open source, you don't take my word for any of it — you read the code.

### FAQ — Questions people actually ask

**Do I need an Apple Developer account?**

No — and that's intentional. There's no signed installer and there isn't meant to be. You clone the repo, run the build script, and launch the app yourself. An open-source tool you compile from source doesn't need a developer account.

**Does the AI work on my Mac?**

The on-device summaries require Apple Silicon, macOS 26, and Apple Intelligence enabled. Without it, Coruro still works fully — you just get cards without the AI summary, and a one-time banner explains why.

**Is my code uploaded anywhere?**

No. The AI model runs on your Mac through Apple's FoundationModels framework. Your code never leaves the machine. The only optional network calls are to the GitHub API for enrichment data — and those go directly from your machine to GitHub, not through any intermediary.

**What does GitHub enrichment require?**

A personal access token, optional. Without it you still get local Git status and on-device AI summaries — just no stars, issues, or CI data. When you add a token it lives in your macOS Keychain, never written to disk.

**I don't have 50 repos. Is this useful for me?**

Coruro is most useful once you have 15–20+ local clones you've stopped tracking. It solves the problem of having so many repos you've lost the map of them. If you still know what's in every folder, a Finder window is fine.

**Is this production software?**

It's a v1 portfolio project. It runs, it's tested, and it has a security pass behind it — but you build it from source, not install it from a store. Treat it accordingly.

### Build it, run it, read the code.

Open source. No installer, no account, no API keys. Clone the repo, run the build script, and your repos become a board you can actually read.

Stack: Tauri v2 · Rust · macOS only · React 19 · TypeScript · Zustand · Tailwind CSS 4 · Apple FoundationModels · Swift sidecar · @Generable structured output · local Git (read-only) · GitHub API · macOS Keychain · local-first · single JSON file · no server · no telemetry · full unit-test suite · security-reviewed · MIT licensed

## Jooby

**Jooby — native macOS app for your job search pipeline.**

Status: macOS · open source. Page: https://fmillan.com/projects/jooby/

Built on career-ops. Open source. Contributions welcome.

- [View on GitHub](https://github.com/felipemillan/career-ops-desktop)
- [Original page on fmillan.com](https://fmillan.com/projects/jooby/)

Jooby started as a dashboard on top of the career-ops CLI toolset. It's grown into a native macOS app with a Kanban, AI evaluation triggers, embedded terminal, and analytics. Still in active development. If it solves a problem you have too, fork it, run it, or help build it.

### Why I built it — I'm job hunting. Using the time deliberately.

I started with career-ops as a user — it handled the hard parts of the pipeline well. Then I noticed the gap: no UI, nothing to look at, everything in Markdown and terminal output. The obvious next step was to build a dashboard. So I did.

But the dashboard was also a test. I'm using this stretch — the job search, the free time between things — to push what I can build with AI-assisted development. How far can it go on something with real moving parts? The web dashboard was one answer. Moving it to a native Tauri app with a Rust backend was the next question. A proper PTY for the terminal. Process spawning with a real security model. Atomic writes with build-time enforcement. Each new layer was a new thing to learn.

The plan is to keep going. More features, better polish, more surface area for the things career-ops can do. And since it's open source, if you're also using career-ops and want to help build the UI layer — or just have a feature you need — the door is open.

### How it works — Four steps.

- **Point Jooby at the companion repo** — Set CAREER_OPS_PATH or pick the folder in-app. The read-only views, analytics, and terminal work immediately. The action buttons need the companion scripts present.
- **Browse the pipeline** — Applications view, Kanban, scan history, and reports — all rendered from your existing Markdown and YAML files.
- **Trigger actions** — Scan for new roles, run AI evaluations against your CV, generate PDFs — from the action bar or from the terminal.
- **Track** — Drag applications through stages. Analytics update automatically.

### What's in it — Five core features.

- **Pipeline views** — Read-only views of your applications, pipeline status, scan history, and generated reports — parsed in TypeScript, rendered as tables and Markdown. Applications Kanban with drag-and-drop status changes.
- **Action bar** — One-click triggers for companion scripts: scan, merge, dedup, pattern analysis, follow-up cadence, PDF/LaTeX generation. Headless AI evaluation through your local claude CLI.
- **Analytics** — KPIs, pipeline funnel, score distribution, weekly activity, status timeline. Built in pure CSS and SVG — no chart library, nothing phoning home.
- **Embedded terminal** — Real PTY running your login shell (xterm.js). Interactive claude and /career-ops commands work exactly as they do in Terminal.app.
- **Privacy + security** — No inbound network surface. Process spawning uses argv arrays — no shell strings. Inputs validated and path-contained. Telemetry optional, off by default, self-hostable.

### Tech stack — For the curious

- **Frontend** — React 19, TypeScript, Vite 7, Tailwind v4, shadcn/ui, TanStack Table, @dnd-kit
- **Backend + app** — Tauri v2, Rust, process spawning, input validation, atomic writes
- **Terminal** — xterm.js, portable-pty, real PTY
- **Data** — Markdown + YAML on disk, no database, no telemetry by default, PostHog optional
- **AI evaluation, scanning, PDF** — companion career-ops repo, Node scripts, Claude CLI

### Honest limitations — What's not here yet.

- Requires setup — Node, Rust, Tauri system dependencies, and the companion career-ops repo. No installer yet — that's on the list.
- macOS only in practice — Tauri is cross-platform but only macOS has been tested and exercised.
- Action buttons need the companion repo — Read-only views, analytics, and the embedded terminal work standalone. The action bar doesn't.
- AI evaluation requires claude CLI on your PATH — That means a Claude Code subscription. No bundled model.
- Active development, not finished — Works well for what it does today. There are rough edges and features missing. That's the point — it's growing.

### FAQ — Questions people ask before cloning it

**Do I need to be a developer to use Jooby?**

Jooby needs you to be comfortable running a few terminal commands during setup. After that, you mostly work from the web dashboard and your browser. You do not need to write or read code to use it day to day.

**What does Jooby cost?**

Jooby is free and open source. You bring your own AI access — Claude Code or a Gemini API key — and, optionally, a free Firecrawl key for automated scanning. There is no subscription and no hosted service to pay for.

**Does Jooby apply to jobs for me?**

Jooby does not auto-apply. It evaluates fit, drafts tailored CVs and cover letters, and organizes your pipeline. Every submission is manual — you review each draft and send it yourself. The tool never hits submit on your behalf.

**Where does my data go?**

Your data stays on your machine. Jooby has no hosting and collects nothing. The only data that leaves your computer is what you send to the AI provider you choose, exactly like using their app directly.

**Is Jooby its own AI model?**

No. Jooby is not an AI model. The reasoning runs on existing AI CLIs — Claude Code or Gemini. The evaluation logic comes from the open-source career-ops project by santifer, which I forked and extended.

**Can I use Jooby for any role or industry?**

Yes. During setup, you teach Jooby your background, your stories, and the roles you are targeting, and it adapts its scoring and drafting to them. It is not tied to any single industry or job type.

### Come build it with me.

Jooby is open source and actively being developed. If you're using career-ops and want a UI layer, this is it. If there's a feature you need, open an issue or a PR — the CONTRIBUTING guide is straightforward. If you just want to follow along, a star on GitHub helps more than it sounds.

github.com/felipemillan/career-ops-desktop

Stack: React 19 · TypeScript · Vite 7 · Tailwind v4 · shadcn/ui · TanStack Table · @dnd-kit · Tauri v2 · Rust · process spawning · input validation · atomic writes · xterm.js · portable-pty · real PTY · Markdown + YAML on disk · no database · no telemetry by default · PostHog optional · companion career-ops repo · Node scripts · Claude CLI · open source

## accesy

**One line. Open source. Actually readable.**

Status: Open source · MIT · v0.1.0. Page: https://fmillan.com/projects/accesy/

accesy adds a floating button to your page. Visitors get twelve reading controls and six one-tap profiles — stored in their own browser, nothing sent to a server. Free, MIT-licensed, and readable end to end.

accesy is a free, MIT-licensed accessibility preference widget. You drop it into any web project with one line of code. Visitors get 12 reading controls and 6 one-tap profiles — dyslexia, low vision, ADHD, colour-blind, motor-impaired, seizure-safe — saved in their own browser. No backend, no tracking, no subscription.

Tags: Open source · MIT · v0.1.0

- [Overlay Fact Sheet](https://overlayfactsheet.com/)
- [Original page on fmillan.com](https://fmillan.com/projects/accesy/)

- Free forever
- MIT licensed — read every line
- One-line install
- No backend, no tracking

### The problem — Two options, both wrong.

When I wanted to add accessibility controls to my own projects, I kept hitting the same two options: build the panel from scratch every time, or drop in a paid overlay that charges a monthly subscription and makes compliance claims that disability advocates actively dispute.

Neither sat right. So I built the thing I wanted — a small, honest widget I could read end to end, drop into any project, and trust.

accesy adds a floating button to your page. A visitor clicks it (or hits alt+a) and a panel slides out with twelve reading controls and six ready-made profiles. Their choice is saved in their own browser. No account, no tracking, no backend. Entirely client-side.

### Features — Twelve controls. Six profiles. One line to install.

- **Twelve reading controls** — Visitor picks what helps them read. High contrast, invert colours; Bigger text, text spacing, line height; Legible fonts, dyslexia font; Pause animations, highlight links; Big cursor, hide images, saturation
- **Six one-tap profiles** — Right set of controls, one click. Dyslexia; Low vision; ADHD; Colour-blind; Motor-impaired; Seizure-safe
- **One line to install** — Zero-config default. <Accesy /> in React — zero configuration; One <script> tag for any other stack; Auto-detects your app root; No setup, no options required
- **Preferences that persist** — Stored in the visitor's browser. Choices saved to localStorage; Restored on the next visit automatically; No login, nothing leaves their device; No backend required
- **Headless core** — Full control when you want it. Engine is separate from the UI; Use the React panel as-is, or restyle with theme tokens; Drive from your own components with useAccesy(); Framework-agnostic headless core
- **Built to behave** — Works inside modern stacks. SSR-safe; React 18+ concurrent-safe; Keyboard-operable, closes on Escape; Small bundle, no dependencies dragged in. English and Spanish included. Adding a locale is a small, documented pull request.

### Motivation — Why I built it

The accessibility-overlay industry has a credibility problem, and it's earned. Widgets that promise "instant ADA compliance" have been the subject of lawsuits and the Overlay Fact Sheet, signed by over 700 accessibility professionals — because an overlay bolted onto an inaccessible site doesn't make it accessible. It just adds a button.

I didn't want to add to that. accesy isn't sold as compliance. It's a preference layer: it lets a visitor adjust how your page reads for them. That's genuinely useful, and it's honest about what it is. A clear, narrow promise paired with open code — that was the version worth shipping.

The other half is selfish. I wanted a widget I controlled — one I could drop into every project I ship, read in full, and never pay a subscription for. So I built it, and I open-sourced it in case it saves someone else the same trouble.

### Honest limitations — Better up front than in the small print.

- **This is not a compliance product** — An overlay cannot fix an inaccessible site. Real accessibility lives in your actual markup — semantic HTML, alt text, keyboard navigation, colour contrast in your real design. accesy gives users reading preferences on top of a site that's already doing that work. If anyone sells you a widget as 'instant legal compliance,' walk away.
- **It's an early release** — This is the first public version (0.1.0). The core is well-tested and the API is stable enough to build on, but there are rough edges I know about and am working through in the open.
- **The legible-fonts option loads from a CDN** — When a visitor turns on legible fonts, the typeface is fetched from jsDelivr. It's opt-in and CSS-only, but if you run a strict Content-Security-Policy, that's worth knowing before you ship it.
- **Two languages so far** — The panel ships with English and Spanish. Adding a locale is a small, well-documented pull request — but right now, that's what's in the box.

### Stack — For the curious

- **Core** — TypeScript, framework-agnostic, localStorage API, CSS custom properties
- **React package** — React 18+, concurrent-safe, SSR-safe, useAccesy() hook, theme tokens
- **Distribution** — headless core export
- **Quality** — MIT licensed, well-tested core, keyboard-accessible, no external dependencies

### FAQ — What people ask

**Does this make my site accessible?**

No — and any widget that claims it does is lying. Real accessibility lives in your actual markup: semantic HTML, alt text, keyboard navigation, colour contrast. accesy gives your visitors preference controls on top of a site that's already doing that work. It's a preference layer, not a compliance shortcut.

**Is this for React only?**

No. There are three delivery options from one engine: a headless core, a React component (<Accesy />), and a single script tag for any other stack. The script tag version auto-detects your app root with no setup.

**Where are user preferences stored?**

In the visitor's own browser, via localStorage. Nothing is sent to a server. No account, no tracking, no backend required.

**What's the bundle impact?**

Small. No external dependencies are dragged into your app. The legible-fonts option loads one typeface from jsDelivr — opt-in and CSS-only, nothing auto-loaded.

**Can I customise the look?**

Yes. You can restyle the panel with theme tokens, or drive the whole thing from your own components using the useAccesy() hook. The headless core is separated from the UI specifically for this.

**Is it SSR-safe?**

Yes. accesy is SSR-safe and React 18+ concurrent-safe. It is keyboard-operable and closes on Escape, and it has no external runtime dependencies.

### Free, open source, one line to drop in.

Read every line, fork it, send a pull request. Add it to your next project in one line — no signup, nothing to buy.

Stack: TypeScript · framework-agnostic · localStorage API · CSS custom properties · React 18+ · concurrent-safe · SSR-safe · useAccesy() hook · theme tokens · headless core export · MIT licensed · well-tested core · keyboard-accessible · no external dependencies

## Artkive (formerly Rolodex)

**Save every artist. Find them again fast.**

Status: Free Chrome extension · in Web Store review. Page: https://fmillan.com/projects/artkive/

Artkive is a free Chrome extension that saves the artists you find on ArtStation and Behance into a private artist roster you control — the whole profile, not just a name. One click to save. Searchable by skills, software, and location. Nothing leaves your device.

Artkive is an artist roster tool for art directors, talent scouts, and collectors who work with ArtStation and Behance. It saves full artist profiles — bio, skills, software, social links, and recent work — into a private, searchable roster kept on your own device. The extension is free.

Tags: Chrome extension — free

- [Original page on fmillan.com](https://fmillan.com/projects/artkive/)

### The problem — You find artists worth hiring every day and lose track of them just as fast.

Artkive turns that scatter into one clean, searchable roster. One click to save. One place to find them again.

- A tab you meant to keep
- A bookmark in the wrong folder
- A screenshot you'll never find

### What gets saved

- Name & bio
- Skills & software
- Location & headline
- What they're open to
- Follower & project counts
- Social links & résumé
- Recent work thumbnails

### Who it's for — Anyone who hires, scouts, or collects artists.

- **Art directors** — Build a private shortlist of candidates across every role — not just names, the full context of what they do and what they use.
- **Talent scouts** — Track hundreds of artists across platforms without a spreadsheet.
- **Anyone who collects** — If you browse art and want to remember who made it — and find them again next year even if their profiles change — this is for you.

### Free — Chrome extension — Capture, search, and organize — for free.

The free Chrome extension does the core job on its own: capture, roster, search, filters, tags, and export. No subscription, no account.

- **One-click capture — the whole profile** — A 'Save to Artkive' button on every ArtStation and Behance profile. Name, bio, skills, software, social links, résumé, and a strip of recent work — all in one click, with undo. If a page can't be read, Artkive tells you — it never saves a blank or half record.
- **Instantly searchable** — Search by name, bio, skills, software, location, or the titles of their work. Filter by skill, platform, or date — fast enough that filtering thousands of artists feels instant.
- **Tag your way** — Organize with your own tags and browse by tag. Your vocabulary, your structure — not a predefined taxonomy.
- **Yours to keep** — Export your whole roster to JSON and re-import anytime. No lock-in — your data is yours regardless of what happens to Artkive.

### How it works — Three steps. No friction.

- **Save** — Click Save to Artkive on any ArtStation or Behance profile. The whole profile is captured in one click — with undo if you change your mind.
- **Find** — Open your roster and search, filter, or tag — instantly. By name, skills, software, location, or the titles of their work.

### Privacy — Your roster stays on your device. Full stop.

No account, no cloud, no analytics. Artkive reads the public artist pages you're already looking at and keeps everything on your device.

- **Stays on your device** — Your roster lives in your browser, on your own machine. Nothing is synced to a server.

### FAQ — Common questions

**Where is my data?**

Artkive keeps all your data on your own device, in your browser. Nothing is synced to a server, and you can export your whole roster anytime — so there's no lock-in.

**Which browsers and operating systems does Artkive support?**

The Artkive extension runs on Chrome on any desktop operating system. Safari support isn't planned; Firefox may come later.

**What exactly is captured when I save an artist?**

Saving an artist captures their name, bio, skills, headline, location, follower and project counts, what they're open to, their software, social links, résumé link, and a strip of recent work thumbnails — everything from the public page you're already viewing.

**What happens if an artist deletes their profile?**

Your saved record stays with you even if an artist removes their profile, though their images may stop loading once the profile is deleted.

### Start your roster in one click.

Free, private, and on your device from day one. Add to Chrome and save your first artist in under a minute.

### Who made it — Built by Felipe Millán

Artkive is built by Felipe Millán, a builder-marketer who has spent over a decade working across creative and tech companies. It came out of a real problem — losing track of artists discovered while hiring — and is designed to keep that work private and on your own device.

## Consentinel (formerly Galletas4All)

**A cookie consent widget I built to own my data — then open-sourced so you can own yours.**

Status: npm · MIT · 54 tests. Page: https://fmillan.com/projects/consentinel/

- [View on npm](https://www.npmjs.com/package/galletas4all)

Consentinel is an open-source, self-hosted cookie consent widget that runs on Cloudflare Workers. It blocks non-essential scripts until a visitor consents, logs every decision to a Cloudflare D1 database in your own account, and covers the opt-in requirements of GDPR, Chile's Ley 21.719, and Brazil's LGPD.

Many consent tools charge monthly, share a tracking layer across customer sites, and keep your consent records on servers you don't control. I wanted something small, self-hosted, and auditable — so I built one. It runs on your own Cloudflare account — the free tier covers around 100,000 consent events a day — the consent log lives in a database you own, and it's MIT, so you can fork it and make it yours.

Built around Chile's Ley 21.719 (in force December 1, 2026), but the opt-in model it uses is the same one GDPR and most Latin American laws require.

Tags: v1.0.3 on npm · 54 tests · CI on Node 20 + 22 · Cloudflare free tier · MIT license

- **~9 KB** — Widget on the wire, gzipped (≈22 KB raw)
- **54** — Tests — unit + integration via vitest-pool-workers
- **~100k/day** — Free-tier ceiling for consent events on Cloudflare

### What it does — One script tag. Your database.

You drop one script tag in your site's <head>. The widget shows a consent banner in Spanish or English, blocks any script you've tagged with data-consent-category until the visitor decides, then logs the decision to a Cloudflare D1 table you own.

That last part is the point. The consent log lives in your own Cloudflare account — not mine, not a shared SaaS database. When a regulator asks for an audit trail, you pull it yourself.

At runtime it makes no external calls except the audit POST to your own Worker. The script loads from jsDelivr CDN by default; if you want zero third-party requests, install from npm and serve the bundle from your own origin.

### SRI-pinned script tag

```
<script
  defer
  src="https://cdn.jsdelivr.net/npm/galletas4all@1.0.2/dist/widget.js"
  integrity="sha384-EcpbutKvmxCq6GRZvTqWyXb9Cb7Ka4LU4zuTSzvN1d2G3xYWus2BGn4yK4Ltv7dy"
  crossorigin="anonymous"
  data-api-url="https://your-worker.workers.dev"
  data-lang="es">
</script>
```

### Where it applies — Opt-in laws. One mechanic.

Consentinel implements the opt-in model: block non-essential scripts until the visitor agrees. That's what GDPR and the ePrivacy Directive require across the EU and UK (with fines reaching up to €20M or 4% of global turnover), what Chile's Ley 21.719 requires from December 1, 2026, and what most Latin American laws — including Brazil's LGPD — are built around. The same code covers all of them, because the mechanic is the same.

What it does not do is the US opt-out model — CCPA/CPRA, "Do Not Sell," and the Global Privacy Control signal work the opposite way. That's a different mechanic and it's out of scope. If you need it, the code is MIT. Fork it.

Compatible with opt-in laws by design — not legal advice, and not a compliance certification.

- **GDPR / ePrivacy** — EU & UK
- **Ley 21.719** — Chile (from Dec 2026)
- **LGPD** — Brazil

### Installation — By hand or by prompt.

Installation is one script tag, or npm install galletas4all if you'd rather bundle it into your build. It's small enough and declarative enough that you don't need a dashboard, an account, or an SDK to learn.

You can paste the tag, or hand the README to your AI coding agent — Claude Code, Cursor, bolt.new, Lovable, Replit — and have it wired up in a single prompt. Shipping it as a package instead of a service is the whole point: it drops straight into whatever you're already building.

- Claude Code
- Cursor
- bolt.new
- Lovable
- Replit

### Architecture — Under the hood

- **Browser** — Preact 10 renders the banner — ~3 KB of runtime; MutationObserver rewrites tagged scripts to type="text/plain" until consent is given, then swaps them back; navigator.sendBeacon sends the audit payload — survives tab close, unlike a plain fetch
- **The Worker** — Origin allow-list validation on every request; 4 KB body cap measured from actual bytes, not the Content-Length header; Parameterized D1 insert — no SQL injection surface; GET /stats is default-deny until you set STATS_TOKEN
- **Audit log** — Every decision writes one row: visitor ID, accepted boolean, category arrays, URL, referrer, user-agent, timestamp; Table lives in your Cloudflare account — not mine; D1 errors return 503; unexpected errors return 500

### Design decisions — A few calls worth explaining

- **navigator.sendBeacon first, not fetch** — The most common failure mode for consent loggers is the user accepting and immediately closing the tab. A plain fetch without keepalive gets cancelled on unload. sendBeacon survives it. I found this bug during a pre-launch audit and fixed it before shipping 1.0.2.
- **Content-Type: text/plain on the POST** — This skips the CORS preflight round-trip — text/plain is a CORS-safelisted content type. The server still parses the body as JSON. It saves a round-trip on every consent decision — not a huge optimization, but a free one.
- **Default-deny on /stats** — A consent widget handling privacy data shouldn't expose analytics by accident. The stats endpoint returns 503 unless you've explicitly set a bearer token. Most operators won't set one, and that's fine — the safe default is off.
- **Preact, not React** — The whole widget is ~9 KB gzipped. Preact's runtime is around 3 KB of that. I didn't want to ship ~45 KB of React to a site that otherwise doesn't use it.
- **teardownCookieEnforcer()** — The MutationObserver runs as long as the page exists. In an SPA that mounts the widget on every route change, you'd stack observers indefinitely. The mount() return function now tears the observer down. This was a real memory leak — the kind that only shows up in long-running SPA sessions.

### Tech stack — What it's built with

- **Core** — TypeScript (strict), Preact 10, esbuild 0.28
- **Testing** — Vitest 2, jsdom, @cloudflare/vitest-pool-workers
- **Infrastructure** — Cloudflare Workers, Cloudflare D1, Cloudflare Pages
- **Delivery** — npm, jsDelivr CDN, GitHub Actions CI

### Roadmap — What's next

An open-source side project, not a product I'm scaling — so the roadmap is "what I'll probably get to" plus "what I'd happily merge." It's MIT; if you need something sooner, fork it.

Nothing here is committed — these are ideas I'd happily merge. Compliance gaps come before polish: the /export endpoint for data-subject requests matters more than a theme editor.

- Google Consent Mode v2
- GTM template
- React wrapper
- Vue wrapper
- Svelte wrapper
- Astro wrapper
- WordPress recipe
- Shopify recipe
- Webflow recipe
- Ghost recipe
- CSS-variable theming
- HMAC-signed consent ledger

- **v1.0.3** — Accessibility — focus trap, Esc to close, reduced-motion
- **v1.0.4** — Worker /health endpoint · custom domain for the demo
- **v1.0.5** — /export endpoint for DSAR audit trails (NDJSON, token-gated)

### Deep dives — More on the architecture

- **Why Cloudflare Workers + D1, not a traditional backend?** — Cloudflare's free tier covers roughly 100,000 consent events per day — more than enough for most personal or small-business sites. D1 is a SQLite-compatible database that lives in your Cloudflare account, not mine. There's no server to provision, no connection pool to manage, and the cold-start time for a Worker is measured in milliseconds. The self-hosting angle is the real reason. Any hosted consent-log backend means your audit data is on someone else's infrastructure. With D1, the data is yours by default.
- **How does script blocking work?** — Before consent, the widget rewrites any data-consent-category-tagged scripts to type="text/plain", which the browser ignores. A MutationObserver watches for new scripts added after the widget mounts — they get the same treatment until consent is recorded. On consent, the type attribute is restored, and the browser re-evaluates the scripts. Reject follows the same flow in reverse — scripts are neutralized and any cookies that were already set are not re-set on subsequent loads.
- **Is the SRI hash safe to use as-is?** — Each version of Consentinel ships with a SHA-384 integrity hash pinned to that exact npm bundle. The hash in the script tag above matches version 1.0.2, and jsDelivr serves the file unmodified from npm, so the browser will refuse to run anything that doesn't match. When you upgrade to a newer version, regenerate the hash from the new bundle. The README includes the command to do it.
- **What does 'self-hosted' mean in practice?** — You deploy one Cloudflare Worker (a single TypeScript file) and one D1 table to your own Cloudflare account. Setup takes about 10 minutes following the quickstart. After that, the widget's audit POSTs go to your Worker URL — no traffic passes through anything I own. The frontend script still loads from jsDelivr by default (a public CDN), because that's the lowest-friction path. If you want zero third-party requests at all, npm install galletas4all and bundle it yourself.

Stack: TypeScript (strict) · Preact 10 · esbuild 0.28 · Vitest 2 · jsdom · @cloudflare/vitest-pool-workers · Cloudflare Workers · Cloudflare D1 · Cloudflare Pages · npm · jsDelivr CDN · GitHub Actions CI

---

# Roles in depth

## Cynoia — Chief Marketing & Sales Officer

09/2024 – 03/2026 · Tallinn

Led marketing and sales for Cynoia — Africa's all-in-one team workspace replacing Slack, Monday, Zoom and Notion for African businesses. Built the GTM motion from the ground up.

What started as a mentorship connection grew into a full rebuild of the go-to-market strategy.

- **6,000+** — users across 13 countries
- **10+** — telecom and university partnerships
- **2** — new country operations — Senegal, Morocco

### The work I'm proudest of — From "global ClickUp competitor" to "made in Africa, by Africans, for Africans."

Repositioned Cynoia around where it was built and who it was for, and localized it into Wolof and Swahili. That unlocked partnerships that had been stalled for over a year.

### What we got done

- Scaled to 6,000+ users across 13 countries
- Opened 2 new country operations (Senegal, Morocco)
- Closed 10+ partnerships with top African telecoms and universities
- Shipped platform features in native African languages
- Led distributed cross-functional teams across Tunisia, Estonia, Senegal and Morocco
- Positioned against global incumbents at ~80% lower software cost for African SMBs
- Owned the full funnel: brand, content, partnerships, community, PLG onboarding, sales enablement, board reporting
- Represented Cynoia at Gitex Africa and continental tech events

## Shroomwell — Chief Marketing Officer

09/2023 – 04/2024 · Tallinn

Led marketing for Shroomwell, a wellness company working with medicinal mushrooms and mycotechnology. Built a net-new marketing division and ran it.

### What I owned

- **Brand strategy & positioning** — The brand narrative for Shroomwell's products and what makes them different.
- **Product marketing** — Launches of mushroom-based products, including Shiitake extract, Reishi and Chaga elixirs and wellness capsules.
- **Digital & social** — Digital campaigns and social media to carry the message further.
- **PR & communications** — Public image, media coverage and relationships with influencers and experts in the space.
- **Content** — Informative content to make Shroomwell a credible voice in mycology and wellness.
- **Research & team** — Market and competitor analysis, and building a cohesive marketing team.

### Where it fits

Between co-founding Hive Identity (05/2021 – 05/2023) and leading marketing and sales for Cynoia (09/2024 – 03/2026). Part of the C-suite and co-founder years, 2021 – 2026: owning the whole funnel.

## Hive Identity — Co-founder & Chief Marketing Officer

05/2021 – 05/2023 · Tallinn

Co-founded Hive Identity, a Customer Identity Platform for startups and small businesses, and ran marketing and growth as CMO.

Non-enterprise businesses had been kept out of KYC (Know Your Customer) by cost and overcomplicated setups. To put it simply: underserved and overcharged. Hive was built for them.

- **$500K** — seed round, led by Isaac Saldana, founder of SendGrid

### What I did

- Owned marketing and growth, scaling a product-led, self-serve strategy
- Built PLG from scratch
- Raised $500K in a round led by SendGrid's founder

### What it taught me

The war in Ukraine disrupted the team, and Hive shut down in 2023 — which taught me more about prioritization than the roles that worked.

### Where it fits

Hive Identity came after Semrush (10/2019 – 04/2021), where I was part of the team through the ~$2B IPO. It started the C-suite and co-founder years, 2021 – 2026: owning the whole funnel, beginning with PLG from scratch at Hive Identity.

The seed round was led by Isaac Saldana, founder of SendGrid, where I was part of the team from 05/2016 to 02/2019.

## Semrush — Global Brand Evangelist & Influencer Marketing Manager

10/2019 – 04/2021

Joined Semrush as its first Global Brand Evangelist, to build brand awareness and translate the value of the product to communities, customers and professional marketers. Part of the team through the ~$2B IPO.

- **20,000+** — influencers in SEO, content, PPC and digital marketing
- **30** — people in a private inner circle

### What I did

- Worked with a network of 20,000+ influencers in SEO, content marketing, PPC and digital marketing
- Looked after a private influencer group of 30
- Automated workflows to streamline teamwork and social tasks
- Worked on awareness through evangelism at tech and marketing conferences and events
- Secured speaking slots at online events and podcast interviews
- Delivered workshops and masterclasses with digital marketers
- Closed the loop between field and product — carrying what users experienced back to the team

## Twilio — Senior Community Development Manager, EMEA

02/2019 – 05/2019 · EMEA

Joined Twilio after the $3B acquisition of SendGrid in 2019. Kept community development running for the Twilio SendGrid program, which gives startups mentoring, networking and free access to SendGrid and Twilio, plus early-release and beta products.

### Before Twilio

SendGrid, 05/2016 – 02/2019. Joined SendGrid before its ~$1.5B IPO in November 2017 (NYSE: SEND) and stayed through the $3B acquisition by Twilio.

Nurtured and expanded SendGrid's Accelerate program out of Europe into Africa, the Middle East and Latin America. The program gives startups mentoring, networking, free access to SendGrid's email platform and early-release products.

### After Twilio

Joined Semrush as its first Global Brand Evangelist (10/2019 – 04/2021). Part of the team through the ~$2B IPO.

### Looking back

Part of the teams at SendGrid, Twilio and Semrush through two IPOs and a major acquisition.

### What a colleague said

“Felipe consistently demonstrated an amazingly positive attitude, an aptitude for finding opportunity in every interaction, the capacity to work with people from a broad range of cultures and backgrounds — all the while doing it with a smile. He'd be an asset to any company he joins.” — Len Shneyder, Sr. Director of Industry Relations & Outbound PM, SendGrid / Twilio

## SendGrid — Senior Community Development Manager, EMEA

05/2016 – 02/2019 · EMEA

Joined SendGrid before its ~$1.5B IPO in November 2017 (NYSE: SEND) and stayed through the $3B acquisition by Twilio.

Nurtured and expanded SendGrid's Accelerate program out of Europe into Africa, the Middle East and Latin America. The program gives startups mentoring, networking, free access to SendGrid's email platform and early-release products.

- **550+** — startup accounts
- **50+** — accelerator and ecosystem partners
- **20+** — countries with activations

### What I contributed

- Evangelized the program to accelerators, managing directors, VC funds, coworking spaces and ecosystem players
- Helped bring in 50+ partners and 550+ accounts generating $15K+ MRR and $35K cMRR — including Techstars, 500, Startup Wise Guys, Startup Bootcamp, Kima Ventures, Microsoft Ventures, Lift99 and Mosaik
- Delivered presentations in 20+ countries: conferences, CTO and developer meetups, workshops
- Handled social engagement with GaggleAmp, reaching 14.2M people
- Served as a technical resource: onboarding and office hours to integrate SendGrid into partner stacks
- Carried feedback from the field to product and developer-experience teams

## Founder years — Chile and the early web

2000 – 2016

Before the scale-ups, I built my own things. Most of what I know about early-stage chaos comes from here: when you've put your own money on the line, you stop caring about vanity metrics and focus on what brings in customers.

- **93** — startups helped launch through PymeFacil
- **~65%** — made it off the ground

### The ventures

- **PymeFacil — CTO & co-founder · 2010 – 2012** — Co-founded the first entrepreneurship agency in Chile, helping 93 startups and companies start their ventures — about 65% of them made it.
- **Guubie.com — Founder & CEO · 2011 – 2015** — A marketing automation platform for startups: newsletters, automated emails and landing pages. Part of Startup Incubator Catalyst.
- **Biletu.com — Founder · 2012 – 2015** — A mobile app to pay between friends and skip the awkwardness, with gamification and social features. Santiago, Chile.
- **SubmitMyStartup.com — Founder & CEO · 2014** — A service for startups to submit their profile to 70+ relevant websites, blogs and directories — an intro to investors, journalists and bloggers.
- **Lanuu.co — Founder · 2015 – 2016** — A simple drag-and-drop web builder for non-technical people.
- **Orange Media Labs — Founder · 2000 – 2016** — Ran every project, from web development to web consultation.

### Honors

- Start-Up Chile — accepted
- Startup Wise Guys accelerator
- LeWeb Paris 2012
- The Next Web Chile Awards
- Guubie — Startup Incubator Catalyst

## Mentor & community — Mentor, advisor, judge, organizer

2016 – 2023 · Europe · Chile · global

Alongside the day jobs, I mentored startups across accelerators in Marketing Strategies, Branding, Go-To-Market and Growth — and helped run startup communities in Tallinn.

### Accelerators

- **Startup Wise Guys · 2016 – 2023** — Marketing and growth mentor in a three-month program, alongside 150+ international and local mentors.
- **Katapult Accelerator, Oslo · 2017 – 2023** — Mentor to startups across cohorts on marketing, branding, GTM and growth.
- **Techstars · 2018 – 2020** — Mentor to startups in different cohorts.
- **Founder Institute, Chisinau · 2017 – 2020** — Mentor in marketing strategy, branding, GTM and growth.
- **TheFactory, Oslo · 2018 – 2020** — Mentor at a fintech, insurtech, regtech and AI accelerator.
- **Storytek Creative Hub, Tallinn · 2018 – 2020** — Mentor at an accelerator for audiovisual and creative-tech startups.
- **Fincube, Istanbul · 2019 – 2020** — Mentor at the digital garage powered by QNB Finansbank.
- **Global Innovation Catalyst · 2021 – 2023** — Fellow mentor in a 12-week experiential learning program on designing and launching new ventures.

### Judging & advisory

- **Start-Up Chile · 2018 – 2021** — Judge — evaluated and scored applications to the Chilean government's program for early-stage founders.
- **SXSW · 2018 – 2019** — Board advisor for the SXSW Pitch competition, reviewing applications.

### Community

- **Startup Grind Tallinn · 2017 – 2019** — Chapter director for the global startup community powered by Google for Entrepreneurs.
- **Fuckup Nights Tallinn · 2017 – 2019** — Co-organizer of the nonprofit event series on business failure stories.
- **Mati Foods · 2023 – present** — Investor in a mycoprotein food company.

---

# Testimonials

> "Felipe consistently demonstrated an amazingly positive attitude, an aptitude for finding opportunity in every interaction, the capacity to work with people from a broad range of cultures and backgrounds — all the while doing it with a smile."
> — Len Shneyder, Sr. Director of Industry Relations & Outbound PM, SendGrid / Twilio

> "Under Felipe's vision, our projects consistently surpassed targets, achieving remarkable growth. His analytical prowess and data-driven decision-making optimized campaigns for maximum ROI."
> — Fernando Angulo, Head of Communications, Semrush

> "Felipe is the quintessential entrepreneur, down to earth, focused, very smart, fast, and visionary. Would I build my next company with him? YES :)"
> — Paolo Privitera, 6X Exit, Serial Entrepreneur & Investor, Evonove

> "Felipe has been a mentor for Katapult Accelerator almost since the beginning of our journey, and his involvement and engagement with our portfolio companies have been invaluable."
> — Nina Heir, Ex-VC, Angel Investor & Board Member, Katapult Accelerator

> "Felipe is an ongoing mentor at SWG accelerator. He helps early-stage startups with building a business mindset and sharing email-marketing knowledge."
> — Alexandra Balkova, Investor & Newton Venture Fellow, Startup Wise Guys

> "Working with Felipe has always been an extreme pleasure. Whether we are talking about his positive attitude or his problem-solving abilities, his drive to achieve results no matter the circumstances is admirable."
> — Sebastien Toupy, Community Builder & Strategist, The Next Web (TNW)

> "Felipe is the heart of a startup community. He truly understands the givers gain concept — he's always giving more than he takes."
> — Kristine Nagle, Sustainability Strategy Partner

> "I had the honor to meet Felipe over a decade ago at Start-Up Chile. Felipe has passion, a global mindset and a real sense to put an idea into a practical and real business."
> — Caro Rossi, Head of Strategic Initiatives, ESNA / Start-Up Chile

