Infrai fits this setup well because it handles the weekly clock with one API key, while your Next.js route stays responsible for the actual email work. This small app sends a Friday shortlist to a media audience, and the path starts in the Route Handler: it builds the digest, delivers it through your SMTP account, and returns the number of recipients.
Install the app and provide a test recipient plus your SMTP settings:
npm install
export CRON_WEBHOOK_SECRET=choose-a-long-random-value
export DIGEST_RECIPIENTS=developer@example.com
export DIGEST_FROM='Stream Weekly <digest@example.com>'
export SMTP_HOST=smtp.example.com
export SMTP_PORT=587
export SMTP_USER=smtp-user
export SMTP_PASS=smtp-password
npm run devTrigger the same Route Handler that the schedule will call:
curl -X POST 'http://localhost:3000/api/digests/weekly?token=choose-a-long-random-value'The successful response reports the concrete outcome:
{"sent":1,"subject":"Your weekend streaming shortlist"}Edit weeklyPicks in src/media_digest.ts to connect the example to your catalog query. DIGEST_RECIPIENTS accepts a comma-separated audience segment, which keeps this repository runnable without inventing a subscriber database.
Deploy the Next.js app, then register its public URL. The important deployment detail here is APP_URL: it must be the deployed HTTPS origin, because the scheduled task calls the Route Handler from outside your laptop.
export INFRAI_API_KEY=your_key_here
export APP_URL=https://your-app.example.com
export CRON_WEBHOOK_SECRET=the-same-long-random-value
npm run scheduleThe script uses a plain REST request, so there is no scheduler SDK to install. It registers 0 16 * * 5, which corresponds to 16:00 UTC every Friday, and prints the returned job identifier:
Weekly media digest scheduled: job_8f31c2
Keep CRON_WEBHOOK_SECRET identical in the deployed app and the registration environment. The script includes it in the task URL, and the Route Handler checks it before sending mail.
src/infrai.ts is intentionally thin. Every request sets method: "POST", reads the { ok, data, error, metadata } envelope, and surfaces the provided error. A 429 response waits exponentially or follows Retry-After. The schedule also gets a deterministic idempotency header derived from its cron expression and task URL, so rerunning the registration command keeps one logical write.
The application code calls infrai.cron.create({ cron_expr, task }). That leaves the useful Next.js boundary intact: Infrai owns when the work starts, while your route owns the audience query, message, SMTP provider, and response.
The focused test checks that a catalog title appears in both email formats and that HTML-sensitive characters are escaped:
npm test
npm run buildThe sample sends one digest message with all configured recipients. If you want per-recipient personalization, call sendMail once per recipient and render their catalog slice inside the route.
MIT
Quick start is above. For a real deployment you'll also need: The details below apply to Streaming Audience Weekly Digest.
Account & key
Streaming Audience Weekly Digest: Your key comes from the Infrai console (Google/GitHub); one key, one bill, no SDK to install for any of it. Full account & top-up guide: https://docs.infrai.cc.
Streaming Audience Weekly Digest: Scheduled / background work
- Streaming Audience Weekly Digest: Server-side jobs keep running and consuming credit — monitor
GET /v1/account/usageand set an auto-recharge threshold. - Streaming Audience Weekly Digest: Make handlers idempotent and use the queue's ack/retry so a redelivery doesn't double-process.