Releases: tedydonel/Heisenberg
Release list
v0.0.4: CSP nonce support
What's Changed
Added
- CSP nonce support for inline styles and scripts. Heisenberg now reads the CSP nonce from
Vite::useCspNonce()(when available) and addsnonce="..."to every inline<style>,<script>, and<link rel="stylesheet">tag. This allows Heisenberg to work correctly in apps that enforce nonce-based Content Security Policy without requiring'unsafe-inline'. - README now includes CSP nonce setup instructions for Laravel apps using Vite.
- README now includes a complete email system quick-start guide with code examples for registering variables, sending via the mailable, rendering directly, and using the admin batch ZIP export.
Changed
- All Blade templates updated to emit
nonce="{{ heisenberg_csp_nonce() }}"on inline<style>,<script>, and<link rel="stylesheet">tags.
Upgrade note: After installing v0.0.4, run composer dump-autoload in your host app. If you use CSP nonces, add Vite::useCspNonce() to your service provider's boot() method.
Heisenberg v0.0.3 — Host-app compatibility fix
Heisenberg v0.0.3 — Host-app compatibility fix
This patch fixes two issues that broke the editor when used inside a host Laravel application (e.g., LangeSky):
Component namespace collision resolved — Heisenberg's Blade components (x-ui.tabs, x-live.canvas, etc.) were registered without a namespace, so a host app's identically-named components would shadow them. This caused the editor to render without any CSS or JavaScript. All components are now namespaced under heisenberg:: (e.g., x-heisenberg::ui.tabs).
Asset URLs now use named routes — Hard-coded paths like /heisenberg-assets/editor.css broke when the app was deployed behind a URL prefix. These now use route() helpers.
Upgrade: Update your Composer constraint to ^0.0.3 and run composer update heisenberg/heisenberg. Clear cached views and config (php artisan view:clear && php artisan config:clear).
Heisenberg v0.0.2 - email personalization, builder phases, URL-filter XSS fix
What's new in 0.0.2
This release is dominated by the email subsystem and two fixes that touch every surface.
✉️ Email personalization (host variables + admin batch export)
- Host-defined email variables: register any dotted key with a typed formatter contract and a safe non-secret sample. Six built-in types ship (
text,url,email,number,boolean,date). - Strict context-aware interpolation before rich-text sanitization / URL filtering, with value-free aggregated errors for unknown tokens, missing values, formatter failures, and target mismatches.
- Per-recipient
EmailRendererandHeisenbergMailableseams across MIME subject, HTML, plain text, size accounting, and CID embeds — while preserving legacy token-free calls. - Sample-only public/editor preview, size, and single HTML/EML export. Runtime maps are never read from author-facing GET query strings, bodies, or headers.
- Email-only authoring picker (subject, rich text, compatible text settings, URL settings) inserting literal
{{ dotted.key }}tokens via text nodes /setRangeText, neverinnerHTML. - Admin-only, all-or-nothing batch ZIP export (
email.generate, defaultadmin) of exactly N recipients × requested locales as HTML or EML. Recipients are explicit value maps; Heisenberg still does not own SMTP, subscribers, campaigns, or recipient discovery. - Usage docs (
docs/email-personalization.md) and compile-checked host examples (examples/EmailVariables/).
🧱 Builder / editor
- Single-row content model — one post carries every configured locale instead of separate translation rows.
- Native threaded comments, moderation, a public thread API, and shared-surface route wiring.
- SEO persistence, scoring, sitemap, hreflang, and opt-in public post routes.
- User-saved block patterns, quick-inserter browse-all, number-stepper UI, gradient values, nested/per-state fonts, and expanded column/inspector controls.
- Responsive featured-image rendering in the public preview.
- Deep published-config merging plus
heisenberg:config-diff.
🔒 Security
javascript:URL-filter XSS bypass fix inBlockRenderer::safeUrl()/NullMediaResolver::safeUrl(): control characters inside the scheme are stripped before parsing (e.g.java\tscript:…), with regression coverage for all obfuscated variants.target="_blank"now emitsrel="noopener noreferrer".ThemeRepository::save()writes withLOCK_EX.
🐛 Notable fixes
- Autosave no longer reverts queued status/slug/date; schedule/publish timestamps no longer drift with viewer timezone.
- Email rendering matches authored content, including translated block attributes.
- Discussion settings target the real toggle input; disabled commenting keeps a frozen thread while hosts can choose how to display it.
- Duplicated blocks get fresh IDs; navigator selection, child toolbar targeting, column flex-basis, heading specificity, icon theming, and font-family quoting fixed.
- AI assistant icon lookup, translation preservation, prompt-size limits, composer height, SEO scoring and sitemap locale assumptions.
Built against
- PHP 8.2 / 8.3 / 8.4 × Laravel 11 / 12 / 13, prefer-lowest + prefer-stable — all green on
14c9037f. - Full suite: 1539 tests / 6121 assertions (email wave alone: 8
feat(email)commits).
Install
composer require heisenberg/heisenberg
php artisan migrate
php artisan storage:linkOpen /editor and start writing.
Heisenberg v0.0.1 - first public release
The first tagged release of Heisenberg: a block-based content engine and bilingual blog backend for Laravel, with zero host coupling - your app keeps its users, routes and pages; Heisenberg brings the editor and the content model.
composer require heisenberg/heisenberg
php artisan migrate
php artisan storage:linkOpen /editor and start writing.
Highlights
🧱 Block engine & editor
- Twelve block types — headings, paragraphs, images, buttons, quotes, lists, icons, separators, embeds, and nestable groups/columns — each defined by a JSON contract, validated server-side, rendered through a sanitizing pipeline
- Full authoring chrome: inspector, floating toolbar, navigator tree, undo/redo, revisions, autosave with optimistic locking, drag & drop, dark mode
- Visual ⇄ Code view: the whole document round-trips through a compact shortcode dialect
📝 Content management
- Post lifecycle: draft → review → published / scheduled / archived, tier-gated
- Categories & tags, featured image, authored table of contents, per-post layout and discussion settings
- Bilingual (
en/fr) editor UI and per-locale content columns
🖼️ Media library
- Drag-drop uploads with per-file progress cards, responsive image variants, bilingual alt/caption metadata
- Virus-scan seam, extension allowlist, collision-safe naming, no PHP in the public read path
- Role-scoped permissions: viewers browse, authors upload and manage their own, editors manage all
🔌 Built for integration
- No native users — your users authorize through the
RoleGatecontract with four canonical roles (admin/editor/author/viewer), read from Spatie permissions or a plainrolecolumn - Host-owned templates — point
template_rootat your app, declare page chrome (featured image, TOC, comments, breadcrumbs, share…) in a validated JSON contract, render with your own Blade views - Provider contracts with null defaults for everything Heisenberg doesn't own: comments, post views, related posts, SEO meta
🤖 AI writing assistant & MCP
- Bring your own provider (Anthropic, OpenAI, or any OpenAI-compatible endpoint) — keys stored write-only and encrypted
- The assistant writes to the live canvas through validated tool calls, streams its reasoning, and remembers conversations
- MCP both ways: connect external MCP servers to the assistant, or expose Heisenberg as a draft-only, bearer-token MCP server for external agents
Requirements
PHP ^8.2 · Laravel 11 / 12 / 13 · Livewire ^4.3
Optional: intervention/image ^3.9 for responsive variants (v4 is not compatible)
Documentation
Start with the README; the full specification lives in docs/.