Skip to content

EmailBuilder.js canvas and lossless template source load/serialize #40

Description

@patoperpetua

Parent: #5
Depends on: #36

Goal

Integrate the EmailBuilder.js visual canvas into @singleton-sd/post-kit-editor and implement lossless load/serialize of the three Git-backed template source files (template.json, metadata.json, preview.json). After this issue, a consumer can hand the editor a template directory's contents, edit the document visually, and get back an equivalent set of files with no information loss.

Scope

Dependency

Add @usewaypoint/email-builder at version 0.0.9 — the exact version already pinned by packages/post-kit-compiler — as a runtime dependency. Both packages must render/parse the same document format.

Canvas component

  • src/canvas/EmailBuilderCanvas.tsx — wraps the EmailBuilder.js editor surface and exposes a controlled-component interface:
interface EmailBuilderCanvasProps {
  document: EmailBuilderDocument;
  onChange: (document: EmailBuilderDocument) => void;
  readOnly?: boolean;
}
  • The canvas owns no persistence and no network access. It receives a document, emits changes.
  • Mount it inside EmailTemplateEditor so the editor renders a working visual canvas.

Document typing

  • src/types.ts: replace the templateJson: unknown placeholder from Scaffold @singleton-sd/post-kit-editor package #36 with an EmailBuilderDocument type.
  • Derive the type from @usewaypoint/email-builder where it exports one. If it does not, define a minimal structural type ({ document: Record<string, unknown> } shape matching what post-kit-compiler accepts) and document why.
  • The type must be compatible with what post-kit-compiler's compile() accepts as templateJson, so the same object can be compiled without conversion.

Load / serialize

// src/serialization.ts
export function loadTemplateSource(input: {
  templateJson: unknown;
  metadata: unknown;
  previewData: unknown;
}): TemplateSourceFiles;

export function serializeTemplateSource(files: TemplateSourceFiles): {
  templateJson: string;
  metadataJson: string;
  previewJson: string;
};
  • loadTemplateSource parses/validates the three inputs and throws a descriptive error naming the offending file when a document is malformed or schemaVersion is unknown.
  • serializeTemplateSource produces the exact file contents to be written back to the consumer repository: stable key ordering, 2-space indentation, trailing newline — so an unmodified round trip yields a byte-identical (or at minimum semantically identical and diff-stable) result.
  • Unknown/forward-compatible fields present in the input must survive the round trip. Never drop keys the editor does not understand.

Round-trip test fixtures

  • Add fixture template directories under src/__fixtures__/ covering: a minimal document, a document with nested blocks, and a document containing an unknown block property.
  • Test: loadTemplateSourceserializeTemplateSource preserves all data for every fixture.

Editor wiring

  • EmailTemplateEditor holds the working TemplateSourceFiles in local state, seeded from the template prop.
  • Canvas edits update templateJson in that state.
  • Expose the current working state to the onSave callback signature already declared in Scaffold @singleton-sd/post-kit-editor package #36 (actual save UI arrives in the save/send-test issue).

Constraints

  • EmailBuilder.js JSON is the editable source of truth. Never reconstruct the builder document from compiled HTML.
  • Pin @usewaypoint/email-builder to the same version as packages/post-kit-compiler (0.0.9); a version drift between compile and edit is a correctness bug.
  • Do not implement metadata editing, subject editing, variable catalogue, preview rendering, or validation UI here — those are separate issues.
  • Do not write files, call fs, or make network requests from this package.
  • Do not store templates anywhere outside the in-memory component state and the consumer's callbacks.
  • Keep the canvas framework-shell agnostic: no router, no global store.

Acceptance criteria

  • @usewaypoint/email-builder@0.0.9 is a runtime dependency of packages/post-kit-editor.
  • EmailTemplateEditor renders a working EmailBuilder.js canvas seeded from the template prop.
  • Canvas edits update the in-memory templateJson and are observable through the component's working state.
  • loadTemplateSource() parses template.json / metadata.json / preview.json inputs and throws a descriptive, file-named error on malformed input.
  • serializeTemplateSource() returns deterministic, diff-stable string contents for all three files.
  • Round-trip tests prove no information loss for all fixtures, including unknown/unrecognised fields.
  • EmailBuilderDocument typing is accepted by post-kit-compiler's compile() without conversion.
  • The package performs no filesystem or network I/O.
  • pnpm -r --if-present run test passes.

Agent implementation notes

Read packages/post-kit-compiler/src/template-source.ts and compiler.ts first to see exactly how template.json is parsed and rendered today — the editor must produce documents that package accepts. Read packages/post-kit-types/src/template.ts for TemplateSourceMetadata and TemplatePreviewData. Read the scaffold delivered by #36 for the package's test and styling conventions. Branch: feat/<issue-number>-editor-canvas-serialization.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions