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

@beefree.io/vue-email-builder

v1.1.1

Published

Vue.js wrapper for the Beefree SDK – A framework-specific package that provides the Builder component and composables to integrate the Beefree SDK (Email Builder, Page Builder, File Manager, Popup Builder) into Vue.js applications

Readme

Beefree SDK Vue.js Components

npm version License TypeScript Vue

A Vue 3 wrapper for the Beefree SDK, providing the Builder component and composables to integrate the Beefree email, page, and popup builder into Vue.js applications.

Table of Contents

What is Beefree SDK?

Beefree SDK is a drag-and-drop visual content builder that lets your users design professional emails, landing pages, and popups — without writing code. It powers thousands of SaaS applications worldwide, offering a white-label, embeddable editing experience with real-time collaborative editing, responsive design output, and extensive customization options.

This Vue package provides a Builder component and a useBuilder composable that handle SDK initialization, lifecycle management, and configuration updates — giving you a Vue-friendly API to integrate the full Beefree editing experience into your application.

Overview

Features

  • Simple Vue Integration - Drop-in component with minimal setup
  • Composition API - useBuilder composable for programmatic control
  • Dynamic Configuration - Update builder configuration reactively
  • Collaborative Editing - Support for shared/collaborative sessions
  • TypeScript Support - Full TypeScript definitions included
  • Customizable - Full access to Beefree SDK configuration options

Compatibility

| Requirement | Version | | ----------- | ------------------------------------------------- | | Vue | >= 3.3 | | Node.js | >= 18.0.0 | | TypeScript | >= 4.7 (optional, but recommended) | | Browsers | Chrome, Firefox, Safari, Edge (latest 2 versions) |

Installation

npm install @beefree.io/vue-email-builder
# or
yarn add @beefree.io/vue-email-builder

Peer Dependencies

This package requires Vue 3.3+ as a peer dependency:

npm install vue

Quick Start

1. Get your credentials

Sign up at developers.beefree.io to get your client_id and client_secret.

2. Set up token generation on your backend

Your backend server should exchange credentials for a short-lived token (see Security: Server-Side Token Generation below for details):

// Example: Node.js/Express backend endpoint
app.post('/api/beefree/token', async (req, res) => {
  const response = await fetch('https://auth.getbee.io/apiauth', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      client_id: process.env.BEEFREE_CLIENT_ID,
      client_secret: process.env.BEEFREE_CLIENT_SECRET,
      grant_type: 'password',
    }),
  })
  res.json(await response.json())
})

3. Integrate the builder in your Vue app

<template>
  <div>
    <div>
      <button @click="preview()">Preview</button>
      <button @click="save()">Save</button>
    </div>
    <Builder v-if="token" :token="token" :config="config" @bb-save="onSave" @bb-error="onError" />
    <div v-else>Loading builder...</div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted } from 'vue'
import { Builder, useBuilder } from '@beefree.io/vue-email-builder'
import type { IToken } from '@beefree.io/vue-email-builder'

const token = ref<IToken | null>(null)

const config = {
  uid: 'user-123',
  container: 'bee-container',
  language: 'en-US',
}

const { save, preview } = useBuilder(config)

onMounted(async () => {
  const res = await fetch('/api/beefree/token', { method: 'POST' })
  token.value = await res.json()
})

function onSave(args: [string, string, string | null, number, string | null]) {
  const [pageJson, pageHtml] = args
  console.log('Saved:', { pageJson, pageHtml })
}

function onError(error: unknown) {
  console.error('Builder error:', error)
}
</script>

API Reference

Builder Component

The component that wraps the Beefree SDK. Use it for email, page, popup, or file-manager flows by passing the appropriate token and config.

Props

| Prop | Type | Default | Description | | ----------- | -------------------- | ---------------------------------------- | ---------------------------------------------- | | token | IToken | required | Authentication token from Beefree API | | template | IEntityContentJson | null | Template JSON to load | | config | IBeeConfig | { container: 'beefree-sdk-container' } | SDK configuration | | width | string | '100%' | Container width | | height | string | '100%' | Container height | | shared | boolean | false | Enable collaborative editing session | | sessionId | string | null | Session ID to join (for collaborative editing) | | loaderUrl | string | null | Custom SDK loader URL | | bucketDir | string | undefined | Custom bucket directory |

Events

All events are prefixed with bb- (Beefree Builder) to avoid collisions with native DOM events:

