{"id":40639831,"url":"https://github.com/verygoodplugins/automail","last_synced_at":"2026-01-21T08:02:03.033Z","repository":{"id":318767360,"uuid":"1076481770","full_name":"verygoodplugins/automail","owner":"verygoodplugins","description":"A self-hosted email waitlist system that runs entirely on Cloudflare's edge","archived":false,"fork":false,"pushed_at":"2025-10-14T23:38:05.000Z","size":29,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-10-15T04:03:45.632Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/verygoodplugins.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":null},"created_at":"2025-10-14T23:34:56.000Z","updated_at":"2025-10-14T23:38:08.000Z","dependencies_parsed_at":"2025-10-15T11:13:17.339Z","dependency_job_id":"7af1c246-1947-4651-adac-edac81768f42","html_url":"https://github.com/verygoodplugins/automail","commit_stats":null,"previous_names":["verygoodplugins/automail"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/verygoodplugins/automail","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/verygoodplugins%2Fautomail","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/verygoodplugins%2Fautomail/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/verygoodplugins%2Fautomail/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/verygoodplugins%2Fautomail/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/verygoodplugins","download_url":"https://codeload.github.com/verygoodplugins/automail/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/verygoodplugins%2Fautomail/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28629922,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-21T04:47:28.174Z","status":"ssl_error","status_checked_at":"2026-01-21T04:47:22.943Z","response_time":86,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-01-21T08:02:00.549Z","updated_at":"2026-01-21T08:02:03.015Z","avatar_url":"https://github.com/verygoodplugins.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# AutoMail 📬\n\n**A self-hosted email waitlist system that runs entirely on Cloudflare's edge.**\n\nZero external dependencies. No SaaS fees. Deploy in 5 minutes.\n\n## Features\n\n✅ **Email Signup** with validation and deduplication  \n✅ **Double Opt-In** (optional) with secure token-based confirmation  \n✅ **Beautiful Email Templates** with dark mode support  \n✅ **Bot Protection** via Cloudflare Turnstile  \n✅ **Admin Dashboard** (JSON/CSV export)  \n✅ **Broadcast Campaigns** to your entire list  \n✅ **Template Previews** for testing  \n✅ **100% Edge Native** - runs on Cloudflare Workers + D1\n\n## Why AutoMail?\n\nMost waitlist tools lock you into expensive SaaS platforms. AutoMail gives you:\n\n- **Full control** - Your data stays in your D1 database\n- **Zero cost** - Cloudflare's free tier covers most projects (100k reads/day, 1k writes/day)\n- **Fast** - Edge-first architecture, global deployment\n- **Simple** - 5-minute setup, no complex integrations\n\n## Quick Start\n\n### 1. Install Wrangler\n\n```bash\nnpm install -g wrangler\nwrangler login\n```\n\n### 2. Create D1 Database\n\n```bash\nnpm run db:create\n# Note the database_id that's returned\n```\n\n### 3. Configure\n\nCopy `wrangler.example.toml` to `wrangler.toml` and add your database ID:\n\n```toml\n[[d1_databases]]\nbinding = \"D1\"\ndatabase_name = \"automail-db\"\ndatabase_id = \"YOUR_DATABASE_ID_HERE\"\n```\n\n### 4. Apply Schema\n\n```bash\nnpm run db:migrate\n```\n\n### 5. Set Environment Variables\n\n```bash\n# Required\nnpx wrangler secret put ADMIN_TOKEN\n# Enter a secure random string\n\n# Optional (for sending emails)\nnpx wrangler secret put RESEND_API_KEY\n# Get your key from resend.com\n```\n\n### 6. Deploy\n\n```bash\nnpm run deploy\n```\n\nDone! Your waitlist API is live at:\n- `POST /api/signup` - Accept signups\n- `GET /admin/waitlist` - View signups (requires auth)\n- `POST /admin/broadcast` - Send campaigns\n\n## Environment Variables\n\n### Required\n\n- `ADMIN_TOKEN` - Secure token for admin endpoints\n\n### Optional (Email Sending)\n\n- `RESEND_API_KEY` - API key from [Resend](https://resend.com)\n- `FROM_EMAIL` - Sender email (default: `no-reply@yourdomain.com`)\n- `FROM_NAME` - Sender name (default: `Your App`)\n- `BASE_URL` - Your app's URL (for links in emails)\n\n### Optional (Features)\n\n- `DOUBLE_OPT_IN` - Set to `\"true\"` to require email confirmation\n- `SEND_WELCOME_EMAIL` - Set to `\"false\"` to disable welcome emails\n- `PUBLIC_TURNSTILE_SITE_KEY` - Enable bot protection (client-side)\n- `TURNSTILE_SECRET_KEY` - Turnstile secret (server-side)\n\n## API Reference\n\n### POST /api/signup\n\nAccept email signups.\n\n```bash\ncurl -X POST https://your-site.com/api/signup \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"email\": \"user@example.com\", \"source\": \"homepage\"}'\n```\n\n**Response:**\n```json\n{\n  \"success\": true,\n  \"message\": \"Welcome to the waitlist!\",\n  \"position\": 42\n}\n```\n\n### GET /admin/waitlist\n\nView waitlist data (requires authentication).\n\n```bash\ncurl -H \"Authorization: Bearer YOUR_ADMIN_TOKEN\" \\\n  https://your-site.com/admin/waitlist\n```\n\n**Response:**\n```json\n{\n  \"stats\": {\n    \"total_signups\": 150,\n    \"confirmed_count\": 120,\n    \"unsubscribed_count\": 5\n  },\n  \"signups\": [\n    {\n      \"email\": \"user@example.com\",\n      \"source\": \"homepage\",\n      \"created_at\": \"2024-01-15T10:30:00Z\"\n    }\n  ]\n}\n```\n\n### POST /admin/waitlist\n\nExport as CSV.\n\n```bash\ncurl -X POST -H \"Authorization: Bearer YOUR_ADMIN_TOKEN\" \\\n  https://your-site.com/admin/waitlist \u003e waitlist.csv\n```\n\n### POST /admin/broadcast\n\nSend email campaigns to your list.\n\n```bash\n# Dry run (preview recipients)\ncurl -X POST https://your-site.com/admin/broadcast \\\n  -H \"Authorization: Bearer YOUR_ADMIN_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"template\": \"day1\",\n    \"dryRun\": true,\n    \"confirmedOnly\": true\n  }'\n\n# Send for real\ncurl -X POST https://your-site.com/admin/broadcast \\\n  -H \"Authorization: Bearer YOUR_ADMIN_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n    \"template\": \"day1\",\n    \"confirmedOnly\": true\n  }'\n```\n\n### POST /admin/preview\n\nPreview email templates by sending them to yourself.\n\n```bash\ncurl -X POST https://your-site.com/admin/preview \\\n  -H \"Authorization: Bearer YOUR_ADMIN_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"to\": \"you@example.com\"}'\n```\n\n## Frontend Integration\n\nSee [`example/signup-component.html`](./example/signup-component.html) for a complete example with:\n- Email validation\n- Turnstile bot protection\n- Success/error handling\n- Accessible form design\n\nBasic example:\n\n```html\n\u003cform id=\"signup-form\"\u003e\n  \u003cinput type=\"email\" name=\"email\" required placeholder=\"Enter your email\"\u003e\n  \u003cbutton type=\"submit\"\u003eJoin Waitlist\u003c/button\u003e\n\u003c/form\u003e\n\n\u003cscript\u003e\ndocument.getElementById('signup-form').addEventListener('submit', async (e) =\u003e {\n  e.preventDefault();\n  const email = e.target.email.value;\n  \n  const res = await fetch('/api/signup', {\n    method: 'POST',\n    headers: { 'Content-Type': 'application/json' },\n    body: JSON.stringify({ email, source: 'landing' })\n  });\n  \n  const data = await res.json();\n  if (data.success) {\n    alert(data.message);\n  }\n});\n\u003c/script\u003e\n```\n\n## Customizing Email Templates\n\nEdit `functions/lib/email.js` and `functions/lib/campaigns.js` to customize:\n\n- Welcome email (sent on signup or after confirmation)\n- Confirmation email (double opt-in)\n- Campaign emails (e.g., Day 1 tips)\n\nAll templates support:\n- Dark mode\n- Mobile responsive\n- Plain text fallback\n- Unsubscribe links\n\n## Architecture\n\n```\n┌─────────────┐\n│   Browser   │\n└──────┬──────┘\n       │ POST /api/signup\n       ↓\n┌─────────────────┐\n│ Cloudflare      │\n│ Workers (Edge)  │\n└────┬───────┬────┘\n     │       │\n     ↓       ↓\n┌─────┐  ┌──────┐\n│  D1 │  │Resend│\n│(DB) │  │(Mail)│\n└─────┘  └──────┘\n```\n\n- **Frontend**: Any framework (vanilla JS, React, Vue, etc.)\n- **Backend**: Cloudflare Workers (serverless functions)\n- **Database**: Cloudflare D1 (SQLite at the edge)\n- **Email**: Resend API (optional, or bring your own SMTP)\n\n## Cost Breakdown\n\n| Service | Free Tier | Typical Usage |\n|---------|-----------|---------------|\n| Cloudflare D1 | 100k reads/day, 1k writes/day | $0 for most projects |\n| Cloudflare Workers | 100k requests/day | $0 for most projects |\n| Resend | 100 emails/day | $0 for early stages |\n\n**Total:** $0/month for projects under 1k signups/day.\n\n## Development\n\n```bash\n# Install dependencies\nnpm install\n\n# Run locally\nnpm run dev\n\n# Test signup\ncurl -X POST http://localhost:8788/api/signup \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"email\":\"test@example.com\"}'\n\n# Query database\nnpx wrangler d1 execute automail-db \\\n  --command=\"SELECT * FROM waitlist\"\n```\n\n## Security\n\n- **Tokens**: HMAC-signed with expiration (not reversible)\n- **Admin Auth**: Bearer token in headers\n- **Rate Limiting**: Configure via Cloudflare (WAF rules)\n- **Bot Protection**: Optional Turnstile integration\n- **CORS**: Configure in `wrangler.toml` as needed\n\n## Roadmap\n\n- [ ] CLI tool: `npx create-automail`\n- [ ] Simple workflow builder\n- [ ] Dashboard UI (view/export/manage signups)\n- [ ] Webhooks support\n- [ ] Segments/tags\n- [ ] Email A/B testing\n- [ ] Analytics dashboard\n\n## Contributing\n\nContributions welcome! Please open an issue first to discuss major changes.\n\n## License\n\nMIT License - see [LICENSE](./LICENSE)\n\n## Built By\n\nAutoMail is something we created for [automem.ai](https://automem.ai).\n\nIf you found this useful, consider:\n- ⭐️ Starring this repo\n- 🐦 [Following us on Twitter](https://twitter.com/jjack_arturo)\n- 🤖 Checking out [AutoMem](https://automem.ai)\n\n---\n\n**Questions?** Open an issue 🧡\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fverygoodplugins%2Fautomail","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fverygoodplugins%2Fautomail","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fverygoodplugins%2Fautomail/lists"}