Parent: #5
Depends on: #40
Goal
Add the preview-data editor and the rendered preview pane to @singleton-sd/post-kit-editor. An admin user must be able to edit the sample values in preview.json and immediately see the email rendered with those values, using the same rendering path as @singleton-sd/post-kit-compiler so what they see matches what will be published.
Scope
Preview data editor
src/preview/PreviewDataEditor.tsx — edits TemplatePreviewData (Record<string, string>) as a key/value list:
- One row per declared variable, pre-populated from the working
previewData.
- Rows for variables declared in
metadata.variables but missing from previewData render with an empty value rather than being hidden.
- Rows present in
previewData but not declared in metadata.variables are shown and marked as extra, so the user can remove them.
- Add/remove row affordances; edits update the working
TemplateSourceFiles state.
- Values are strings only, matching
TemplatePreviewData.
Rendered preview
src/preview/PreviewPane.tsx — renders the current EmailBuilder document with the current preview data substituted.
- Reuse
@singleton-sd/post-kit-compiler rather than reimplementing rendering or {{variable}} substitution. Add it as a runtime dependency.
- Preferred approach: call the compiler's existing compile/validate entry point with the in-memory
TemplateSourceFiles and render the resulting HTML. If the compiler's public surface is filesystem-bound in a way that cannot run in a browser, use the object-based entry point (compile()), and document any browser-compatibility caveat in the package README.
- Display the result in a sandboxed
<iframe> (sandbox attribute set, scripts disabled) so template markup cannot affect the host admin application.
- Debounce re-rendering on rapid edits so typing does not re-render on every keystroke.
Preview failure handling
- When rendering fails (malformed document, template syntax error), the preview pane shows the compiler's error message in place of the preview and leaves the rest of the editor usable. The editor must not crash or unmount the canvas.
Preview surface
Expose the rendered HTML to the consumer through a read-only callback so an application can offer its own "open preview in new tab" behaviour:
onPreviewRendered?: (html: string) => void;
Add this as an optional prop on EmailTemplateEditorProps.
Constraints
- Do not reimplement HTML rendering or variable substitution — delegate to
@singleton-sd/post-kit-compiler.
- Pin the compiler as a workspace dependency (
workspace:*), consistent with the other packages.
- Preview must render in a sandboxed iframe with scripting disabled.
- Do not implement validation messaging, save, or send-test — separate issues.
- Preview data must never contain real personal data; the README section for this feature should state that sample values are committed to the consumer's repository and must stay synthetic.
- No network calls and no filesystem access from the editor package.
- Do not block the canvas or metadata editing while a preview render is in flight.
Acceptance criteria
Agent implementation notes
Read packages/post-kit-compiler/src/compiler.ts and its README first to choose the right entry point and understand what errors it throws. Read the working-state model from #40 and extend it rather than introducing separate state. Branch: feat/<issue-number>-editor-preview.
Parent: #5
Depends on: #40
Goal
Add the preview-data editor and the rendered preview pane to
@singleton-sd/post-kit-editor. An admin user must be able to edit the sample values inpreview.jsonand immediately see the email rendered with those values, using the same rendering path as@singleton-sd/post-kit-compilerso what they see matches what will be published.Scope
Preview data editor
src/preview/PreviewDataEditor.tsx— editsTemplatePreviewData(Record<string, string>) as a key/value list:previewData.metadata.variablesbut missing frompreviewDatarender with an empty value rather than being hidden.previewDatabut not declared inmetadata.variablesare shown and marked as extra, so the user can remove them.TemplateSourceFilesstate.TemplatePreviewData.Rendered preview
src/preview/PreviewPane.tsx— renders the current EmailBuilder document with the current preview data substituted.@singleton-sd/post-kit-compilerrather than reimplementing rendering or{{variable}}substitution. Add it as a runtime dependency.TemplateSourceFilesand render the resulting HTML. If the compiler's public surface is filesystem-bound in a way that cannot run in a browser, use the object-based entry point (compile()), and document any browser-compatibility caveat in the package README.<iframe>(sandboxattribute set, scripts disabled) so template markup cannot affect the host admin application.Preview failure handling
Preview surface
Expose the rendered HTML to the consumer through a read-only callback so an application can offer its own "open preview in new tab" behaviour:
Add this as an optional prop on
EmailTemplateEditorProps.Constraints
@singleton-sd/post-kit-compiler.workspace:*), consistent with the other packages.Acceptance criteria
preview.jsonvalues are editable and update the workingTemplateSourceFilesstate.@singleton-sd/post-kit-compiler.onPreviewRenderedis called with the rendered HTML when a render succeeds.pnpm -r --if-present run testpasses.Agent implementation notes
Read
packages/post-kit-compiler/src/compiler.tsand its README first to choose the right entry point and understand what errors it throws. Read the working-state model from #40 and extend it rather than introducing separate state. Branch:feat/<issue-number>-editor-preview.