| Event | SDK Callback | Payload | | ----------------------------- | -------------------------- | ---------------------------------------------------------- | | bb-save | onSave | [pageJson, pageHtml, ampHtml, templateVersion, language] | | bb-save-as-template | onSaveAsTemplate | [pageJson, templateVersion] | | bb-send | onSend | htmlFile | | bb-error | onError | error | | bb-warning | onWarning | warning | | bb-load | onLoad | value | | bb-change | onChange | [json, detail, version] | | bb-auto-save | onAutoSave | json | | bb-start | onStart | — | | bb-comment | onComment | [comment, action] | | bb-info | onInfo | info | | bb-preview | onPreview | isOpen | | bb-toggle-preview | onTogglePreview | isOpen | | bb-preview-change | onPreviewChange | value | | bb-save-row | onSaveRow | [rowJson, rowHtml, rowMeta] | | bb-remote-change | onRemoteChange | [json, detail, version] | | bb-session-change | onSessionChange | value | | bb-session-started | onSessionStarted | value | | bb-template-language-change | onTemplateLanguageChange | { label, value, isMain } | | bb-view-change | onViewChange | value | | bb-load-workspace | onLoadWorkspace | value |

Handling Builder Events

Use Vue's native event system to react to builder events. All events use the bb- prefix:

<template>
  <Builder
    :token="token"
    :config="config"
    @bb-save="onSave"
    @bb-error="onError"
    @bb-session-started="onSessionStarted"
  />
</template>

<script setup lang="ts">
function onSave(args: [string, string, string | null, number, string | null]) {
  const [pageJson, pageHtml] = args
  console.log('Saved:', { pageJson, pageHtml })
}

function onError(error: unknown) {
  console.error('Builder error:', error)
}
</script>

Note for developers coming from React: The Builder component also supports defining callbacks directly in the config object (e.g., onSave, onError). If both are provided, the config callback fires first, then the Vue event is emitted. While this works, the events-based approach shown above is the idiomatic Vue pattern and is recommended for new projects.

Composable: useBuilder

The useBuilder composable provides programmatic control over a builder instance. It must be called at the top level of <script setup> (as with all Vue composables).

<script setup lang="ts">
import { useBuilder } from '@beefree.io/vue-email-builder'

const config = {
  container: 'bee-editor',
  uid: 'user-123',
  language: 'en-US',
}

const {
  save,
  load,
  preview,
  togglePreview,
  updateConfig,
  getTemplateJson,
  switchTemplateLanguage,
} = useBuilder(config)

async function changeLanguage(lang: string) {
  await updateConfig({ language: lang })
}
</script>

How It Works

The composable connects to the builder instance through the container ID:

  1. You call useBuilder(config) with a config that includes a container ID.
  2. When a Builder component with a matching container mounts, the composable automatically binds to its SDK instance.
  3. Methods like save() and preview() delegate to the live SDK instance via closures — reactivity is maintained without computed wrappers.
  4. When the component unmounts, the composable cleans up its config registry entry.

Available Methods

| Method | Description | | -------------------------------- | ----------------------------------------- | | updateConfig(partial) | Updates builder configuration dynamically | | save(options?) | Triggers save action | | saveAsTemplate() | Saves as template | | send(args?) | Sends the email | | load(template) | Loads a template JSON | | reload(template, options?) | Reloads without loading dialog | | preview() | Opens preview | | togglePreview() | Toggles preview | | switchPreview(args?) | Switches preview language | | toggleComments() | Toggles comments panel | | toggleStructure() | Toggles structure outlines | | toggleMergeTagsPreview() | Toggles merge tag preview | | switchTemplateLanguage(args) | Switches content language | | getTemplateJson() | Returns template JSON | | getConfig() | Returns current config | | loadConfig(args, options?) | Loads new config | | loadStageMode(args) | Loads stage mode | | loadWorkspace(type) | Loads workspace | | loadRows() | Loads rows | | showComment(comment) | Shows a comment | | updateToken(token) | Updates auth token | | execCommand(command, options?) | Executes editor command | | startFileManager(config, ...) | Starts file manager | | join(config, sessionId, ...) | Joins shared session | | start(config, template, ...) | Starts builder |

Best Practices

🔒 Security: Server-Side Token Generation

⚠️ CRITICAL: Never expose your Beefree API credentials in frontend code!

❌ Bad (Insecure):

// DON'T DO THIS!
const token = await fetch('https://auth.getbee.io/loginV2', {
  method: 'POST',
  body: JSON.stringify({
    client_id: 'your-client-id', // ❌ Exposed!
    client_secret: 'your-secret', // ❌ Exposed!
  }),
})

✅ Good (Secure):

  1. Backend API endpoint (Node.js/Express example):
