Skip to content

Repository files navigation

✉ Preact Editor Email Template

A visual email authoring studio with reusable blocks, drag-and-drop composition, history, safe previews, and production-oriented exports.

Preact TypeScript Tailwind CSS SortableJS Vite

Deploy with Vercel


✨ Highlights

  • Reusable Blocks: Builds messages from heading, text, button, image, divider, and spacing blocks.
  • Direct Composition: Uses SortableJS for drag-and-drop ordering with stable selection, duplication, and deletion.
  • Contextual Inspector: Edits subject, preheader, width, colors, alignment, padding, URLs, and block content.
  • Undo History: Preserves meaningful template snapshots for undo and redo without polluting history on selection.
  • Durable Drafts: Debounces IndexedDB autosave and restores the complete sample from the header.
  • Responsive Preview: Switches between desktop and mobile widths inside an isolated iframe.
  • Safer Rendering: Sanitizes preview markup and escapes editable text during export.
  • Production-Oriented Export: Downloads JSON or table-based inline-style HTML and copies HTML to the clipboard.
  • Adaptive Studio: Keeps the canvas primary while turning the inspector into a focused mobile editing surface.

🧱 Project Structure

public/
|-- favicon.svg
|-- sample-email-banner.svg
`-- sample-email-template.json
src/
|-- app.tsx
|-- index.css
|-- main.tsx
|-- components/
|   |-- block-inspector.tsx
|   |-- block-library.tsx
|   `-- email-canvas.tsx
|-- domain/
|   `-- template.ts
`-- services/
    `-- template-store.ts

🛠️ Tech Stack

  • Preact 10, TypeScript 6, Vite 8, and Tailwind CSS 4
  • SortableJS, DOMPurify, Zod, nanoid, Preact Signals, and Lucide icons
  • IndexedDB persistence through idb-keyval

📦 Included Demo Data

public/sample-email-template.json provides a complete synthetic product-update email with subject, preheader, palette, width, and editable content blocks. public/sample-email-banner.svg supplies local artwork so image and export workflows can be tested without searching for an asset.

🚀 Local Development

npm install
npm run dev

Open http://localhost:5173.

🔌 Extension Notes & Nuances

  • Export escapes editable text and produces a conservative table layout with inline styles.
  • Preview content is sanitized before being assigned to iframe srcDoc.
  • DOM sanitization does not replace server-side template validation, URL policy, and content security controls.
  • Proxy or upload remote images through an approved asset service rather than trusting arbitrary production URLs.
  • Add provider-specific rendering tests, CSS inlining, merge-tag validation, unsubscribe requirements, and plain-text alternatives before delivery.
  • The generated HTML is a useful baseline, not a guarantee of identical rendering across every email client.
  • Replace src/services/template-store.ts with a versioned draft API when collaborative or server-backed editing is required.
  • On smaller screens the canvas remains primary and the inspector becomes a slide-in editing surface.

🧪 Build & Checks

npm run format:check
npm run build
npm run preview
npm audit --omit=dev

🌐 Vercel Deployment

{
  "$schema": "https://openapi.vercel.sh/vercel.json",
  "framework": "vite",
  "buildCommand": "npm run build",
  "outputDirectory": "dist",
  "rewrites": [
    {
      "source": "/(.*)",
      "destination": "/index.html"
    }
  ]
}

📄 License

MIT License. See LICENSE.

Releases

Packages

Contributors

Languages