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

emaildsl

v0.0.2

Published

Framework-agnostic TypeScript DSL for building email-safe HTML with React and Vue preview support

Readme

EmailDSL

A framework-agnostic TypeScript DSL for building email-safe HTML.

Features

  • Email-safe: Framework generates tables and inline styles automatically.
  • Themable: Global theme support with component overrides.
  • Responsive: Fluid layouts that work on mobile (with stacking support).
  • TypeScript: Full type safety for all primitives.
  • Zero dependencies: Lightweight and fast.

Installation

From NPM

pnpm add emaildsl
# or
npm install emaildsl

Local Development

For local development or to contribute, clone the repository:

git clone https://github.com/veri5ied/emaildsl.git
cd emaildsl
pnpm install
pnpm build

Usage

HTML (Framework Agnostic)

import { email, section, text, button } from "emaildsl";

const myEmail = email({
  title: "Hello",
  body: [
    section([
      text("Hello World"),
      button("Click Me", { href: "https://example.com" }),
    ]),
  ],
});

const html = myEmail.render();

React (Live Preview)

import { EmailPreview } from "emaildsl/react";
import { email, section, text } from "emaildsl";

const myEmail = email({
  body: [section([text("Hello")])],
});

function App() {
  return <EmailPreview config={myEmail.config} />;
}

Vue (Live Preview)

<script setup>
import { EmailPreview } from "emaildsl/vue";
import { email, section, text } from "emaildsl";

const myEmail = email({
  body: [section([text("Hello")])],
});
</script>

<template>
  <EmailPreview :config="myEmail.config" />
</template>

Primitives

Layout Primitives

  • section(children, options) - Creates a layout section (renders as table row)
  • column(children, options) - Creates a column within a section (renders as table cell)

Content Primitives

  • text(content, options) - Creates a text element with optional styling
  • button(label, options) - Creates a clickable button with href
  • image(src, options) - Creates an image element with alt text and dimensions
  • divider(options) - Creates a horizontal divider line
  • spacer(height) - Creates vertical spacing (accepts px or em)

API Reference

Email Configuration

email({
  title: string;              // Email title (appears in <title> tag)
  body: Primitive[];          // Array of primitives
  theme?: Theme;              // Optional global theme
  lang?: string;              // Language code (default: 'en')
});

Theme Options

theme: {
  colors?: {
    primary?: string;
    secondary?: string;
    text?: string;
    background?: string;
  };
  fonts?: {
    family?: string;
    size?: string;
  };
  spacing?: {
    section?: string;
    element?: string;
  };
  button?: {
    borderRadius?: string;
    padding?: string;
  };
}

Styling System

Every primitive accepts a style option for inline CSS overrides:

text("Hello", {
  style: {
    fontSize: "24px",
    fontWeight: "bold",
    color: "#333333",
  },
});

Style priority (highest to lowest):

  1. Element-level style option
  2. Global theme configuration
  3. Built-in defaults

Examples

Welcome Email

import { email, section, text, button, divider } from "emaildsl";

const welcomeEmail = email({
  title: "Welcome to Our Platform",
  theme: {
    colors: {
      primary: "#4CAF50",
      text: "#333333",
    },
  },
  body: [
    section([
      text("Welcome!", { style: { fontSize: "24px", fontWeight: "bold" } }),
      text("We're excited to have you on board."),
      button("Get Started", {
        href: "https://example.com/onboarding",
        style: { backgroundColor: "#4CAF50" },
      }),
      divider(),
      text("Questions? Reply to this email.", {
        style: { fontSize: "12px", color: "#666666" },
      }),
    ]),
  ],
});

const html = welcomeEmail.render();

Receipt Email

import { email, section, text, divider } from "emaildsl";

const receipt = email({
  title: "Order Receipt",
  body: [
    section([
      text("Order Confirmation", { style: { fontSize: "24px" } }),
      text("Order #12345"),
      divider(),
      text("Product Name"),
      text("$99.00", { style: { fontWeight: "bold" } }),
      text("Shipping: $5.00"),
      divider(),
      text("Total: $104.00", {
        style: { fontSize: "18px", fontWeight: "bold" },
      }),
    ]),
  ],
});

Multi-column Layout

import { email, section, column, text } from "emaildsl";

