Skip to content

andrewkitchell/goodnewsbot

Repository files navigation

Good News Bot — Outreach Programs

Scheduled outreach email system built on Next.js (App Router) + Prisma + Inngest + Vercel Cron.

Architecture Overview

Vercel Cron (hourly)
  → GET /api/cron/outreach-dispatch          [auth: CRON_SECRET]
      → finds active programs where next_run_at ≤ now
      → fires inngest event "outreach/program.due" per program

Inngest function: outreach-program-due
  → loads program, resolves listings from scope_payload
  → creates program_run + outreach_recipients rows
  → fans out "outreach/recipient.generate" per recipient
  → updates program.next_run_at

Inngest function: outreach-generate-recipient-email
  → builds LISTING or OWNER-rollup email
  → calls createGmailDraft() → stores draftId on recipient row

Quick Start

# 1. Install dependencies
npm install

# 2. Set up environment
cp .env.example .env.local
# Edit .env.local with your DATABASE_URL, CRON_SECRET, Inngest keys

# 3. Generate Prisma client and push schema
npm run db:generate
npm run db:push        # or: npm run db:migrate (for migration files)

# 4. Run Next.js dev server
npm run dev

# 5. In a separate terminal, run the Inngest Dev Server
npx inngest-cli@latest dev

Running Tests

npm test

Covers:

  • computeNextRunAt — MONTHLY / QUARTERLY / SMART cadences and edge cases
  • groupListingsByOwner — recipient grouping for OWNER audience type

Environment Variables

Variable Required Description
DATABASE_URL PostgreSQL connection string
CRON_SECRET Bearer token for cron route auth
INNGEST_EVENT_KEY Inngest event API key
INNGEST_SIGNING_KEY Inngest signing key (production)
GMAIL_CLIENT_ID When live Google OAuth client ID
GMAIL_CLIENT_SECRET When live Google OAuth client secret
GMAIL_REFRESH_TOKEN When live Google OAuth refresh token

TODOs / Stubs to Replace

  • src/lib/gmail.ts — replace stub with real googleapis integration
  • resolveListingOwners() in outreach-program-due.ts — query real owner data
  • resolveOwnerEmail() in outreach-generate-recipient-email.ts — look up real email addresses
  • Email templates — inject real listing metrics / highlights
  • SMART frequency — refine 30-day default with engagement-based logic
  • scopeType handling — add ALL, TAG, or other scope types beyond FILTER

File Map

good-news-bot/
├── .env.example
├── vercel.json                              # Hourly Vercel Cron config
├── prisma/
│   └── schema.prisma                        # outreach_programs, program_runs, outreach_recipients
├── src/
│   ├── app/api/
│   │   ├── cron/outreach-dispatch/route.ts  # Cron handler
│   │   └── inngest/route.ts                 # Inngest serve route
│   ├── inngest/
│   │   ├── client.ts
│   │   ├── index.ts
│   │   └── functions/
│   │       ├── outreach-program-due.ts
│   │       └── outreach-generate-recipient-email.ts
│   └── lib/
│       ├── db.ts                            # Prisma singleton
│       ├── gmail.ts                         # Gmail draft stub
│       └── scheduling.ts                    # next_run_at + groupListingsByOwner
└── __tests__/
    ├── scheduling.test.ts
    └── recipient-grouping.test.ts

goodnewsbot

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors