Inspiration
Cold outreach is universally hated — by the people writing it and the people receiving it. The friction isn't the sending; it's everything around it. Hunting for verified emails. Switching between Apollo, LinkedIn, and a half-finished spreadsheet. Staring at a blank draft at 11pm trying to sound human. Second-guessing every line.
We kept asking: what if cold email felt as fast and casual as Tinder? You see a face, you see a pitch, you swipe. That's Cold Reach.
What it does
Cold Reach turns cold outreach into a swipe deck.
- Filter — pick company stage, role, location, and industry.
- Generate — an AI agent searches Apollo for verified contacts, then drafts 2–3 personalized cold emails per person using Claude.
- Swipe — right sends the email via your real Gmail, left sends it to a queue for later editing.
From "I need to reach out to fintech founders in SF" to a real email landing in their inbox — under a minute, no copy-paste, no tab juggling.
How we built it
One Next.js 16 monorepo deployed on Vercel — UI and backend in the same app.
- Frontend: Next.js (App Router), React, Tailwind v4, shadcn/ui, scaffolded with v0.
- Agent: Vercel AI SDK v6 streaming Claude Opus 4.6 via the Vercel AI Gateway. The agent has two tools:
apollo_search_contactsanddraft_cold_email. It calls them in sequence and streams the whole thing back to the UI live. - Auth: Auth.js v5 (NextAuth) with Google OAuth, scoped to
gmail.sendso we can send from the user's actual address. - Send:
googleapisGmail v1 — RFC 2822 + base64url, straight to the user's Sent folder. - Storage: Vercel KV (Upstash Redis) for drafts and their statuses (
pending/queued_for_edit/sent). - Contacts: Apollo.io REST, with a mock fallback that kicks in automatically when the API key is missing — so we could keep building without burning credits.
We built backwards from the demo: Google sign-in → filters → streaming agent → swipe → real email arrives. Anything that didn't serve that flow got cut.
Challenges we ran into
- Vercel Hobby's 10-second function cap killed the agent route mid-stream. Bumped
maxDurationto 60s invercel.jsonand moved to Fluid Compute. - OAuth scopes. Getting
gmail.sendto persist into the JWT through NextAuth v5's session callback took longer than we'd like to admit. - v0 generates beautiful components that don't match your API. We learned to paste the TypeScript types from our README directly into v0 prompts — that got us 90% of the way there on the first try.
- Swipe gestures eat time. We built the deck with big "Send" / "Skip" buttons first, then layered the swipe animation on top once the flow worked end-to-end.
- AI SDK v6 dropped built-in MCP support. We had Apollo wired through MCP and had to fall back to calling the REST API directly.
Accomplishments that we're proud of
- A real email actually leaves your real Gmail at the end of a swipe. Not a mock, not "imagine if" — your Sent folder updates.
- The agent streams its tool calls live, so you watch it find contacts and write drafts in real time. It feels alive.
- Mock fallback for Apollo means the demo doesn't break because of a third-party outage or empty credits.
- Full stack shipped in one hack day — auth, agent, persistence, real Gmail send, swipe UI.
What we learned
- "Build backwards from the demo" is the cheat code. We knew exactly what the final screen needed to look like, so every commit was either getting closer to it or getting deleted.
- Type-driven prompting changes how you use AI codegen. v0 + shadcn + Next.js is fast when your API contract is locked first.
- Streaming agent UX is more about visible progress than actual speed. Even when the agent took 8 seconds, watching it work felt instant.
- Mock fallbacks aren't lazy — they're how you make a demo that survives flaky conference WiFi.
What's next for Cold Reach
- Reply tracking and follow-up sequences — right now you swipe once and it's gone. Cold email is a multi-touch game.
- Inline editing on the swipe card — left-swipe queues, but we want the edit to happen on the card itself.
- Saved searches and contact lists so you don't re-pick filters every time.
- Mobile-first UI — Tinder is a phone app. Cold Reach should be too.
- Better OAuth refresh handling so users don't get bounced after an hour.
- Open and reply analytics (with consent) so users can actually learn what's working.
- Swap
@vercel/kvfor@upstash/redisdirectly, since v3 is deprecated.
Built With
- google-oauth
- next-auth
- next.js
- node.js
- react
- shadcn-ui
- typescript
- upstash-redis
- v0
- vercel
- vercel-ai-gateway
- vercel-ai-sdk
- vercel-kv
Log in or sign up for Devpost to join the conversation.