npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

outreach-send-core

v0.2.16

Published

Reusable outreach toolkit with a headless send engine, Brevo mailer, Bouncer verifier, and multi-source prospect search.

Readme

outreach-send-core

Reusable outreach toolkit for backend projects that need:

  • a headless send engine
  • Brevo transactional email sending
  • Bouncer email verification
  • Google-first production prospect search
  • accepted-only legacy multi-source prospect search
  • a mock-backed preview and a live-tuning demo for prospect search

It does not include app-specific preview URLs, unsubscribe token generation, branded templates, database schemas, or Local News article creation.

What It Handles

  • Daily send caps
  • Candidate filtering for missing contacts or previews
  • Suppression checks
  • Optional email verification
  • Template rendering
  • Delivery handoff to your mailer
  • Recording sent, failed, and suppressed outcomes through your repository adapter
  • Production prospect discovery through GoogleFirstSeedProvider
  • Legacy prospect discovery across Google Places, OpenStreetMap, public web results, and optional LLM hints

Included Adapters

  • createOutreachEngine(...)
  • BrevoOutboundMailer
  • BouncerEmailVerifier
  • evaluateBouncerEmailVerification(...)
  • GoogleFirstSeedProvider
  • GooglePlacesSeedProvider

Install

npm install outreach-send-core

Demo

The package is functional and ships with a runnable demo that exercises:

  • createOutreachEngine(...)
  • BrevoOutboundMailer
  • BouncerEmailVerifier
  • evaluateBouncerEmailVerification(...)
  • GoogleFirstSeedProvider
  • GooglePlacesSeedProvider

Live demo:

  • https://andreakrea.github.io/outreach/

Run the mock preview locally with:

npm install
npm run demo

That mode uses mocked HTTP responses, so you do not need Brevo, Bouncer, Google Places, or live public-search credentials just to preview the package.

If you want the finder demo to behave like the real app and surface live diagnostics, run:

$env:PUBLIC_SERVICE_USER_AGENT='outreach-demo/1.0 ([email protected])'
$env:GOOGLE_PLACES_API_KEY='your_key_here'
npm run demo:live -- --cities Torino --business-types restaurant --keywords pizza

For quick local startup, you can also use the launcher scripts:

npm run start:demo:live
npm run start:playground

On Windows, the direct wrappers work too:

scripts\demo-live.cmd
scripts\playground.cmd

The live demo keeps the send-engine example mock-backed, but runs GooglePlacesSeedProvider against live Google Places, OpenStreetMap, and public web results using the legacy multi-source acceptance logic. It prints:

  • resolved criteria and provider toggles
  • search diagnostics and rejection counts
  • accepted seeds
  • fetch logs for provider calls and page crawls

You can tune the live finder with CLI flags or env vars such as:

  • --cities, --provinces, --business-types, --keywords, --limit
  • --google-places-enabled, --openstreetmap-enabled, --web-search-enabled
  • --search-budget-ms, --crawl-page-limit, --max-enrichment-candidates
  • PUBLIC_SERVICE_USER_AGENT, PUBLIC_SERVICE_REFERER, GOOGLE_PLACES_API_KEY

If you want a browser UI for testing the package locally, run:

$env:GOOGLE_PLACES_API_KEY='your_key_here'
npm run playground

Then open http://127.0.0.1:4317.

The finder playground uses live provider calls for Google Places, OpenStreetMap, and public web search. It now exposes the live tuning knobs too, including:

  • search budget
  • crawl page limit
  • max enrichment candidates
  • timeout
  • public-service user agent and referer overrides
  • request-log toggling

If you leave Google Places enabled without a key, the provider will skip Google discovery and note that in diagnostics.

If you want the live site to publish from this repo, enable GitHub Pages for the main branch and /docs folder in the repository settings.

Example output:

Mock-backed demo for outreach-send-core.
No Brevo, Bouncer, Google Places, or live public-search credentials are required for this preview.

Outreach Engine Demo
====================
{
  "result": {
    "approvedCount": 3,
    "attemptedCount": 2,
    "sentCount": 1,
    "suppressedCount": 1,
    "skippedMissingPreviewCount": 1
  }
}

