npm.io
1.0.4 • Published 2d ago

@plexobuilder/sdk

Licence
MIT
Version
1.0.4
Deps
6
Size
480 kB
Vulns
0
Weekly
0

@plexobuilder/sdk

Visual drag-and-drop email & landing page builder SDK with AI integration — built for React.

npm version license


Features

  • Visual drag-and-drop builder — rows, columns, and elements with live editing
  • Email & Landing Page modes — export clean, production-ready HTML for both
  • AI content generation — built-in support for OpenAI, Gemini, and Claude
  • Stock image search — Unsplash, Pexels, Pixabay integrations
  • Design token system — Strata token support for consistent brand theming
  • ESM-only, pure client-side — zero server-side dependencies

Installation

npm install @plexobuilder/sdk

Peer dependencies (install if not already present):

npm install react react-dom

Quick Start

Plain React (Vite / CRA)
import { useRef } from 'react';
import { PlexoBuilder, type PlexoBuilderRef } from '@plexobuilder/sdk';
// Import the builder's stylesheet
import '@plexobuilder/sdk/dist/sdk.css';

export function Editor() {
  const builderRef = useRef<PlexoBuilderRef>(null);

  const handleSave = async () => {
    const result = await builderRef.current?.exportDesign('email');
    console.log('HTML:', result?.html);
    console.log('JSON:', result?.json);
  };

  return (
    <div style={{ height: '100vh' }}>
      <PlexoBuilder
        ref={builderRef}
        apiKey="your-api-key"
        mode="email"
        backgroundColor="#ffffff"
        themeBgColor="#6d28d9"
        themeFgColor="#ffffff"
        textColor="#111827"
        showSaveButton={false}
      />
      <button onClick={handleSave}>Save</button>
    </div>
  );
}

Next.js (App Router)

Important: The SDK is a purely client-side component that uses drag-and-drop and browser APIs. It must never be rendered on the server.

Step 1 — Create a dynamic wrapper

Because the SDK uses browser-only APIs, wrap it with next/dynamic and disable SSR. Be sure to import the CSS stylesheet:

// components/template-editor.tsx
'use client';

import dynamic from 'next/dynamic';
import type { PlexoBuilderRef } from '@plexobuilder/sdk';
import { useRef } from 'react';

// Import the builder's stylesheet
import '@plexobuilder/sdk/dist/sdk.css';

// Never SSR the builder — it relies on browser APIs (drag-and-drop, ResizeObserver, etc.)
const PlexoBuilder = dynamic(
  () => import('@plexobuilder/sdk').then((m) => ({ default: m.PlexoBuilder })),
  { ssr: false, loading: () => <p>Loading builder…</p> }
);

export function TemplateEditor() {
  const builderRef = useRef<PlexoBuilderRef>(null);

  const handleSave = async () => {
    const result = await builderRef.current?.exportDesign('email');
    console.log(result?.html);
  };

  return (
    <div style={{ height: '100vh' }}>
      <PlexoBuilder
        ref={builderRef}
        apiKey="your-api-key"
        mode="email"
        backgroundColor="#ffffff"
        themeBgColor="#6d28d9"
        themeFgColor="#ffffff"
        textColor="#111827"
        showSaveButton={false}
      />
      <button onClick={handleSave}>Save</button>
    </div>
  );
}
Step 2 — Use in a Server Component page
// app/editor/page.tsx  (Server Component — no "use client")
import { TemplateEditor } from '@/components/template-editor';

export default function EditorPage() {
  return <TemplateEditor />;
}

Props Reference

