A dead simple email relay service with a slick admin dashboard. Built with Next.js and Convex, using Brevo as the primary provider with NotificationAPI as fallback.
- What it does
- Stack
- Getting started
- Screenshots
- Configuration
- API
- Admin Dashboard
- Security
- Testing
- Project layout
- Setting up the providers
- Deploying
- License
- Sends emails reliably via Brevo (with automatic fallback to NotificationAPI if something fails)
- Tracks every email sent with detailed logs
- Provides a secure admin dashboard to manage everything
- API-first design – use it from your own apps or scripts
- Zero-downtime deployments (uses Convex, not your database)
- Next.js 16 with App Router
- TypeScript (strict mode)
- Tailwind CSS v4 for styling
- Convex for the backend (serverless)
- Brevo + NotificationAPI for email
- Bun or Node 18+ as runtime
Clone and install:
git clone https://github.com/Falakme/mail-relay.git
cd mail-relay
bun installSet up Convex:
bunx convex devCreate your config:
cp example.env .envFill in your secrets in .env (Brevo API key, NotificationAPI creds, and Convex URL).
Start the dev server:
bun devHead to http://localhost:3000 and log in with your SITE_KEY.
Everything lives in .env. See example.env for a template.
Required:
SITE_KEY– Secret key for admin loginBREVO_API_KEY– Your Brevo API keyNOTIFICATIONAPI_CLIENT_ID&NOTIFICATIONAPI_CLIENT_SECRET– NotificationAPI credentialsCONVEX_DEPLOYMENT&NEXT_PUBLIC_CONVEX_URL– Convex setup (auto-generated bybunx convex dev)
Optional:
DEFAULT_FROM_EMAIL– Default sender email
POST /api/send-mail
Authorization: Bearer <your-api-key>
Content-Type: application/json
Body:
{
"to": "user@example.com",
"subject": "Hello",
"body": "Text version",
"html": "<p>HTML version</p>",
"from": "sender@example.com",
"senderName": "My App",
"replyTo": "reply@example.com"
}Only to, subject, and body are required.
GET /api/status?hours=24
Returns health stats, delivery rates, and provider status.
All admin routes require authentication via SITE_KEY:
POST /api/auth– Login, logout, check sessionGET /api/api-keys– List your API keysPOST /api/api-keys– Create a new keyPUT /api/api-keys– Update a keyDELETE /api/api-keys– Delete a keyGET /api/logs– View email logsDELETE /api/logs– Delete a log entry
Log in at / with your SITE_KEY. You get:
- Email Logs – See every email sent, delivery status, any errors
- API Keys – Create, rotate, disable, and delete keys
- System Status – Real-time health, delivery metrics, provider limits
- Admin sessions are HMAC-signed and stored as httpOnly cookies
- API keys are hashed with SHA256 and never stored in plaintext
- Bearer tokens work for API access from other services
bun test
bun test:watchmail-relay/
├── app/
│ ├── (admin)/ # Admin dashboard pages
│ ├── api/ # API routes
│ ├── page.tsx # Login page
│ └── globals.css # Global styles
├── components/ # UI components
├── convex/ # Database schema + functions
├── lib/ # Auth, email logic, crypto
├── public/
│ └── screenshots/ # UI screenshots
└── test/ # Test files
Brevo
- Sign up at brevo.com
- Get a transactional API key
- Set
BREVO_API_KEYin your.env
NotificationAPI
- Create an account at notificationapi.com
- Create an email template called
email_relay - Add merge tags:
{{subject}},{{body}},{{html}} - Grab your Client ID and Secret
- Set
NOTIFICATIONAPI_CLIENT_IDandNOTIFICATIONAPI_CLIENT_SECRET
Vercel works great. Just:
- Push your code to GitHub
- Connect the repo to Vercel
- Set all environment variables
- Deploy
Or deploy manually:
bun run build
bun run start- Rate limiting is in-memory per provider (resets on restart)
- Convex handles all persistence – no database setup needed
- Colors:
#000040(main),#0000C0(accent) - Font: FalakSans
MIT – use freely.







