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

@useinsider/guido

v3.0.0-beta.a72fd61

Published

Guido is a Vue + TypeScript wrapper for Email Plugin. Easily embed the email editor in your Vue applications.

Downloads

20,906

Readme

@useinsider/guido

Guido is a Vue 2 + TypeScript wrapper for the Stripo Email Editor plugin. Easily embed the professional email editor in your Vue applications with a clean, type-safe configuration.

Installation

npm install @useinsider/guido

Prerequisites

Your project needs:

  • Vue 2.7+
  • Pinia (state management)

Add these to your bundler config to optimize dependencies:

Webpack (webpack.config.js or vue.config.js):

shared: {
  vue: { singleton: true },
  pinia: { singleton: true },
},

Vite (vite.config.js):

resolve: {
  dedupe: ['vue', 'pinia'],
},

Quick Start

<template>
  <Guido
    ref="guidoRef"
    :config="config"
    @ready="onReady"
    @dynamic-content:open="onDynamicContentOpen"
    @save:complete="onSaveComplete"
  />
</template>

<script setup lang="ts">
import { ref } from 'vue';
import { Guido } from '@useinsider/guido';
import type { GuidoConfigInput } from '@useinsider/guido';

const guidoRef = ref<InstanceType<typeof Guido> | null>(null);

const config = ref<GuidoConfigInput>({
  identity: {
    templateId: 'template-123',
    userId: 'user-456',
  },
  partner: {
    name: 'your-partner-name',
  },
  template: {
    html: '<p>Initial content</p>',
    css: '',
  },
});

const onReady = () => console.log('Editor ready');
const onDynamicContentOpen = () => console.log('Dynamic content requested');
const onSaveComplete = (template) => console.log('Saved:', template);
</script>

Configuration

Guido uses a single, validated config prop organized by domain:

import type { GuidoConfigInput } from '@useinsider/guido';

const config: GuidoConfigInput = {
  // Required: Identity
  identity: {
    templateId: string,      // Required - Template identifier
    userId: string,          // Required - User identifier
    variationId?: string,    // Optional - A/B test variation
  },

  // Required: Partner
  partner: {
    name: string,            // Required - Partner name
    productType?: number,    // Optional - Default: 60 (Email)
    messageType?: number,    // Optional - Default: 1 (Promotional)
    username?: string,       // Optional - Default: 'Guido User'
  },

  // Optional: Template content
  template?: {
    html?: string,
    css?: string,
    preselectedDynamicContent?: DynamicContent[],
    selectedUnsubscribePages?: number[],
    forceRecreate?: boolean,       // Default: false - Force recreate template in Stripo storage
  },

  // Optional: Editor settings
  editor?: {
    locale?: string,              // Default: 'en'
    translationsPath?: string,    // Default: 'window.trans.en'
    migrationDate?: number,       // Stripo migration timestamp
    emailHeader?: {
      senderName?: string,
      subject?: string,
    },
    savedModulesFolderName?: string,    // Default: 'savedModules' - folder name for user-saved modules
    defaultModulesFolderName?: string,  // Default: 'defaultModules' - folder name for default/prebuilt modules
  },

  // Optional: UI settings
  ui?: {
    showHeader?: boolean,         // Default: true
    backButtonLabel?: string,
  },

  // Optional: Feature toggles
  features?: {
    dynamicContent?: boolean,     // Default: true
    saveAsTemplate?: boolean,     // Default: true
    versionHistory?: boolean,     // Default: true
    testMessage?: boolean,        // Default: true
    displayConditions?: boolean,  // Default: true
    unsubscribe?: boolean,        // Default: true
    modulesDisabled?: boolean,    // Default: false - Disable modules panel
  },

  // Optional: Callbacks
  callbacks?: {
    externalValidation?: (data: SavedTemplateDetails) => Promise<boolean>,  // Return false to cancel save
  },

  // Optional: Block configuration
  blocks?: {
    excludeDefaults?: DefaultBlockType[],
    includeCustoms?: CustomBlockType[],
  },

  // Optional: HTML compiler
  compiler?: {
    customRules?: CompilerRule[],
    ignoreDefaultRules?: boolean,  // Default: false
  },
};

Events

| Event | Payload | Description | |-------|---------|-------------| | ready | - | Editor is loaded and ready | | dynamic-content:open | DynamicContent \| null | User wants to insert dynamic content | | back | - | Back button clicked | | save:start | - | Save process started | | save:complete | SavedTemplateDetails | Save completed successfully (includes metadata) | | on-change | - | Template was modified | | test-email:click | - | Test email button clicked | | onboarding-finished | - | Onboarding popup dismissed |

save:complete Payload

The save:complete event emits a SavedTemplateDetails object containing the compiled template data along with editor metadata:

interface SavedTemplateDetails {
  dynamicContentList: DynamicContent[];
  compiledHtml: string;
  rawHtml: string;
  css: string;
  ampHtml: string;
  ampErrors: string[];
  modules: number[];
  recommendation: {
    campaignUrls: Record<string, string>;
    configs: Record<string, string>;
  };
  unsubscribe: {
    status: boolean;
    config: number[];
  };
  metadata: Metadata;
}

interface Metadata {
  emailId: string;
  partnerName?: string;
  productType?: number;
  userId: string;
  username?: string;
  savedModulesFolderName?: string;
  defaultModulesFolderName?: string;
}

⚠️ Important: The metadata object in the save:complete payload must be passed directly into your templateConfig / stripoConfig object while saving. This ensures the email-service receives the correct version of sync modules features


Exposed Methods

