Skip to content
Changelog

What shipped, and when

Every release is listed here with the packages it changed — all packages share one version number.

OctNov
20 releases in 24 days
  • Fix@templatical/editor@templatical/types

    Add PreviewSurface ("preview" | "test-email") and the required PreviewResolveContext.surface, so a resolver knows whether the editor's preview mode or the test-email dialog is calling. Read surface, not the presence of recipient, to tell them apart: the dialog leaves recipient out while its recipient field is empty. A resolver the editor calls needs no change; code that builds a PreviewResolveContext itself, such as a test that calls its own resolver, adds surface: "preview" or surface: "test-email".

Read the full notes for 0.59.1
  • Feature@templatical/editor@templatical/types

    Add PreviewResolveTrigger ("open" | "refresh" | "recipient" | "locale"), the required PreviewResolveContext.trigger, and the refreshPreview() instance method. A Refresh preview button is available in preview mode and the test-email dialog when resolvePreview is configured. A resolver the editor calls needs no change; code that builds a PreviewResolveContext itself, such as a test that calls its own resolver, adds trigger: "open". A failed re-resolve now shows the unresolved template instead of stale resolved content, opening the test-email dialog makes one resolver call with its seeded recipient, and a test-email recipient change always waits 500 ms, including before the first answer lands.

  • Feature@templatical/editor

    Add header.actions for host-owned controls in the editor header, with darkModeToggle, previewToggle and viewportToggle opt-outs. The editor reports compact and resolved-theme state on the host element.

  • Fix@templatical/core@templatical/editor

    Fix undo history after replacing an editor document. Undo after loading another template could write the previous template's content into it on save, and undo after setContent() could restore part of the old document. Loading a template, creating one with new content, or calling the public setContent() now clears undo and redo; creating a template from the current content keeps history. In collaborative editing, reloading the same template no longer sends the loaded document as an edit or drops presence and locks, and creating a template from the current content keeps undo and redo available in the new template.

  • Fix@templatical/import-beefree

    Read the Menu, Table and Video modules in the shape BeeFree exports (IPluginModuleMenu, IPluginModuleTable and IPluginModuleVideo in BeeFree's bee.ts). The importer read keys BeeFree never writes, so a real menu or table imported with no content and a video lost its thumbnail and width.

Read the full notes for 0.59.0
  • Feature@templatical/renderer

    Breaking changes:

  • Fix@templatical/template-tools

    custom-block render and custom-block validate pass their own liquidjs to renderToMjml, which no longer imports it. CLI output is unchanged.

  • Fix@templatical/import-beefree

    Skip a BeeFree spacer whose height is an explicit 0px, reported as skipped, instead of importing it as a 24px spacer. A spacer with a missing, unreadable or negative height now imports at BeeFree's 60px default rather than 24px. In an Icons module, an explicit 0px itemsSpacing no longer falls back to the legacy itemSpacing key.

  • Fix@templatical/import-beefree

    Preserve social icon scheme prefixes (mailto:, tel:, sms:) and keep custom social icons as images with their original file and link during Beefree imports.

Read the full notes for 0.58.0
  • Fix@templatical/types

    A locale operation (updateBlockLocale, updateSettingsLocale) writes only to the block's or settings' own l10n layer for that language. A layer inherited through the object's prototype is no longer reused and changed in place; the edit gets a fresh own layer instead.

Read the full notes for 0.57.2
  • Fix@templatical/import-beefree@templatical/import-chamaileon@templatical/import-easy-email-pro@templatical/import-html@templatical/import-mjml@templatical/import-topol@templatical/types

    cloneBlock serializes a block tree once and remints IDs throughout the copy.

  • Fix@templatical/ai-kit

    The shipped eval set's domain-mismatch case checks link text with >[^<>]*(?:www\.|://) instead of >(?:[^<]*)(?:www\.|://). It matches the same text, and checking a turn whose output holds a long run of > no longer takes quadratic time.

  • Fix@templatical/import-beefree

    BeeFree multi-column rows now convert outer column edges and matching top or bottom sides into section borders; painted column backgrounds, inner borders, and overlapping row borders still warn.

  • Fix@templatical/editor@templatical/renderer@templatical/template-tools@templatical/types

    Custom-block Liquid renders now have budgets: createCustomBlockLiquid sets memoryLimit to CUSTOM_BLOCK_LIQUID_MEMORY_LIMIT (1e7) and renderLimit to CUSTOM_BLOCK_LIQUID_RENDER_LIMIT (2000 ms), both exported from @templatical/types, so a template such as a loop over (1..1000000000) fails with a Liquid limit error in the editor, renderToMjml and custom-block validate instead of exhausting memory. Data-source preview recipes render with the same limits.

  • Fix@templatical/import-beefree

    Preserve explicit zero and shorthand padding on BeeFree buttons, with longhands taking precedence. Let an entirely bold label override any button style weight; import missing or unreadable weights as regular otherwise, and note lost partial bold formatting.

Read the full notes for 0.57.1
  • Feature@templatical/core@templatical/types

    Breaking changes:

  • Feature@templatical/editor@templatical/media-library

    Add Danish editor and media library translations and localized recipient-facing content defaults.

  • Feature@templatical/ai-kit@templatical/core@templatical/template-tools@templatical/types

    Breaking changes:

  • Feature@templatical/ai-kit

    Breaking changes:

  • Fix@templatical/renderer@templatical/types

    resolveLocale copies each block once, so resolving a deeply nested template takes time in proportion to its size. Masking merge tags with a custom syntax runs each regex once per match instead of again on every tag.

  • Fix@templatical/import-easy-email-pro@templatical/quality

    link.localhost-or-staging matches links.nonProductionHosts globs in linear time, so a very long URL host no longer stalls the linter, and compatibility rules group CSS declarations and clients without copying arrays. The Easy Email Pro importer decodes HTML entities by looking at most six characters ahead of each &.

  • Fix@templatical/import-beefree@templatical/import-chamaileon@templatical/import-topol@templatical/import-unlayer@templatical/renderer@templatical/template-tools

    The Unlayer, BeeFree and Topol importers check for a repeated warning in constant time, so a design with thousands of languages no longer slows the import quadratically. The Chamaileon importer looks up variable references in a table built once per document. The renderer escapes control characters in a block's type and id before it logs the missing-renderer warning. templatical live answers 400 to a request target it can't parse, where it used to exit.

  • Fix@templatical/core

    Localized operations preserve other language layers when an existing block moves into a newly added wrapper. Mixed section and wrapper parent objects resolve to the section column, matching the operation engine.

  • Fix@templatical/editor@templatical/import-beefree@templatical/renderer@templatical/types

    The canvas draws a button at the same height as the export (#1144). The renderer now writes line-height="120%" explicitly; compiled HTML is unchanged.

  • Fix@templatical/ai-kit

    translateFields sends the model short field aliases

  • Fix@templatical/editor

    Fix the header switching to its compact layout while the save status shows. "Unsaved" and "Saved" appear on every edit and save; in an editor just wide enough for the full header, their words compacted the whole header until the status cleared, about 5 seconds with templates.autoSave. The badge keeps a fixed slot (its icon) in the header's fit measurement and shows its words only where the full header has room for them. Without room it shows the icon alone, a different one per state (dot, check, alert), and keeps the words as its tooltip and for screen readers. In the compact header the badge is always the icon alone.

  • Fix@templatical/ai-kit

    An editing session checks locale layers in time proportional to the template size. Each locale is resolved only for the blocks that carry its layer, so a template with thousands of locales no longer makes every batch resolve the whole template once per locale.

  • Fix@templatical/core@templatical/editor

    Preview surfaces are read-only: the canvas in preview mode and the test-email and saved-block previews no longer start inline edits or write table cells, so resolved preview content can't overwrite the template.

Read the full notes for 0.57.0
2 days
  • Fix@templatical/import-topol

    convertTopolTemplate() accepts designs whose sections sit under mj-body and converts them like mj-container designs, including the container's background-color. When a design has neither, the empty-design warning names both tags.

Read the full notes for 0.56.1
  • Feature@templatical/ai-kit@templatical/editor@templatical/import-beefree@templatical/import-chamaileon@templatical/import-easy-email-pro@templatical/import-html@templatical/import-mjml@templatical/import-stripo@templatical/import-topol@templatical/import-unlayer@templatical/quality@templatical/renderer@templatical/template-tools@templatical/types

    Breaking changes:

  • Feature@templatical/ai-kit@templatical/editor@templatical/template-tools@templatical/types

    displayConditions.onRequest lets a host open its own condition builder. The callback receives a copy of the block and, when one is set, the current condition including opaque data. null cancels. conditions is optional. With onRequest set, conditions and allowCustom are ignored. DisplayCondition.data round-trips through the template.

  • Feature@templatical/editor@templatical/types

    Spread syntax presets with matching value and logic patterns use the built-in linear merge-tag scanner across localization and editor parsing. Different pattern sources or flags other than g and y keep custom regex matching. @templatical/types exports builtInPresetOf(syntax), which returns the built-in preset name whose patterns a syntax uses.

  • Feature@templatical/ai-kit@templatical/editor@templatical/renderer@templatical/template-tools@templatical/types

    A section wrapper or a layout wrapper can span the recipient's window. Set fullWidth: true on section.wrapper or on a layout wrapper block and the renderer emits MJML's full-width="full-width" on that mj-wrapper: the band's background color and background image run edge to edge, and the section or the wrapper's children stay at settings.width. Omit fullWidth, or set it false, and the band stays the email width, exactly as before. A corner radius is not rendered while full width is on; the stored radius remains and comes back when full width is off.

  • Feature@templatical/import-beefree@templatical/import-chamaileon@templatical/import-easy-email-pro@templatical/import-html@templatical/import-mjml@templatical/import-stripo@templatical/import-topol@templatical/import-unlayer

    Breaking changes:

Read the full notes for 0.56.0
  • Feature@templatical/import-beefree

    A real-design audit of the BeeFree importer found it converts every design but loses fidelity and, in one case, breaks Twig at send time. This release closes the gaps it found.

  • Feature@templatical/ai-kit@templatical/editor@templatical/renderer@templatical/template-tools@templatical/types

    Two optional block fields. Leaving either out renders exactly as before.

  • Feature@templatical/ai-kit@templatical/editor@templatical/import-html@templatical/import-mjml@templatical/import-stripo@templatical/quality@templatical/types

    Built-in merge-tag scanning, merge-tag span handling, and CSS rule parsing complete in linear time on malformed template input. Pixel value parsers reject long invalid whitespace suffixes without super-linear backtracking.

  • Feature@templatical/ai-kit@templatical/editor@templatical/import-beefree@templatical/import-chamaileon@templatical/import-mjml@templatical/import-stripo@templatical/import-topol@templatical/import-unlayer@templatical/renderer@templatical/template-tools@templatical/types

    SocialPlatform includes xing. Social icon blocks can use a XING icon, drawn from the same glyph as the other platforms, in the editor and in every rendered style and tone.

  • Fix@templatical/quality

    Lint auto-fixes now rewrite single-quoted attributes without adding attributes. Double-quoted values are copied as written, including entities, and a rewritten anchor tag is lowercase. Link and alignment fixes skip markup inside comments, link fixes use the same attribute decoding and HTML whitespace rules as detection, and alignment fixes split declarations on decoded CSS characters, so &#59; separates declarations, and keep the character references in the declarations they keep.

  • Fix@templatical/import-beefree

    A 7/12 or 5/12 BeeFree column row imports as an even two-column section. When a snapped column is narrower than its grid share, the shortfall comes back from the padding that faces the next column, so a one-line footer stays one line.

  • Fix@templatical/import-beefree@templatical/import-stripo

    Two importer corrections.

Read the full notes for 0.55.0
  • Fix@templatical/renderer

    Template values in MJML attributes are escaped before rendering. Body background colours containing markup use a transparent fallback so the compiled HTML does not carry that markup. CSS-valued attributes (background colours, border radius, background size, position and repeat) also drop ;, {, } and line breaks, so a value stays one CSS declaration.

  • Fix@templatical/editor@templatical/renderer@templatical/types

    Title blocks now unwrap paragraphs with quoted attributes correctly in the editor and rendered email. The editor sanitizes title HTML after unwrapping to close a script-injection path in the canvas. findOpenTagEnd now treats a quote inside an unquoted attribute value as an ordinary character, as HTML does.

  • Fix@templatical/editor

    In preview mode the canvas hides lint issue badges, like the rest of the block chrome.

Read the full notes for 0.54.2
  • Fix@templatical/editor

    The text formatting toolbar stays behind the Insert Link dialog after a merge-tag or logic-tag picker has been opened and closed.

Read the full notes for 0.54.1
  • Feature@templatical/import-beefree

    convertBeeFreeTemplate() imports images at the width BeeFree shows them, keeps spacing dividers invisible, and converts the Icons module, addons and empty modules.

  • Fix@templatical/import-html@templatical/import-unlayer

    The Unlayer and HTML importers import a divider as the line it draws, so one that draws nothing no longer becomes a black line.

  • Fix@templatical/renderer

    Compiling renderToMjml() output with mjml no longer throws TypeError: Cannot read properties of undefined (reading 'indexOf') when a paragraph or title holds a character reference in a style attribute.

Read the full notes for 0.54.0
  • Feature@templatical/import-beefree@templatical/import-chamaileon@templatical/import-easy-email-pro@templatical/import-html@templatical/import-mjml@templatical/import-stripo@templatical/import-topol@templatical/import-unlayer

    Importers keep the source's languages

  • Feature@templatical/editor

    Language versions and translation in the editor

  • Feature@templatical/types

    Language versions and translation in the template model

  • Feature@templatical/core

    Language versions in editing, collaboration and AI edits

  • Feature@templatical/template-tools

    Language versions in the CLI, with strings export and strings import

  • Feature@templatical/quality

    Localization checks for language versions

  • Feature@templatical/renderer

    Rendering a language version

  • Feature@templatical/ai-kit

    Translation over your own backend

Read the full notes for 0.53.0
  • Fix@templatical/editor@templatical/renderer@templatical/template-tools@templatical/types

    Custom-block {% cycle %} output is HTML-escaped once with liquidjs 10.30.1

  • Fix@templatical/editor

    The block action bar and comment-count pill stay inside the canvas pane

Read the full notes for 0.52.1
2 days
  • Feature@templatical/editor@templatical/quality@templatical/types

    The editor sanitizes live rich-text HTML, custom-block canvas HTML, and inline SVG icons with DOMPurify. Custom-block export HTML is unchanged. URL attribute checks use a shared scheme policy from @templatical/types; the link dialog and @templatical/quality use the same scheme parsing. Unsupported DOM environments display escaped text.

  • Feature@templatical/editor@templatical/renderer@templatical/template-tools@templatical/types

    Custom block fields are HTML-escaped in templates

Read the full notes for 0.52.0
5 days
  • Fix@templatical/editor

    The AI button renders with the rest of the header

  • Fix@templatical/editor

    The AI header button matches the other header buttons

Read the full notes for 0.51.1
  • Feature@templatical/editor@templatical/quality@templatical/template-tools

    Add default-on compatibility lint for authored pass-through HTML and CSS, using a pinned caniemail snapshot, plus an explicit compiled-HTML Gmail size check. Agents and headless callers receive a concrete suggestion and reference on every issue, with affected clients and an excerpt when available. The editor shows suggestions and source links, and offers an on-demand Check size action when its render provider can compile without saving. templatical validate --html reports htmlBytes and a clipping warning.

  • Feature@templatical/editor

    @templatical/quality is an optional dependency of the editor and installs by default. Leaving it out is supported: the editor works without it and hides the Issues tab.

  • Feature@templatical/quality

    lintTemplate now runs the deliverability category by default. Agents can use lintDeliverability, DELIVERABILITY_RULES, localized messages, DEFAULT_SHORTENER_HOSTS, and DEFAULT_DELIVERABILITY_THRESHOLDS directly. The category flags deliverability.link-text-domain-mismatch (warning), deliverability.url-shortener (warning), deliverability.ip-address-url (warning), and deliverability.low-text (info). Each rule reports a JSON-detectable content cue; none auto-fixes or scores a template.

  • Feature@templatical/editor@templatical/types

    Custom merge-tag syntaxes get autocomplete through opener and closer

  • Feature@templatical/editor

    init({ ai }): bring your own AI backend. Each feature is labelled as AI, in every editor locale:

  • Feature@templatical/types

    AI as a bring-your-own contract (BYO contract):

  • Feature@templatical/ai-kit

    New package @templatical/ai-kit, MIT and with no LLM SDK dependency: the editor's AI over your own backend.

  • Feature@templatical/core

    The collaboration controller applies an AI turn's operations as this session's batches, marked origin: 'ai', one undo step per turn (applyOperations). invertOperations now comes from @templatical/types; core re-exports it.

Read the full notes for 0.50.0
4 days
  • Feature@templatical/template-tools

    edit speaks operations vocabulary v2

  • Feature@templatical/types

    Operations vocabulary v2, the engine that applies it, and the collaboration contract

  • Feature@templatical/editor

    Real-time collaboration in the editor over your backend, and agents' edits named

  • Feature@templatical/core

    Real-time collaboration over a provider

Read the full notes for 0.49.0
4 days
  • Feature@templatical/editor@templatical/import-beefree@templatical/import-unlayer@templatical/types

    Size an image by its height with the aspect ratio locked. When the image file's size is known, the image settings show a link toggle on the Height row, on by default: typing a height sets the width from the file's ratio, and a height that would make the image wider than its column sets it to Full width, with a note of the height it lands at. Under the lock the stored height stays unset, because a stored height squashes an image on any phone narrower than its width (MJML shrinks the width and keeps the height).

  • Feature@templatical/editor@templatical/import-easy-email-pro@templatical/import-mjml@templatical/quality@templatical/renderer@templatical/template-tools@templatical/types

    Sections can render as heroes

  • Feature@templatical/editor@templatical/renderer@templatical/types

    Titles stay bold while you edit them. A title showed at weight 700 on the canvas and in the email, but its edit surface showed it at 400, so the text turned lighter, and could rewrap, the moment editing started. The canvas, the edit surface and the exported heading now all use 700, which @templatical/types exports as TITLE_FONT_WEIGHT. The renderer writes it onto the heading as font-weight:700, so emails look as before in clients that already bold headings, and a page that resets heading styles (Tailwind's preflight, for one) no longer shows the email's titles at regular weight. With shadowDom: false on such a page, the canvas title was regular too; it is now bold.

  • Feature@templatical/import-mjml@templatical/renderer

    An image set narrower than its column keeps its width on phones (#861). The renderer set fluid-on-mobile on every mj-image through <mj-attributes>, so a 120px logo grew to the whole column on a phone while the editor's mobile preview showed it at 120px, and an image with a set height was stretched out of shape (120×40 became 355×40 on a 375px phone). The attribute is now set per image, only on one that fills its column on desktop: width: "full", or a pixel width at or above the room MJML gives it, which is the column less the side padding and border of the wrapper band, the section and the image. Images wider than the phone still shrink to fit, and video thumbnails follow the same rule.

  • Fix@templatical/media-library

    The standalone media library (init() and MediaLibraryModal) now renders as designed on host pages without a CSS reset. A reset such as Tailwind's preflight hid all of this. Inside the editor, the media library already rendered correctly.

  • Fix@templatical/editor@templatical/import-mjml@templatical/renderer

    Fractional padding and borders no longer shift which images fill their column on phones

  • Fix@templatical/import-beefree@templatical/import-chamaileon@templatical/import-easy-email-pro@templatical/import-html@templatical/import-mjml@templatical/import-stripo@templatical/import-topol@templatical/import-unlayer

    Imported images come in at the width the source email shows them, and every importer decides width: "full" by one rule. A missing width, 100%, or a px width that reaches the image's room (its column less its own side padding, and border where the importer reads one) is "full"; a narrower px width stays px; a percentage under 100% becomes px of the room and is reported approximated, since a px width keeps its size on a phone.

Read the full notes for 0.48.0

Showing the 20 most recent releases.

Every release

Looking for an older version?

The docs changelog carries the full history back to the first release, with the complete notes for every entry.