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

groundmail

v0.25.1

Published

Groundmail transactional email API client

Readme

groundmail

Official Node.js / TypeScript client for the Groundmail transactional email API.

npm install groundmail
export GROUNDMAIL_API_KEY=gm_your_key_here
import { Groundmail } from 'groundmail'

const tx = new Groundmail(process.env.GROUNDMAIL_API_KEY!)

const email = await tx.emails.send({
  from: '[email protected]',
  to: '[email protected]',
  subject: 'Your receipt',
  html: '<p>Thanks for your purchase.</p>',
})

console.log(email.id, email.status)

Azure managed identity (no API key)

On Azure, authenticate with the workload's managed identity instead of a key. Pass a token provider; the client caches the token until shortly before it expires and asks for a new one after a 401:

import { DefaultAzureCredential } from '@azure/identity'
import { Groundmail } from 'groundmail'

const credential = new DefaultAzureCredential()
const client = new Groundmail({ getToken: () => credential.getToken('https://api.groundmail.dev/.default') })

getToken may return a string or { token, expiresOnTimestamp }. Add the Groundmail app to your Entra tenant once (az ad sp create --id 0146ad5c-4051-4703-aece-e4edf9805d8e) and register the identity in the dashboard first: https://docs.groundmail.dev/authentication/azure-managed-identity

Testing

Use a test key (gm_test_…, create one with tx.apiKeys.create({ test: true }) or in the dashboard) to run sends through validation, templates and webhooks without delivering anything. Simulator addresses produce a specific outcome with any key and never leave Groundmail:

import { simulatorAddress } from 'groundmail'

await tx.emails.send({
  from: '[email protected]',
  to: simulatorAddress('bounce', 'signup-42'), // [email protected]
  subject: 'Bounce handling test',
  html: '<p>Simulated.</p>',
})
// status `bounced`, then an `email.bounced` webhook with `data.test: true`

Outcomes: delivered, bounce, block, complaint, suppressed, delayed. Details: https://docs.groundmail.dev/testing

Tenants

If you send email for your own customers, create one tenant per customer. Each tenant has its own domains, suppression list, stats, pause switch and daily limit, so one customer's bounces or complaints never affect the others. Tenants are included on the Scale and Dedicated plans.

await tx.tenants.create({ external_id: 'cus_123', name: 'Acme', daily_limit: 5000 })
await tx.tenants.domains.assign('cus_123', 'mail.acme.com')

await tx.emails.send({
  from: '[email protected]',
  to: '[email protected]',
  subject: 'Your invoice',
  html: '<p>Thanks!</p>',
  tenant: 'cus_123',
})

const { stats } = await tx.tenants.stats('cus_123', { days: 7 })
await tx.tenants.pause('cus_123', 'Unpaid invoice')
await tx.tenants.resume('cus_123')

tenant (your external id or the Groundmail id) also works on emails.list, domains.create and domains.list, suppressions, apiKeys.create (a key limited to one tenant) and emails.testWebhook. Webhook endpoints take tenants: ['cus_123'] to receive only those tenants' email events. Details: https://docs.groundmail.dev/tenants

DMARC monitoring

Free for every domain. Turn it on, publish the record it returns, and read sources, pass rates and whether it's safe to enforce once the daily reports arrive:

const { dmarc } = await tx.dmarc.enable('yourdomain.com') // or { apply: 'cloudflare' }
console.log(dmarc.dns.suggested_record) // your record with our report address in rua=

const report = await tx.dmarc.get('yourdomain.com')
if (report.dmarc.enabled) console.log(report.dmarc.readiness.label, report.dmarc.sources)

Details: https://docs.groundmail.dev/dmarc

Adapters

Optional entry points (install peer deps as needed):

| Import | Package / peer | |--------|----------------| | groundmail/nodemailer | groundmail-nodemailer + nodemailer | | groundmail/better-auth | groundmail-better-auth | | groundmail/authjs | groundmail-authjs | | groundmail/clerk | groundmail-clerk | | groundmail/payload | groundmail-payload |

Docs

  • Quickstart: https://docs.groundmail.dev/quickstart
  • Node / Nodemailer: https://docs.groundmail.dev/frameworks/node
  • Testing (test keys, simulator): https://docs.groundmail.dev/testing
  • DMARC monitoring: https://docs.groundmail.dev/dmarc
  • API reference: https://docs.groundmail.dev/api/emails
  • Product: https://groundmail.dev

License

MIT