⏱ 5 min read

What's New in 3.0

StaticForge 3.0 is a modernization release, not a rewrite. Every change in it followed the same rule: behavior stays the same unless a bug is being fixed on purpose. If you're rendering a site today, upgrading and re-running site:render should produce byte-identical output — the changes are almost entirely under the hood.

The one place that does break compatibility is how Features hook into the system. If you've written a custom Feature — in-tree or as an external Composer package — see Migrating to 3.0 for the upgrade path. Everything else on this page is safe to skim.


Requirements Changed


Typed Events Replace Array-Based Ones

Every event listener used to receive (Container $container, array $parameters) and had to return $parameters to keep the pipeline alive. That's gone. Listeners now receive one typed object — Event, RenderEvent, or a purpose-built subclass like RssItemBuildingEvent — and mutate its public properties directly. There's no array to remember to return, and no "forgot to return it, and now the site won't build" failure mode.

This is the biggest change in 3.0, and it's the reason 3.0 is a major version bump rather than a minor one. See The Nervous System: Events for the full reference and Migrating to 3.0 if you need to update your own code — that page also covers feature:migrate, a CLI command that converts most of a Feature's old event contract automatically.


Dependency Injection, Finished

Every in-tree Feature now gets its dependencies constructor-injected and autowired by a new FeatureFactory, instead of hand-building services inside register(). Two real bugs came out of finishing this:

Neither of these ever showed up as an error — they were just slower and, in MenuBuilder's case, occasionally wrong. Both are fixed.


Security Hardening

A cluster of real, previously-unguarded issues were closed in this release:

None of these change the shape of siteconfig.yaml or .env — they change what the system does with values that were always there.


Reachable-CLI Fixes


First-Party Feature Packages, All Updated

Every officially-maintained external package is migrated and released as 3.0.0, matching StaticForge's own major version: staticforge-chapternav, staticforge-google-analytics, staticforge-social-metadata, staticforge-gallery, staticforge-podcast, staticforge-popup, staticforge-sitedownloader, and answer-engine-optimization. If your composer.json still pins one of these to ^2.0 or >=1.x, bump it to ^3.0 alongside your own eicc/staticforge upgrade.


Nothing Else Changed

siteconfig.yaml, frontmatter fields, template variables, shortcode syntax, and every command's flags and output are unchanged. If you don't maintain a custom Feature, upgrading should be a version bump and nothing else.