PlexoBuilder
Prop Type Default Description
mode 'email' | 'landing_page' Required. Output mode for the editor
apiKey string Required. Your Plexo API key
initialTemplate TemplateJSON Pre-load a saved template JSON
initialHtml string Pre-load raw HTML (landing page mode)
initialCss string Pre-load CSS (landing page mode)
initialJs string Pre-load JS (landing page mode)
showSaveButton boolean true Show/hide the built-in save button
onSave (data: { json, html }) => void Callback when built-in save button is clicked
autoSave boolean false Auto-save periodically
autoSaveDuration number 3000 Auto-save interval in ms
onUpload (file: File) => Promise<string> | string Custom image upload handler, returns URL
backgroundColor string '#ffffff' Canvas background colour
themeBgColor string '#000000' Primary brand/accent colour
themeFgColor string '#ffffff' Foreground colour on brand elements
textColor string '#000000' Default body text colour
useAi boolean false Enable AI content generation
aiProvider 'openai' | 'gemini' | 'claude' 'openai' AI provider
aiApiKey string API key for the AI provider (client-side)
aiTier 'AUTO' | 'BASIC' | 'MEDIUM' | 'HIGH' 'AUTO' AI model tier
unsplashKey string Unsplash API key for stock images
pexelsKey string Pexels API key for stock images
pixabayKey string Pixabay API key for stock images

PlexoBuilderRef — Imperative API

Access via ref on the component:

const builderRef = useRef<PlexoBuilderRef>(null);

// Export the current design
const { json, html } = await builderRef.current.exportDesign('email');
// or:
const { json, html } = await builderRef.current.exportDesign('landing_page');

// Get the JSON without compiling HTML
const json = builderRef.current.getJson();
Method Signature Description
exportDesign (target: 'email' | 'landing_page') => Promise<{ json: TemplateJSON; html: string }> Compile & export the current design
getJson () => TemplateJSON Get the raw design JSON snapshot

Compiler Utilities (Server-safe)

These utilities run without browser APIs — safe to use in Node.js, server components, or API routes:

import {
  compileToHTML,
  compileToPlainText,
  compileToHTMLWithStrataAuto,
  parseJsonToTargetFormat,
  injectStrataBundle,
} from '@plexobuilder/sdk';
Utility Description
compileToHTML(json, target) Compile TemplateJSON to HTML string
compileToPlainText(json) Extract plain text from a template
compileToHTMLWithStrataAuto(json, target, tokens?) Compile with Strata design tokens inlined
parseJsonToTargetFormat(json, target) Parse and validate a template JSON
injectStrataBundle(html, tokens) Inject Strata runtime CSS into compiled HTML
Example — Compile on the server (Next.js API route)
// app/api/compile/route.ts
import { compileToHTML } from '@plexobuilder/sdk';
import type { TemplateJSON } from '@plexobuilder/sdk';

export async function POST(req: Request) {
  const { template }: { template: TemplateJSON } = await req.json();
  const html = compileToHTML(template, 'email');
  return Response.json({ html });
}

Design Token Utilities

import {
  createTokenMapping,
  applyTokensToElement,
  getTokensByCategory,
  generateTokenCSS,
} from '@plexobuilder/sdk';

TypeScript Types

import type {
  TemplateJSON,
  RowJSON,
  ColumnJSON,
  ElementJSON,
  ElementType,
  PlexoBuilderProps,
  PlexoBuilderRef,
  PlexoTargetType,
  StrataToken,
  StrataTokenSet,
  CompileTarget,
} from '@plexobuilder/sdk';

Framework Notes

Vite

Works out of the box — no extra config needed.

Next.js (Pages Router)

Same dynamic import pattern applies:

import dynamic from 'next/dynamic';

const PlexoBuilder = dynamic(
  () => import('@plexobuilder/sdk').then((m) => ({ default: m.PlexoBuilder })),
  { ssr: false }
);
Remix / React Router v7

Use the lazy approach or a client-only guard:

import { lazy, Suspense } from 'react';

const PlexoBuilder = lazy(() =>
  import('@plexobuilder/sdk').then((m) => ({ default: m.PlexoBuilder }))
);

// In your component:
<Suspense fallback={<p>Loading…</p>}>
  <PlexoBuilder ... />
</Suspense>

Note: In Remix, place this inside a clientLoader or use <ClientOnly> wrapper to ensure it's never executed on the server.


Changelog

1.0.1
  • Fixed: Removed Rolldown CJS interop shim (require()) from ESM output — resolves compatibility issues with Turbopack (Next.js 15+/16+) and strict ESM environments
  • All React sub-paths (react/jsx-runtime, etc.) are now properly externalized
1.0.0
  • Initial release

License

MIT Plexo HQ

Keywords