const guidoRef = ref<InstanceType<typeof Guido> | null>(null);

// Insert dynamic content
guidoRef.value?.dynamicContent.insert({
  text: 'Display Name',
  value: 'variable_name',
  fallback: 'Default Value',
});

// Close dynamic content modal
guidoRef.value?.dynamicContent.close();

// Silent save (no UI feedback)
guidoRef.value?.saveSilent();

Block Configuration

Default Blocks (can be excluded)

type DefaultBlockType =
  | 'amp-accordion'
  | 'amp-carousel'
  | 'amp-form-controls'
  | 'banner-block'
  | 'button-block'
  | 'html-block'
  | 'image-block'
  | 'menu-block'
  | 'social-block'
  | 'spacer-block'
  | 'text-block'
  | 'timer-block'
  | 'video-block';

Custom Blocks (opt-in)

type CustomBlockType =
  | 'dynamic-content'
  | 'checkbox-block'
  | 'radio-button-block'
  | 'recommendation-block'
  | 'unsubscribe-block'
  | 'coupon-block'
  | 'items-block';

Examples

// Exclude specific default blocks
const config: GuidoConfigInput = {
  identity: { templateId: 'tpl-123', userId: 'user-456' },
  partner: { name: 'partner' },
  blocks: {
    excludeDefaults: ['timer-block', 'video-block'],
  },
};

// Include custom blocks
const config: GuidoConfigInput = {
  identity: { templateId: 'tpl-123', userId: 'user-456' },
  partner: { name: 'partner' },
  blocks: {
    includeCustoms: ['recommendation-block', 'coupon-block', 'dynamic-content'],
  },
};

Module Folder Configuration

Customize the Stripo module folder names for saved and default modules. These values are passed to Stripo metadata and the dynamic folder paths are constructed in the Stripo plugin panel configuration.

const config: GuidoConfigInput = {
  identity: { templateId: 'tpl-123', userId: 'user-456' },
  partner: { name: 'acme' },
  editor: {
    // Folder name for user-saved modules
    savedModulesFolderName: 'savedModules',

    // Folder name for default/prebuilt modules
    defaultModulesFolderName: 'defaultModules',
  },
};

Default Values

| Config Option | Default Value | |--------------|---------------| | savedModulesFolderName | 'savedModules' | | defaultModulesFolderName | 'defaultModules' |

Note: The actual folder paths (e.g., guido_acme_savedModules) are configured in the Stripo plugin panel using variable substitution like ${savedModulesFolderName}.


HTML Compiler Rules

Add custom rules to transform HTML during export:

const config: GuidoConfigInput = {
  identity: { templateId: 'tpl-123', userId: 'user-456' },
  partner: { name: 'partner' },
  compiler: {
    customRules: [
      // Replace rule
      {
        id: 'replace-domain',
        type: 'replace',
        search: 'old-domain.com',
        replacement: 'new-domain.com',
        priority: 10,
      },
      // Regex rule
      {
        id: 'remove-comments',
        type: 'regex',
        pattern: '<!--.*?-->',
        replacement: '',
        flags: 'g',
        priority: 20,
      },
      // Custom processor
      {
        id: 'add-tracking',
        type: 'custom',
        processor: (html) => html.replace('</body>', '<img src="track.gif"/></body>'),
        priority: 30,
      },
    ],
    ignoreDefaultRules: false, // Set true to skip built-in rules
  },
};

TypeScript Exports

// Component
import { Guido } from '@useinsider/guido';

// Types
import type {
  GuidoConfig,
  GuidoConfigInput,
  IdentityConfig,
  PartnerConfig,
  TemplateConfig,
  EditorConfig,
  UIConfig,
  FeaturesConfig,
  BlocksConfig,
  CompilerConfig,
  DynamicContent,
  DefaultBlockType,
  CustomBlockType,
} from '@useinsider/guido';

// Utilities
import {
  validateConfig,
  parseConfig,
  MessageType,
  ProductType,
} from '@useinsider/guido';

// Styles
import '@useinsider/guido/style';

Constants

import { MessageType, ProductType } from '@useinsider/guido';

MessageType.PROMOTIONAL    // 1
MessageType.TRANSACTIONAL  // 2

ProductType.EMAIL          // 60
ProductType.ARCHITECT      // 49
ProductType.UNSUBSCRIBE_PAGES // 97

Dynamic Content Modal

When the dynamic-content:open event fires, show your custom modal and call the insert method:

<template>
  <Guido ref="guidoRef" :config="config" @dynamic-content:open="showModal = true" />

  <!-- Your modal must have id="guido-dynamic-content-modal" -->
  <YourModal v-if="showModal" id="guido-dynamic-content-modal" @select="insertContent" @close="closeModal" />
</template>

<script setup>
const showModal = ref(false);

const insertContent = (content) => {
  guidoRef.value?.dynamicContent.insert({
    text: content.label,
    value: content.value,
    fallback: content.fallback || '',
  });
  showModal.value = false;
};

const closeModal = () => {
  guidoRef.value?.dynamicContent.close();
  showModal.value = false;
};
</script>

Development

# Install
bun install

# Start dev server
bun start

# Build
bun run build

# Lint & type-check
bun run lint

Environment Variables

VITE_STRIPO_PLUGIN_ID=your_plugin_id
VITE_STRIPO_SECRET_KEY=your_secret_key
VITE_STRIPO_ROLE=your_role

Local Testing

# Build the package
bun run build

# Create tarball
npm pack

# Install in your project
cd ../your-project
npm install ../guido/useinsider-guido-1.0.0.tgz

License

ISC License