// backend/routes/auth.js
app.post('/api/beefree/token', async (req, res) => {
  const response = await fetch('https://auth.getbee.io/apiauth', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      client_id: process.env.BEEFREE_CLIENT_ID,
      client_secret: process.env.BEEFREE_CLIENT_SECRET,
      uid: req.user.id,
    }),
  })

  const token = await response.json()
  res.json(token)
})
  1. Frontend:
<script setup lang="ts">
import { ref, onMounted } from 'vue'
import type { IToken } from '@beefree.io/vue-email-builder'

const token = ref<IToken | null>(null)

onMounted(async () => {
  const response = await fetch('/api/beefree/token', {
    method: 'POST',
    credentials: 'include',
  })
  token.value = await response.json()
})
</script>

🎯 Unique Container IDs

When using multiple builders on the same page, ensure unique container IDs:

<script setup lang="ts">
const builder1 = useBuilder({ container: 'builder-1', uid: 'user-1' })
const builder2 = useBuilder({ container: 'builder-2', uid: 'user-2' })
</script>

📝 Reactive Configuration

Use reactive() for configs that need runtime updates (e.g., language switching). The Builder component deep-watches its config prop and syncs callbacks automatically:

<script setup lang="ts">
import { reactive } from 'vue'

const config = reactive({
  uid: 'user-123',
  container: 'bee-editor',
  language: 'en-US',
  onSave: (json: string, html: string) => {
    console.log('Saved:', { json, html })
  },
})

function changeLanguage(lang: string) {
  config.language = lang
}
</script>

🔄 Collaborative Editing

For collaborative sessions, share the sessionId between users:

<template>
  <!-- Host creates the session -->
  <Builder
    :token="token"
    :config="hostConfig"
    :shared="true"
    @bb-session-started="onSessionStarted"
  />

  <!-- Guest joins with sessionId -->
  <Builder
    v-if="sessionId && guestToken"
    :token="guestToken"
    :config="guestConfig"
    :shared="true"
    :session-id="sessionId"
  />
</template>

<script setup lang="ts">
import { ref } from 'vue'

const sessionId = ref<string | null>(null)

function onSessionStarted(event: { sessionId?: string }) {
  if (event?.sessionId) {
    sessionId.value = event.sessionId
  }
}
</script>

Advanced Usage

Custom Content Dialogs

const config = {
  contentDialog: {
    saveRow: {
      label: 'Save to Library',
      handler: async (resolve) => {
        const rowName = await showCustomDialog()
        resolve({ name: rowName })
      },
    },
    addOn: {
      handler: async (resolve) => {
        const content = await fetchCustomContent()
        resolve(content)
      },
    },
  },
}

External Content Sources

const config = {
  rowsConfiguration: {
    externalContentURLs: [
      {
        name: 'My Saved Rows',
        handle: 'saved-rows',
        isLocal: true,
      },
    ],
  },
  hooks: {
    getRows: {
      handler: async (resolve, reject, args) => {
        if (args.handle === 'saved-rows') {
          const rows = await fetchSavedRows()
          resolve(rows)
        } else {
          reject('Handle not found')
        }
      },
    },
  },
}

Mentions/Merge Tags

const config = {
  hooks: {
    getMentions: {
      handler: async (resolve) => {
        const mentions = [
          { username: 'FirstName', value: '{{firstName}}', uid: 'fn' },
          { username: 'LastName', value: '{{lastName}}', uid: 'ln' },
        ]
        resolve(mentions)
      },
    },
  },
}

Examples

The /example directory contains a fully working application that demonstrates:

  • Token authentication flow
  • Collaborative editing with template preservation
  • Save/preview actions and downloads from builder callbacks (Save -> .html, Save as Template -> .json)
  • Multi-language UI switching (header + example control labels outside the builder)
  • Sample/blank template toggle with local blank template fallback
  • Different builder modes (email, page, popup, file manager) via config
  • Per-instance control bars in co-editing mode
  • Keyboard-accessible split divider with ARIA attributes
  • Reusable toast notification system

Quick start:

cd example
cp .env.sample .env   # Fill in your Beefree credentials
cd ..
yarn install
yarn start            # Opens at http://localhost:5173

FAQ

How do I authenticate with the Beefree SDK?

Authentication requires a client_id and client_secret, which you get by signing up at developers.beefree.io. These credentials should never be exposed in frontend code. Instead, create a backend endpoint that exchanges them for a short-lived token and pass that token to the Builder component. See Security: Server-Side Token Generation for a complete example.

Can I use this with Nuxt, Vite, or other Vue frameworks?

