2.1.1
Changes
src/appno longer has an imposed structure.
The generator now creates elements in src/app/<path>/ instead of src/app/<type>s/<path>/ (e.g. generate view user/user-view → src/app/user/user-view/).
New projects still ship components/, services/ (empty) and views/ as the suggested layout, so pass the folder explicitly to keep it (generate component components/my-component).
- Removed the
src/app/{components,views,services}/index.tsbarrel files from new projects, and the generator no longer appends exports to them.
Import app elements by their file path.
Import Nutin elements by the framework's barrel (src/core/index.ts).
Sass now compiles every
.scssfile undersrc/appinstead of onlysrc/app/componentsandsrc/app/views.The generator now exits before writing anything if the target folder already exists and isn't empty, since folder names carry no type suffix.
Dev builds (
dev/serve/build) now bundle with esbuild too, unminified with a sourcemap andconsole/debuggerkept, so npm runtime dependencies work in dev without import maps or vendoring. tsc's per-file output is still emitted for testin-nutin.Sass now resolves
@use "pkg:<package>/<path>"imports throughnode_modules.The default
builder.esbuild.targetinnutin.config.jsis nowes2020(wases2015), which libraries relying on nativeasyncfunctions (e.g. Alpine) require. Existing projects keep their ownnutin.config.jsvalue.Generated SEO HTML now includes
hreflangalternates (one per language plusx-default) when i18n is enabled,og:typeandtwitter:card(summary_large_image) meta tags, and an absoluteog:image/twitter:imageURL (a relativeogImageinconfig/seo.jsonis now prefixed withbaseUrl).The router now supports
#hashfragments: navigating topath#idkeeps the hash in the URL and scrolls to the matching element, falling back to the top of the page. The hash is also kept on reload and on language change.New
NavigationManager.replaceState(path)(exported fromcore/index.ts) rewrites the current URL without adding a history entry. The router now updates history before rendering the new view, so a view'sonEnter()can call it without the change being overwritten.Docker feature:
tools/docker/Dockerfile.templatenow defaults to Node24.21.0(was22.23.2) Alpine3.24(was3.20, end-of-life) for the nginx runtime image (nginx1.26→1.30).Docker feature: in i18n projects, nginx now redirects a bare
/to the default language (generated intonginx.confthrough a new__ROOT_REDIRECT_PLACEHOLDER__token).
Fixes
generatewith a missing argument now prints its usage message instead of crashing.Attributes set on a
data-componentplaceholder (class,id,aria-*,data-*, …) are now kept on the mounted component's element instead of being dropped. Classes are merged with the component's own.Builds now take a lock (
.build-lock/, gitignored) before touchingdist-build, so concurrent builds (a manual build duringdev, or stray watcher processes) no longer corrupt each other's output.The dev watcher no longer drops a file change made while a rebuild is running. It now rebuilds again once the current build finishes.
Stopping
devnow kills the whole process group of live-server and the watcher (including an in-flight build), so no orphaned watcher processes are left behind. On Windows, the process tree is killed withtaskkillinstead.SSR now renders views into a real
<main id="app">, so unsetdata-optionalfields are removed from prerendered HTML instead of leaking the literal textundefined.Ctrl/Cmd/Shift/Alt-clicks and middle-clicks on
<a href>elements with adata-eventclick handler now fall through to the browser's native behaviour (e.g. open in a new tab), instead of being intercepted.Docker feature: nginx now issues relative redirects (
absolute_redirect off), so the trailing-slash redirect on prerendered routes no longer leaks the container's internal port or scheme behind a proxy. A route directory without its ownindex.htmlnow serves the SPA shell instead of a 403.