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

@bitfocusas/email

v0.3.0

Published

Shared design and templates for Bitfocus transactional emails

Readme

@bitfocusas/email

Design and templates for Bitfocus transactional emails: the automatic emails our services send (account verification, password resets, sign-in codes, invitations, notifications). Change the look here and every app picks it up on its next version bump.

Not for personal or hand-written mail: email signatures, Gmail replies and the careers mailbox stay as they are.

Used by

| App | Templates | | ------------------ | --------------------------------------------------------------------------------------------------------- | | bitfocus-api | verifyEmail, resetPassword, reactivateAccount, subscriptionConfirmed, newsletterVerify | | bitfocus-auth | signInCode, smtpTest | | bitfocus-developer | moduleSubmitted, modulePublished, moduleBuildFailed, moduleChangesRequested, discussionActivity | | bitfocus-intra | productAlert | | bitfocus-reseller | invitation, memberAdded, notificationDigest |

Usage

Every template returns { subject, html, text }. The caller doesn't need React.

import { verifyEmail } from "@bitfocusas/email";

const { subject, html, text } = await verifyEmail({ url });

Send it with your existing sender, or with the shared SMTP sender:

import { createSmtpSender } from "@bitfocusas/email/smtp";

const sender = createSmtpSender({
	host: env.SMTP_HOST,
	port: env.SMTP_PORT,
	username: env.SMTP_USER,
	password: env.SMTP_PASS,
	from: { name: "Bitfocus", address: "[email protected]" },
});

const outcome = await sender.send({ to, subject, html, text });
// "accepted" | "confirmed-failure" (safe to retry) | "indeterminate" (may have been delivered)

The sender always verifies TLS certificates, allows unencrypted SMTP only to localhost, and gives up after 20 seconds.

One-off emails

Apps using React can build their own email from the same parts:

import { Buttons, Heading, Layout, renderEmail, Text } from "@bitfocusas/email/components";

const email = await renderEmail(
	"Subject",
	<Layout preview="Inbox preview line">
		<Heading>Hello</Heading>
		<Text>Body</Text>
		<Buttons buttons={[{ text: "Open", url }]} />
	</Layout>,
);

If the email is likely to be reused, or a second app needs it, add it as a template here instead.

Brand overrides

Every template takes an optional brand, e.g. to point the logo at a staging host:

await verifyEmail({ url, brand: { logoUrl: "https://staging.example/logo.png" } });

Installing

yarn add @bitfocusas/email

It's a public package on npm, like @bitfocusas/audit, so installs need no tokens in CI or Docker. The templates only hold copy and brand colours, nothing secret.

The package has no dependencies of its own (about 2 MB installed). Templates ship with React and the renderer bundled in, so backends without React need nothing else. Two entry points use what the app already has:

  • @bitfocusas/email/smtp needs nodemailer 10.
  • @bitfocusas/email/components needs react and react-dom 19. It renders the app's own components, which have to share the app's React.

Let Dependabot open a PR in each app when a new version is out:

# .github/dependabot.yml
version: 2
updates:
  - package-ecosystem: npm
    directory: /
    schedule: { interval: daily }
    allow:
      - dependency-name: "@bitfocusas/email"

Development

yarn install
yarn dev        # live preview of every template at http://localhost:3030
yarn test       # snapshot tests; run `yarn test -u` after an intended design change
yarn export     # static HTML of every template in out/
  • src/brand.ts holds colours, fonts, logo URL and company details.
  • src/components holds the layout and building blocks.
  • src/templates/<app>/<name>.tsx holds one template per file: a React component (default export, used by the preview) and a render function (named export, used by the apps).

Every design change shows up as a diff in tests/__snapshots__. To see it rendered, run yarn dev, or download the email-previews artifact from the PR's CI run.

Adding a template

  1. Create src/templates/<app>/<name>.tsx following an existing one, with realistic preview props.
  2. Export its render function from src/index.ts.
  3. Add it to the list in tests/templates.test.tsx and run yarn test -u.

Releasing

Run yarn release on an up-to-date main. It runs the checks, asks for the new version, then commits, tags and pushes. The pushed tag triggers the release workflow, which stages the version on npm using trusted publishing, so the repo needs no npm token. The version goes live once a maintainer approves it with 2FA, under the package's Staged Packages tab on npmjs.com or with npm stage list @bitfocusas/email and npm stage approve <stage-id> (staged publishing).

React, react-dom and react-email are bundled into dist, so apps get their security fixes only through a new release here. Dependabot groups them in one bundled PR: merge it and release.

The first release has to be published by hand (corepack yarn build && npm publish --ignore-scripts), because trusted publishing can only be configured for a package that already exists. Then, on npmjs.com, add bitfocusas/bitfocus-email with workflow release.yml as a trusted publisher, leave "Allow npm publish" and "Allow npm dist-tag" unchecked so it can only stage, and set publishing access to disallow bypass 2FA tokens.

Images

Email images are hosted by bitfocus-www at https://bitfocus.io/email/ (its public/email/ folder), so every app shares one stable URL. That folder is the only copy. To change an image, add it there under a new filename and update src/brand.ts. Never overwrite or delete a hosted file, because old emails still load it.