Prospect Finder Demo
====================
{
  "diagnostics": {
    "provider": "google_places",
    "strategy": "multi_source_province_acceptance"
  },
  "firstSeed": {
    "companyName": "Cafe Uno",
    "businessType": "restaurant",
    "primaryEmail": "[email protected]"
  }
}

Production Quick Start

import {
  BrevoOutboundMailer,
  BouncerEmailVerifier,
  createOutreachEngine,
  evaluateBouncerEmailVerification,
} from 'outreach-send-core'

const outreach = createOutreachEngine({
  repository: myRepository,
  mailer: new BrevoOutboundMailer({
    apiKey: process.env.BREVO_API_KEY,
    fromEmail: process.env.EMAIL_FROM,
    fromName: process.env.EMAIL_FROM_NAME,
  }),
  emailVerifier: new BouncerEmailVerifier({
    apiKey: process.env.BOUNCER_API_KEY,
  }),
  evaluateEmailVerification: evaluateBouncerEmailVerification,
  resolveGlobalDailyCap: async () => 50,
  resolveReplyTo: async () => '[email protected]',
  linkBuilder: async ({ campaign, contact, preview }) => ({
    previewUrl: preview.publicUrl,
    unsubscribeUrl: `https://example.com/unsubscribe?email=${encodeURIComponent(contact.email)}`,
    registerUrl: `https://example.com/register?campaign=${campaign.id}`,
  }),
  templateBuilder: async ({ prospect, links }) => ({
    subject: `Preview for ${prospect.companyName}`,
    htmlContent: `<a href="${links.previewUrl}">Open preview</a>`,
    textContent: `Open preview: ${links.previewUrl}`,
    tags: ['outreach'],
  }),
})

await outreach.sendApprovedBatch('campaign_123')

Prospect Search Example

import { GoogleFirstSeedProvider } from 'outreach-send-core'

const provider = new GoogleFirstSeedProvider({
  apiKey: process.env.GOOGLE_PLACES_API_KEY,
  maxExpandedMunicipalities: 12,
  businessTypeLabels: {
    restaurant: 'restaurant',
    salon: 'hair salon',
  },
  nearbyTypesByBusinessType: {
    restaurant: ['restaurant'],
    salon: ['beauty_salon', 'hair_care'],
  },
})

const result = await provider.search({
  country: 'IT',
  language: 'it',
  cities: ['Torino'],
  provinces: [],
  businessTypes: ['restaurant'],
  keywords: ['pizza'],
  limit: 20,
})

The production provider now uses Google Places as the business identity source of truth, applies staged identity/type/website/contact gates, returns accepted prospects in seeds, and holds borderline prospects in reviewCandidates.

Each returned seed can now include:

  • primaryEmail
  • qualityScore
  • sourceMetadata with source classes, source providers, and a score summary

Diagnostics now also expose:

  • rawCandidateCount
  • acceptedCandidateCount
  • acceptedCount
  • reviewCount
  • rejectedCount
  • rejectionCounts
  • rejectionCountsByStage
  • reviewCounts
  • sourceContributionCounts

Required Repository Contract

Your repository must implement:

  • getCampaign
  • countSentSince
  • listApprovedSendCandidates
  • getSuppressedEmailSet
  • suppressEmail
  • recordSuppressedSend
  • recordFailedSend
  • recordSentSend

See src/types.ts for the full interface definitions.

AI Agent Implementation Guide

If you are wiring this package with an AI coding agent, start with AGENTS.md.

That file gives the exact integration path:

  • the repository contract
  • required data invariants
  • the canonical sendApprovedBatch(...) execution flow
  • the production GoogleFirstSeedProvider integration path
  • the meaning of seeds vs reviewCandidates
  • the meaning of each result counter
  • a minimal adapter skeleton
  • an acceptance checklist for validation

Publish

npm run build
npm test
npm pack
npm publish

If you are publishing a public scoped package on npm, use:

npm publish --access public