const newsletter = email({
  body: [
    section([
      column(
        [
          text("Column 1 Header", { style: { fontWeight: "bold" } }),
          text("Left side content goes here."),
        ],
        { width: "50%" },
      ),
      column(
        [
          text("Column 2 Header", { style: { fontWeight: "bold" } }),
          text("Right side content goes here."),
        ],
        { width: "50%" },
      ),
    ]),
  ],
});

Advanced Theming

import { email, section, text, button } from "emaildsl";

const themedEmail = email({
  theme: {
    colors: {
      primary: "#2196F3",
      secondary: "#FFC107",
      text: "#212121",
      background: "#FAFAFA",
    },
    fonts: {
      family: "Helvetica, Arial, sans-serif",
      size: "16px",
    },
    spacing: {
      section: "32px",
      element: "16px",
    },
    button: {
      borderRadius: "8px",
      padding: "14px 28px",
    },
  },
  body: [
    section([
      text("Themed Email"),
      button("Action Button", { href: "https://example.com" }),
    ]),
  ],
});

Email Client Support

EmailDSL generates HTML that works across all major email clients:

  • Gmail (web, iOS, Android)
  • Outlook 2016/2019/365 (Windows)
  • Outlook.com
  • Apple Mail (macOS, iOS)
  • Yahoo Mail
  • AOL Mail
  • Thunderbird
  • And more

Why EmailDSL?

The Problem

Writing HTML emails is notoriously difficult:

  • Email clients use outdated rendering engines
  • Modern CSS (Flexbox, Grid) doesn't work
  • Styles must be inline
  • Tables are required for layout
  • Each client has unique quirks

The Solution

EmailDSL abstracts away the complexity:

// Instead of this:
<table cellpadding="0" cellspacing="0" border="0" width="100%">
  <tr>
    <td style="padding: 20px; font-family: Arial, sans-serif; font-size: 16px; color: #333333;">
      Hello World
    </td>
  </tr>
</table>;

// Write this:
section([text("Hello World")]);

Development

Prerequisites

  • Node.js 18+
  • pnpm

Setup

git clone https://github.com/veri5ied/emaildsl.git
cd emaildsl
pnpm install

Commands

pnpm dev      # Watch mode with auto-rebuild
pnpm build    # Build for production
pnpm test     # Run tests
pnpm test:ui  # Run tests with UI
pnpm lint     # Lint code

Project Structure

emaildsl/
├── src/
│   ├── primitives/     # DSL primitive implementations
│   ├── renderer/       # HTML rendering logic
│   ├── types/          # TypeScript definitions
│   └── index.ts        # Main export
├── examples/           # Example email templates
├── tests/              # Unit + integration tests
└── package.json

TypeScript Support

EmailDSL is written in TypeScript and provides full type safety:

import { email, section, text } from "emaildsl";

// TypeScript will catch errors:
email({
  title: 123, // ❌ Error: Type 'number' is not assignable to type 'string'
  body: [
    section([
      text("Hello", {
        style: {
          color: "red",
          fontWeight: "bold",
          invalidProp: true, // ❌ Error: Object literal may only specify known properties
        },
      }),
    ]),
  ],
});

Roadmap

  • [x] Core TypeScript DSL
  • [x] HTML renderer with table-based layouts
  • [x] Inline style generation
  • [x] Global theme system
  • [x] Component-level style overrides
  • [x] Publish to npm
  • [x] React renderer (optional, for live previews)
  • [x] Vue renderer (optional)
  • [ ] Svelte renderer (optional)
  • [ ] Framework-agnostic usage in all JS environments
  • [ ] Pre-built email template library
  • [ ] Visual email builder
  • [ ] Email testing utilities
  • [ ] Integration with email sending services

Contributing

Contributions are welcome! Please follow these steps:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Please ensure:

  • All tests pass (pnpm test)
  • Code is linted (pnpm lint)
  • TypeScript types are correct
  • You've added tests for new features

License

MIT License - see LICENSE file for details.

Support

  • Issues: GitHub Issues
  • Discussions: Coming soon
  • Documentation: Coming soon

Acknowledgments

EmailDSL was created to solve the universal pain of writing cross-client compatible email HTML. It draws inspiration from React Email and MJML while maintaining complete framework independence.


Built with TypeScript. Tested across major email clients.