AI-powered email outreach platform for sales teams, recruiters, and professionals who need personalized cold emails at scale.
Sendable generates hyper-personalized outreach emails using AI. It automates audience research, intent-based email generation, and multi-step follow-up sequences so you can focus on closing deals instead of writing cold emails.
- AI Email Generation - One-click personalized emails with optimized subject lines, body copy, and CTAs
- Intent-Based Engine - Automatically adapts tone and messaging for sales, recruiting, or networking contexts
- Audience Research - AI scans prospect web presence and surfaces personalization hooks
- Smart Follow-ups - Automated multi-step sequences that keep conversations going
- Rich Editor - Dual Markdown/WYSIWYG editor with inline AI rewrites and version history
- Session Management - Real-time session tracking with browser detection and revocation
- Two-Factor Auth - TOTP-based 2FA with backup codes and email OTP
| Layer | Technology |
|---|---|
| Framework | Next.js 16 (React 19, App Router) |
| Backend | Convex (real-time database + serverless functions) |
| Auth | Better Auth (email/password, OAuth, 2FA, magic links) |
| Resend + Nodemailer SMTP fallback | |
| UI | Tailwind CSS v4 + shadcn/ui |
| Animations | Framer Motion |
| Logging | BetterStack / Logtail (production) |
| Language | TypeScript (strict mode, full-stack type safety) |
- Node.js >= 20.x
- pnpm >= 9.x
- A free Convex account
git clone https://github.com/hasnaintypes/sendable-ai.git
cd sendable-ai
pnpm installcp .env.example .env.localEdit .env.local with your values. See Environment Variables for details.
Set the same variables in your Convex dashboard under Settings > Environment Variables.
pnpm devThis starts Next.js + Convex simultaneously. Open http://localhost:3000.
sendable-ai/
├── convex/ # Backend (Convex serverless)
│ ├── auth/ # Auth helpers, queries, mutations
│ ├── betterAuth/ # Better Auth schema & config
│ ├── emails/ # Email service + React Email templates
│ │ ├── email.tsx # Send actions (Resend + SMTP fallback)
│ │ └── templates/ # Email templates (BaseLayout, Verify, Reset, etc.)
│ ├── lib/ # Shared backend utilities
│ │ └── logger.ts # Logger (console local, BetterStack production)
│ ├── userPreferences/ # User profile & notification prefs
│ │ ├── schema.ts
│ │ ├── queries.ts
│ │ ├── mutations.ts
│ │ └── upload.ts # Profile image upload via Convex storage
│ ├── users/ # User schema (extends Better Auth)
│ └── schema.ts # Root schema (composes all tables)
│
├── src/
│ ├── app/ # Next.js App Router
│ │ ├── (auth)/ # Authenticated routes (dashboard, settings)
│ │ ├── (unauth)/ # Public routes (sign-in, sign-up, etc.)
│ │ └── layout.tsx # Root layout (providers, font, theme)
│ │
│ ├── components/
│ │ ├── auth/ # Auth forms (sign-in, sign-up, reset, 2FA)
│ │ ├── dialogs/ # Modal dialogs (delete account, 2FA, change email)
│ │ ├── layout/ # Shell components (AppHeader, AppSidebar, Footer)
│ │ ├── pages/ # Route-specific components
│ │ │ ├── (auth)/settings/ # Settings tab sections
│ │ │ └── (unauth)/home/ # Landing page sections
│ │ ├── providers/ # React context providers
│ │ ├── shared/ # Shared components (Logo, UserMenu, ThemeSwitcher)
│ │ └── ui/ # shadcn/ui primitives
│ │
│ └── lib/
│ ├── auth/ # Auth client (browser) & server helpers
│ ├── logger.ts # Frontend logger (dev console, prod silent)
│ └── utils.ts # Utility functions
│
├── public/
│ └── icons/ # Browser icons, logo, social provider SVGs
│
└── package.json
pnpm dev # Start dev server (Next.js + Convex)
pnpm build # Production build
pnpm lint # ESLint + TypeScript checks
pnpm format # Prettier format
pnpm format:check # Check formatting| Variable | Required | Where | Description |
|---|---|---|---|
CONVEX_DEPLOYMENT |
Yes | .env.local |
Convex deployment identifier |
NEXT_PUBLIC_CONVEX_URL |
Yes | Both | Convex cloud URL |
NEXT_PUBLIC_CONVEX_SITE_URL |
Yes | Both | Convex HTTP actions URL |
SITE_URL |
Yes | Convex | App URL (used for auth origins and email links) |
NEXT_PUBLIC_SITE_URL |
Yes | .env.local |
Public app URL |
BETTER_AUTH_SECRET |
Yes | Convex | Auth encryption secret (openssl rand -base64 32) |
RESEND_API_KEY |
Yes | Convex | Resend API key for production emails |
EMAIL_PROVIDER |
No | Convex | "resend" (default) or "smtp" |
SMTP_HOST |
If SMTP | Convex | SMTP server hostname |
SMTP_PORT |
No | Convex | SMTP port (default: 587) |
SMTP_USER |
If SMTP | Convex | SMTP username |
SMTP_PASS |
If SMTP | Convex | SMTP password |
SMTP_SECURE |
No | Convex | "true" for TLS (default: false) |
SMTP_FROM_NAME |
No | Convex | Sender name (default: Sendable) |
SMTP_FROM_EMAIL |
No | Convex | Sender email (default: onboarding@resend.dev) |
RESEND_VERIFIED_RECIPIENT |
No | Convex | Restrict Resend to one email (free tier) |
LOGTAIL_SOURCE_TOKEN |
No | Convex | BetterStack source token for production logging |
GITHUB_CLIENT_ID |
No | Convex | GitHub OAuth client ID |
GITHUB_CLIENT_SECRET |
No | Convex | GitHub OAuth client secret |
GOOGLE_CLIENT_ID |
No | Convex | Google OAuth client ID |
GOOGLE_CLIENT_SECRET |
No | Convex | Google OAuth client secret |
SLACK_CLIENT_ID |
No | Convex | Slack OAuth client ID |
SLACK_CLIENT_SECRET |
No | Convex | Slack OAuth client secret |
"Both" = set in both .env.local and Convex dashboard. "Convex" = Convex dashboard only.
For local development, set EMAIL_PROVIDER=smtp and use Mailpit or Mailtrap:
# Mailpit (local SMTP catcher)
SMTP_HOST=localhost
SMTP_PORT=1025
SMTP_USER=
SMTP_PASS=| Feature | Status |
|---|---|
| Email/password sign-up & sign-in | Active |
| Email verification | Active |
| Password reset flow | Active |
| Two-factor authentication (TOTP) | Active |
| Magic link login | Active |
| OTP verification | Active |
| Session management & revocation | Active |
| Rate limiting (10 req/60s) | Active |
| OAuth (GitHub, Google, Slack) | Ready (env vars needed) |
- Rate limiting on all auth endpoints (10 requests per 60-second window)
- Password strength validation with real-time requirements checklist
- 2FA disable requires password confirmation
- Account linking restricted to same-email only
- User lookup queries require authentication
- CSRF protection via framework defaults (Convex + Better Auth)
- File uploads validated for type and size (2MB max, image types only)
- Structured logging with no PII in production logs (BetterStack)
- Environment variables validated with descriptive error messages
See CONTRIBUTING.md for detailed guidelines.
git checkout -b feature/your-feature
# Make changes
pnpm lint # Verify before committing
git commit -m "feat: describe your change"
git push origin feature/your-feature
# Open a Pull RequestThis project is proprietary. All rights reserved.
- Convex - Real-time backend
- Better Auth - Authentication
- shadcn/ui - UI components
- Next.js - React framework
- Resend - Email delivery
- BetterStack - Production logging