2.0.0
Version 2.0.0 focuses on simplicity and clear APIs over feature accumulation: fewer abstractions, clearer responsibilities, and a more focused API.
Breaking Changes
- Renamed
BaseComponent'schildConfigs()toregisterChildren()andcatalogConfig()tocreateCatalogComponents(). - Raised the required Node.js version from
>=18to>=22. - Removed all libraries except
Pipes, as they did not fit Nutin's philosophy. - Removed
Store. Its responsibilities were unclear and largely duplicated what services already provide. - Removed the
forceparameter fromlistenToRenderEvents(). It is no longer needed.
Architecture & API
Clarified and separated the responsibilities of the base classes:
BaseComponent: render lifecycle, hydration, DOM lifecycle, DOM and EventBus subscriptions, teardown, render guard, and composition orchestration.Component: props (className,style,data-bindings), configuration/defaults/normalization, and template generation throughtemplateFn.View: route parameters, navigation hooks (onEnter()/onExit()), and view identity (viewName).
Components and Views now inherit
listen()andlistenToRenderEvents()methods with automatic unsubscription.Added explicit lifecycle hooks:
- Component:
onBeforeRender(),onAfterRender(),onBeforeDestroy(),onAfterDestroy() - View:
onEnter(),onExit()
- Component:
Simplified the EventBus API:
- Added
AppEventMapfor app-level events. Nutin's internal events are no longer declared inglobals.d.ts. - Event payload types are now objects.
- EventBus now exposes domain facades for
NavigationandLifecycleevents. - Event subscription functions (
on*) now return a closure for unsubscription. AppEventBuscan still be used directly when needed (once(), etc.), but subscriptions must then be unsubscribed manually through theonBeforeDestroy()hook.
- Added
// emit
Navigation.navigateTo('path');
// closure
const unsub = Navigation.onNavigate(this.doStuff);
// onDestroy
unsub()
Services
- Services now expose a single
getInstance()method. - Arguments can be passed to
getInstance(), but are only used during the first instantiation.
Configuration & Build
- Added
nutin.config.jsas the central configuration file for Nutin options, builder, generator, and testing. - Added optional Tailwind CSS v4 support as a utility layer alongside SASS.
- Added globally scoped stylesheets co-located with feature files. Use unique class names. Nutin's naming convention encourages prefixes such as
home__header. - HTML templates can now be either inline or external
.htmlfiles. Defining both, or neither, fails the build. - Added configurable Docker ports through
nutin.config.js. - Dockerfile now builds a Brotli-enabled image.
SEO & i18n
Added optional generation of static SEO files from
config/seo.json.- Production builds generate static HTML for each route using the actual components.
- Only
title,description, andogImageremain hand-authored SEO content. - Generates
robots.txtandsitemap.xml. - Supports per-route
disallowanddisallowBots.
i18n now uses the URL, aligning with common practices and allowing static SEO HTML to be generated for each language.
CLI & Developer Experience
- Added
nutin-update, which updates Nutin to the latest patch or minor version by diffing the project against the new templates and merging compatible changes. Unresolved conflicts are reported. - Added
nutin-add docker. - Added
GETTING_STARTED.md, providing the architectural context and conventions needed to start working with a Nutin project without immediately consulting the full documentation. - Added
AGENTS.md, providing LLMs with the minimal context required to work effectively in a Nutin project.
TestinNutin
- Added code coverage summaries for branches, functions, and lines.
- Added
it.todo. - Added clock mocking for
setTimeoutandsetInterval.
Bug Fixes
- Numerous bug fixes and stability improvements.