Upgrade Guide

Smooth way is to use composer, a dependency manager for PHP.

Run composer update and the job is done (almost).

composer show pushword/core tells you which version you run. Read every note below that is newer than it, oldest first, and skip the ones whose packages you do not install. Releases absent from the table ask for nothing beyond composer update.

Package names drop their pushword/ prefix; js-helper is the npm package @pushword/js-helper.

Release notes

VersionPackagesWhat changed
rc877admin-block-editor core flat newsletter page-scanner static-generatora newsletter audience, campaign or automation can be marked transactional and sent with no unsubscribe link; newsletter contacts keep a consent ledger of every opt-in, confirmation and unsubscribe; the static Caddyfile webp fallback needs a rebuild to fire reliably; render typography keeps quote pairs straight and a number with its unit — run doctrine:schema:update --force
rc876coretypography keeps markup carrying a > inside an attribute intact, and typographs a < that opens no tag
rc875flatan unchanged pw:flat:sync no longer bumps every page’s updatedAt and revision:
rc874corepw:image:cache in parallel no longer dies on a large media library
rc873core quizfenced_code_pre_class works for the first time; quiz images size themselves; body images size themselves inside a quiz
rc872coremarkdown body images take their sizes from body_image_sizes, settable per app
rc871core js-helperlinks to unpublished pages are restored from the pw_auth cookie instead of an auth probe; image() takes a sizes argument and defaults to 100vw
rc869newslettera newsletter form can be fetched by the front end itself, so a modal loads it on open rather than on every page load
rc868newsletterthe newsletter subscribe token is signed instead of session-bound, so a statically generated site keeps CSRF protection on
rc866newsletteraudiences carry a postal address, printed at the foot of every mail; confirmation mails are capped per address, so resubmitting no longer resends at once
rc865admin-block-editor core flatrendered text gets locale-aware typography (smart quotes, non-breaking spaces…); sources stay plain — the editor no longer writes typographic characters and the flat export straightens them
rc864advanced-main-imagethe main image “∅” format is now labelled None (Aucun in French)
rc858api conversation/api/conversation and /api/review each serve only their own type
rc857newsletterthe tracking opt-in mail states its purpose in a hint line over a bare confirm button
rc856newsletternewsletter mails can track clicks, behind a double consent — run doctrine:schema:update --force
rc853admin admin-block-editorthe show-more calls accept named arguments, and the editor writes them
rc852admin admin-block-editor conversation core js-helpera group can be made collapsible from the block editor, and the legacy show-more markers are parsed, paired and convertible
rc851quizthe quiz question list opts out of the host’s prose styling
rc850admin core flatsaving a page in the admin without editing it no longer counts as an edit; a page imported from a flat file gets an author, and editing a page no longer claims its authorship
rc849admin-block-editor core flatthe link panel’s style options are named in English so they can be translated; the static build’s workers drop the opcache file cache that was killing them; link-improver counts a page’s links once, so a site whose links are written absolute gets the density it configured; a flat file edited in the same second as a sync is no longer lost; SQLite enforces the schema’s foreign keys and makes a concurrent writer wait rather than fail
rc848admin corethe Docker account guard and the per-editor unsaved-changes key described in rc845 actually ship here; a new project installs again
rc845admin admin-block-editor core newsletter page-scanner snippet js-helpera forged delivery report can no longer unsubscribe an address; a Docker container no longer seeds a default-credential super admin over a restored database; a missing template degrades instead of 500ing the page; media uploaded after the pages naming them get their usage rows — run pw:media:usage:rebuild
rc843admin admin-block-editor advanced-main-image api conversation core flat installer link-improver newsletter page-scanner page-update-notifier quiz repurpose search snippet static-generator template-editor version js-helperevery bundle registers itself in config/bundles.php and imports its own routes; the markdown body is edited in Monaco instead of EasyMDE
rc842admin-block-editor core link-improvercard lists and galleries lay themselves out from the wrapper
rc841static-generatormultilingual static sites serve the localized 404 page
rc840core js-helperfull-bleed blocks no longer scroll the page sideways
rc839core dev-app installer page-scannerDocker is offered at install time; the page scan sees unreachable hosts again
rc838admin-block-editor page-scannerthe block editor uploads inline, groups blocks under a div wrapper, links carry any rel, and page-scan tells an unreachable link from a bad status
rc837admin-block-editor core js-helperpages_list gets a CSS-only horizontal scroller
rc835admin admin-block-editor core flat js-helper newsletter page-scanner static-generatorthe database now knows which pages use which media; admin dates follow the locale; page-scan findings have a code
rc834core newsletter page-scanner js-helperthe page scanner reports missing image alts and colliding translation locales, two newsletter contacts can be joined into one, galleries, videos and body images open in the lightbox again
rc833newsletternewsletter contacts can be keyed on a phone number, campaigns carry one body per locale, and bounces can be read over IMAP — run doctrine:schema:update --force
rc832newslettera mailbox of delivery failures can be read back into the list
rc831searchthe static search endpoint ships a populated index, and an unreadable index rebuilds itself — run pw:static
rc830static-generatorparallel static workers each get their own opcache file cache
rc829newslettera fresh install ships real starter content; six unused editorjs twig helpers are gone; automations keep a send ledger
rc828core installer newthe first install is repaired: no destructive installer, a super admin, an AGENTS.md
rc827conversation core page-scanner repurpose snippetfour more entities expose their columns as properties
rc825corepage exposes its columns as properties, with no getter/setter left
rc823newslettercontent triggers merged into automations, newsletter entities expose properties — run doctrine:schema:update --force
rc819admin core js-helperhtmx 4 in the admin, gated live blocks
rc812flatthe deploy resets production even when the push fails
rc808flatthe deploy excludes every generated output
rc807flatthe deploy counts its deletions before making them
rc805flatthe deploy script ships with the package
rc804api conversation newsletter quizquiz and newsletter API coverage, conversation merge safety
rc803api flatone serializer for the flat page file, raw .md API intake
rc802conversation flat quizflat sync survives split databases — run doctrine:schema:update --force
rc799coreentity and site state are native properties (PHP 8.4)
rc798newsletter js-helperthe newsletter form is fetched, and CSRF-protected
rc796core searchsearch runs on Loupe 1.0, pages_list searches are parsed — run pw:search:index
rc787adminthe browser no longer strips the rights it uploads
rc785coreimage rights are read from PNG, WebP and C2PA — run pw:media:license --all
rc784admin coreimage license metadata — run doctrine:schema:update --force, then pw:media:license
rc769conversationthe author IP is stored as text — run doctrine:schema:update --force
rc757core dev-apppushword/skeleton renamed to pushword/dev-app
rc673conversationreview replies
rc650versionactivity journal — run doctrine:schema:update --force
rc637api core static-generatorper-page publication hold, page-workflow removed — run doctrine:schema:update --force
rc627core flatredirectFrom authored on the destination page — run doctrine:schema:update --force
rc623apithe REST API becomes its own bundle
rc621core page-scanner js-helperunpublished links are restored for logged-in editors
rc589coreimage() is the single entry point for images
rc564js-helperthe package installs from GitHub, not npm
rc555coreretina fix: the thumb filter leaves the default filter sets
rc437flatdeferred export runs on Messenger, optional git auto-commit
rc372admin coreentity, site and content-pipeline overhaul — run doctrine:schema:update --force, then pw:migrate
rc371conversation core installerDimensions value object, media filename utils, conversation route
rc341conversation core page-update-notifierunified notification email service
rc333admin admin-block-editor conversation coretemplate changes (DOM simplification)
rc294coreMainContentSplitter replaced by a Twig function
rc247core js-helperSymfony 8 — run pw:image:cache
rc80admin admin-block-editor core flat js-helperSonata to EasyAdmin, Tailwind v4, Markdown-backed editor
rc79coreentity cleanup, pushword/svg dropped