Yes. This package works with any Vue 3-based framework. For Nuxt 3, wrap the builder in a <ClientOnly> component since the SDK requires the DOM. For Vite, it works out of the box. For Quasar or other Vue 3 frameworks, use them as you would any Vue component.

Does it support collaborative editing?

Yes. Set :shared="true" on the Builder component to create a collaborative session. The bb-session-started event provides a sessionId that other users can use to join the same session. See Collaborative Editing for a full example.

What email clients are supported?

The Beefree SDK generates responsive HTML that is compatible with all major email clients, including Gmail, Outlook (desktop and web), Apple Mail, Yahoo Mail, and mobile email apps. The output follows email HTML best practices with inline CSS and table-based layouts for maximum compatibility.

Can I customize the builder UI?

Yes. The Beefree SDK supports extensive UI customization including custom content dialogs, external content sources, merge tags, special links, and more. See Advanced Usage and the Beefree SDK Documentation for the full range of customization options.

How do I load an existing template?

Pass your template JSON to the :template prop of the Builder component. You can also use the load method from the useBuilder composable to programmatically load a template at any time after initialization.

Can I use the Options API instead of <script setup>?

The useBuilder composable must be called within a Vue setup context (either <script setup> or inside the setup() function). The Builder component works with both the Options API and the Composition API.

Development

Prerequisites

  • Node.js >= 18 (see .nvmrc)
  • Yarn 4

Setup

# Install dependencies
yarn install

# Start the example dev server
yarn start

# Run tests
yarn test

# Run tests once (CI)
yarn test:ci

# Lint
yarn lint

# Build library
yarn build

Building

yarn build

The library build uses Vite library mode (vite.lib.config.ts) and generates ESM, CJS, and DTS outputs.

Outputs:

  • dist/index.js - CommonJS bundle
  • dist/index.es.js - ES module bundle
  • dist/index.d.ts - TypeScript definitions

Project Structure

src/                      # Library source
  components/             # Vue component (Builder)
  composables/            # Vue composables (useBuilder, useRegistry)
  types.ts                # TypeScript types
  constants.ts            # Constants
  index.ts                # Public API exports
  __tests__/              # Test files

example/                  # Example application (Vite dev server)
  App.vue                 # Root component with toast system
  BeefreeExample.vue      # Demo component with co-editing
  beefree-token.ts        # Token service (demo only)
  environment.ts          # Environment config
  i18n/                   # Localization files (22 languages)

Environment Variables

Copy example/.env.sample to example/.env and fill in your Beefree SDK credentials:

VITE_EMAIL_BUILDER_CLIENT_ID=your-client-id
VITE_EMAIL_BUILDER_CLIENT_SECRET=your-client-secret
VITE_EMAIL_BUILDER_USER_ID=your-user-id

VITE_PAGE_BUILDER_CLIENT_ID=your-client-id
VITE_PAGE_BUILDER_CLIENT_SECRET=your-client-secret
VITE_PAGE_BUILDER_USER_ID=your-user-id

VITE_POPUP_BUILDER_CLIENT_ID=your-client-id
VITE_POPUP_BUILDER_CLIENT_SECRET=your-client-secret
VITE_POPUP_BUILDER_USER_ID=your-user-id

VITE_FILE_MANAGER_CLIENT_ID=your-client-id
VITE_FILE_MANAGER_CLIENT_SECRET=your-client-secret
VITE_FILE_MANAGER_USER_ID=your-user-id

# Optional: override sample template URLs used by the example UI
VITE_EMAIL_TEMPLATE_URL=https://rsrc.getbee.io/api/templates/m-bee
VITE_PAGE_TEMPLATE_URL=https://rsrc.getbee.io/api/templates/m-bee-page
VITE_POPUP_TEMPLATE_URL=https://rsrc.getbee.io/api/templates/m-bee-popup

Troubleshooting

Builder not loading

  1. Verify token is valid and not expired
  2. Check the browser console for errors
  3. Ensure container ID is unique on the page
  4. Confirm uid is set in the config

Builder not responding to useBuilder methods

The container ID in your useBuilder config must match the container in the Builder component's config. The composable binds to the SDK instance by container ID.

Other Frameworks

Beefree SDK wrappers are available for the following frameworks:

| Framework | Package | Repository | | --------- | ----------------------------------- | --------------------------------------------------------------------------------------- | | React | @beefree.io/react-email-builder | BeefreeSDK/react-email-builder | | Angular | @beefree.io/angular-email-builder | BeefreeSDK/angular-email-builder |

License

Apache License 2.0

Support

For issues related to:

Resources