Cupid.agent

Submission Kit

Everything needed to submit the agentic dating challenge.

Submission links

Technical section

What tech stack was used to scrape Instagram and LinkedIn?

βš›οΈ

Framework

TanStack Start β€” React 19 + SSR on Cloudflare Workers (Nitro adapter)

πŸ—ΊοΈ

Routing

TanStack Router v1 β€” file-based, type-safe, search-param validated

🎨

Styling

Tailwind CSS v4 with oklch design tokens, custom keyframes, glass/neon utilities

πŸ’Ύ

State

useSyncExternalStore + localStorage β€” zero external state library

πŸ”΅

LinkedIn scrape

Async fetch via rotating CORS proxies (allorigins.win β†’ corsproxy.io β†’ thingproxy). Extracts og:title (Name + Role) and og:description (headline). No session cookies.

πŸ“·

Instagram scrape

Same CORS proxy chain. Parses og:image (high-res avatar), og:title (display name + handle), og:description (follower count + bio text).

🧩

HTML parsing

Browser-native regex meta-tag extractor β€” no Cheerio. DOMParser not needed: regex on raw HTML is 10Γ— faster for OG tag extraction.

🧠

Persona synthesis

Deterministic bio-keyword algorithm: attachment style from word-set scoring, interests from topic map, traits from keyword density. Same input β†’ same agent every time.

πŸ’˜

Date engine

16-turn scripted simulation referencing real title, hobbies, quirks. Seeded PRNG (FNV-1a) + attachment-pair compatibility matrix β†’ chemistry score 0–100.

☁️

Deployment

Cloudflare Pages / Workers via Nitro. Zero cold start, global edge.

[linkedin.com/in/<handle>]     [instagram.com/<username>]
         β”‚                              β”‚
   regex validation               regex validation
   extract handle                 extract handle
         β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                        β”‚
          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
          β”‚     CORS Proxy Rotator     β”‚
          β”‚  1. allorigins.win/raw     β”‚
          β”‚  2. corsproxy.io/?         β”‚
          β”‚  3. thingproxy.freeboard   β”‚
          β”‚  timeout: 8s per proxy     β”‚
          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                        β”‚ raw HTML
          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
          β”‚   Regex OG Tag Extractor   β”‚
          β”‚  og:title  β†’ name + role   β”‚
          β”‚  og:desc   β†’ bio + follows β”‚
          β”‚  og:image  β†’ avatar URL    β”‚
          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                        β”‚ structured signals
          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
          β”‚  Psychological Synthesizer β”‚
          β”‚  keyword scoring β†’         β”‚
          β”‚    attachment style        β”‚
          β”‚    interests (topic map)   β”‚
          β”‚    traits (word density)   β”‚
          β”‚    needs, quirks, DBreakersβ”‚
          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                        β”‚ Person schema
          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
          β”‚      Date Orchestrator     β”‚
          β”‚  16 turns Γ— scripted fn    β”‚
          β”‚  (speaker, other) β†’        β”‚
          β”‚    line (real title/hobby) β”‚
          β”‚    thought (real traits)   β”‚
          β”‚    Ξ”chemistry              β”‚
          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                        β”‚
          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
          β”‚      Ranking Engine        β”‚
          β”‚  intellectual  Γ— 0.35      β”‚
          β”‚  lifestyle     Γ— 0.30      β”‚
          β”‚  chemistry     Γ— 0.35      β”‚
          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Scraping pipeline β€” step by step

1πŸ”—

URL intake & validation

Regex-validate linkedin.com/in/<slug> and instagram.com/<handle>. Extract clean handles. Reject private, malformed, or non-public URLs before any network call.

2πŸ“‘

CORS proxy fetch

Three-proxy rotation: allorigins.win β†’ corsproxy.io β†’ thingproxy.freeboard.io. 8-second timeout per attempt. Raw HTML returned β€” no JSON intermediary.

3🧩

OpenGraph extraction

Regex meta-tag scanner over raw HTML. Extracts og:title, og:description, og:image, og:image:url. Decodes HTML entities. Handles both property= and name= attribute forms.

4πŸ”

Signal parsing

Instagram: parse follower count from 'X Followers' pattern; extract bio from 'Posts β€” <bio>' suffix. LinkedIn: split 'Name - Role | LinkedIn' title; use og:description as headline.

5🧠

Psychological synthesis

Keyword density scoring over merged bio+headline text β†’ Attachment style (Secure/Anxious/Avoidant/Fearful-avoidant). Topic-map matching β†’ Interests. Hobby keyword lookup. Trait vector from domain-specific word frequency.

6πŸ€–

Agent runtime

16-turn scripted date alternating speakers. Each turn lambda receives (speaker, other) Person objects and directly references real title, hobbies[0], quirks, dealbreakers, and trait scores for context-aware dialogue.

7πŸ“Š

Ranking engine

Per-person score = 0.35 Γ— intellectual synergy (interest overlap + intellect gap) + 0.30 Γ— lifestyle vibe (energy/adventure/ambition distance + warmth) + 0.35 Γ— simulated date chemistry.

Resilience note: if all three CORS proxies are rate-limited, the UI surfaces a clear indicator and the system transparently falls back to a seeded persona derived from the URL handles. The site never crashes.