nibula 1.2.4 → 1.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/.eleventy.js +81 -81
  2. package/.eleventyignore +3 -3
  3. package/.github/workflows/publish.yml +37 -0
  4. package/CHANGELOG.md +166 -148
  5. package/LICENSE +169 -169
  6. package/NOTICE +4 -4
  7. package/README.md +120 -123
  8. package/bin/create.js +507 -507
  9. package/bin/nibula.js +317 -305
  10. package/docs/Assistant CLI.md +65 -65
  11. package/docs/Backend.md +295 -295
  12. package/docs/Components.md +84 -84
  13. package/docs/Creating pages.md +64 -64
  14. package/docs/Deploy.md +189 -189
  15. package/docs/Head and SEO.md +138 -138
  16. package/docs/Javascript.md +50 -50
  17. package/docs/Styling with SCSS.md +141 -141
  18. package/nginx.conf +75 -75
  19. package/package.json +1 -1
  20. package/src/backend/.htaccess +6 -6
  21. package/src/backend/_core/composer.json +5 -5
  22. package/src/backend/_core/composer.lock +492 -492
  23. package/src/backend/_core/index.js +267 -267
  24. package/src/backend/_core/index.php +147 -147
  25. package/src/backend/_core/init.js +52 -52
  26. package/src/backend/_core/init.php +33 -33
  27. package/src/backend/_core/modules/RateLimiter.js +58 -58
  28. package/src/backend/_core/modules/RateLimiter.php +30 -30
  29. package/src/backend/_core/modules/Response.js +59 -59
  30. package/src/backend/_core/modules/Response.php +48 -48
  31. package/src/backend/api/protected/example-protected.js +23 -23
  32. package/src/backend/api/protected/example-protected.php +16 -16
  33. package/src/backend/api/public/example-public.js +24 -24
  34. package/src/backend/api/public/example-public.php +16 -16
  35. package/src/backend/backend-node.service.example +30 -30
  36. package/src/backend/database/Database.js +46 -46
  37. package/src/backend/database/Database.php +23 -23
  38. package/src/backend/example.config.js +37 -37
  39. package/src/backend/example.config.php +27 -27
  40. package/src/backend/package.json +18 -18
  41. package/src/backend/web.config +16 -16
  42. package/src/frontend/.htaccess +51 -51
  43. package/src/frontend/404.njk +17 -17
  44. package/src/frontend/assets/brand/favicon.svg +54 -54
  45. package/src/frontend/assets/brand/logo.svg +54 -54
  46. package/src/frontend/components/global/footer.njk +25 -25
  47. package/src/frontend/components/global/header.njk +6 -6
  48. package/src/frontend/components/welcome.njk +114 -114
  49. package/src/frontend/data/site.json +48 -48
  50. package/src/frontend/index.njk +8 -8
  51. package/src/frontend/js/modules/exampleModule.js +2 -2
  52. package/src/frontend/js/pages/404.js +6 -6
  53. package/src/frontend/js/pages/homepage.js +6 -6
  54. package/src/frontend/layouts/base.njk +132 -132
  55. package/src/frontend/layouts/page-components.njk +13 -13
  56. package/src/frontend/llms.njk +17 -17
  57. package/src/frontend/robots.njk +7 -7
  58. package/src/frontend/scss/modules/_animations.scss +24 -24
  59. package/src/frontend/scss/modules/_footer.scss +27 -27
  60. package/src/frontend/scss/modules/_global.scss +47 -47
  61. package/src/frontend/scss/modules/_header.scss +27 -27
  62. package/src/frontend/scss/modules/_mobile.scss +29 -29
  63. package/src/frontend/scss/modules/_root.scss +34 -34
  64. package/src/frontend/scss/modules/_typography.scss +14 -14
  65. package/src/frontend/scss/modules/frameworks/_bootstrap.scss +109 -109
  66. package/src/frontend/scss/modules/frameworks/_bulma.scss +108 -108
  67. package/src/frontend/scss/modules/frameworks/_foundation.scss +138 -139
  68. package/src/frontend/scss/modules/frameworks/_uikit.scss +109 -109
  69. package/src/frontend/scss/pages/404.scss +27 -27
  70. package/src/frontend/scss/pages/homepage.scss +22 -22
  71. package/src/frontend/sitemap.njk +17 -17
  72. package/src/frontend/ts/modules/exampleModule.ts +2 -2
  73. package/src/frontend/ts/pages/404.ts +6 -6
  74. package/src/frontend/ts/pages/homepage.ts +6 -6
  75. package/src/frontend/web.config +55 -55
  76. package/tools/config/messages.json +3 -1
  77. package/tools/res/templates/template.js +6 -6
  78. package/tools/res/templates/template.njk +8 -8
  79. package/tools/res/templates/template.scss +22 -22
  80. package/tools/res/templates/template.ts +6 -6
  81. package/tsconfig.json +24 -24
package/.eleventy.js CHANGED
@@ -1,82 +1,82 @@
1
- const esbuild = require("esbuild");
2
- const glob = require("glob");
3
- const Image = require("@11ty/eleventy-img");
4
- const fs = require("fs");
5
- const path = require("path");
6
-
7
- const OUTPUT_DIR = "out";
8
-
9
- module.exports = function (eleventyConfig) {
10
-
11
- function copyRecursiveSync(src, dest) {
12
- if (!fs.existsSync(src)) return;
13
- if (src.includes('.git')) return;
14
- const stat = fs.statSync(src);
15
- if (stat.isDirectory()) {
16
- fs.mkdirSync(dest, { recursive: true });
17
- for (const child of fs.readdirSync(src)) {
18
- copyRecursiveSync(path.join(src, child), path.join(dest, child));
19
- }
20
- } else {
21
- fs.mkdirSync(path.dirname(dest), { recursive: true });
22
- fs.copyFileSync(src, dest);
23
- }
24
- }
25
-
26
- eleventyConfig.on("eleventy.before", () => {
27
- copyRecursiveSync("src/backend", `${OUTPUT_DIR}/backend`);
28
- });
29
-
30
- eleventyConfig.addPassthroughCopy("src/frontend/.htaccess");
31
- eleventyConfig.addPassthroughCopy("src/frontend/web.config");
32
- eleventyConfig.addPassthroughCopy("src/frontend/assets");
33
- eleventyConfig.addPassthroughCopy("src/frontend/robots.txt");
34
-
35
- eleventyConfig.addPassthroughCopy({
36
- "node_modules/bootstrap/dist/js/bootstrap.bundle.min.js": "js/bootstrap.bundle.min.js",
37
- "node_modules/bootstrap-icons/font/fonts": "css/fonts",
38
-
39
- // Foundation
40
- // "node_modules/foundation-sites/dist/js/foundation.min.js": "js/foundation.min.js",
41
-
42
- // UIkit
43
- // "node_modules/uikit/dist/js/uikit.min.js": "js/uikit.min.js",
44
- // "node_modules/uikit/dist/js/uikit-icons.min.js": "js/uikit-icons.min.js",
45
-
46
- // Bulma — CSS only, no JS passthrough needed
47
- });
48
-
49
- eleventyConfig.addShortcode("image", async function (src, alt) {
50
- let metadata = await Image(src, {
51
- widths: [320, 480, 720, 1280, 1920, 2048, 2560, 3840, 4096, 7680],
52
- formats: ["webp", "jpeg"],
53
- outputDir: `${OUTPUT_DIR}/assets/images/`,
54
- urlPath: "/assets/images/",
55
- });
56
-
57
- return Image.generateHTML(metadata, {
58
- alt,
59
- sizes: "(max-width: 768px) 100vw, 50vw",
60
- loading: "lazy",
61
- decoding: "async",
62
- });
63
- });
64
-
65
- eleventyConfig.addWatchTarget("./src/frontend/scss");
66
- eleventyConfig.addWatchTarget("./src/frontend/routes");
67
- eleventyConfig.addWatchTarget("./src/frontend/data");
68
-
69
- eleventyConfig.setServerOptions({
70
- watch: [`${OUTPUT_DIR}/js/**/*.js`]
71
- });
72
-
73
- return {
74
- dir: {
75
- input: "src/frontend",
76
- output: OUTPUT_DIR,
77
- includes: "components",
78
- layouts: "layouts",
79
- data: "data",
80
- },
81
- };
1
+ const esbuild = require("esbuild");
2
+ const glob = require("glob");
3
+ const Image = require("@11ty/eleventy-img");
4
+ const fs = require("fs");
5
+ const path = require("path");
6
+
7
+ const OUTPUT_DIR = "out";
8
+
9
+ module.exports = function (eleventyConfig) {
10
+
11
+ function copyRecursiveSync(src, dest) {
12
+ if (!fs.existsSync(src)) return;
13
+ if (src.includes('.git')) return;
14
+ const stat = fs.statSync(src);
15
+ if (stat.isDirectory()) {
16
+ fs.mkdirSync(dest, { recursive: true });
17
+ for (const child of fs.readdirSync(src)) {
18
+ copyRecursiveSync(path.join(src, child), path.join(dest, child));
19
+ }
20
+ } else {
21
+ fs.mkdirSync(path.dirname(dest), { recursive: true });
22
+ fs.copyFileSync(src, dest);
23
+ }
24
+ }
25
+
26
+ eleventyConfig.on("eleventy.before", () => {
27
+ copyRecursiveSync("src/backend", `${OUTPUT_DIR}/backend`);
28
+ });
29
+
30
+ eleventyConfig.addPassthroughCopy("src/frontend/.htaccess");
31
+ eleventyConfig.addPassthroughCopy("src/frontend/web.config");
32
+ eleventyConfig.addPassthroughCopy("src/frontend/assets");
33
+ eleventyConfig.addPassthroughCopy("src/frontend/robots.txt");
34
+
35
+ eleventyConfig.addPassthroughCopy({
36
+ "node_modules/bootstrap/dist/js/bootstrap.bundle.min.js": "js/bootstrap.bundle.min.js",
37
+ "node_modules/bootstrap-icons/font/fonts": "css/fonts",
38
+
39
+ // Foundation
40
+ // "node_modules/foundation-sites/dist/js/foundation.min.js": "js/foundation.min.js",
41
+
42
+ // UIkit
43
+ // "node_modules/uikit/dist/js/uikit.min.js": "js/uikit.min.js",
44
+ // "node_modules/uikit/dist/js/uikit-icons.min.js": "js/uikit-icons.min.js",
45
+
46
+ // Bulma — CSS only, no JS passthrough needed
47
+ });
48
+
49
+ eleventyConfig.addShortcode("image", async function (src, alt) {
50
+ let metadata = await Image(src, {
51
+ widths: [320, 480, 720, 1280, 1920, 2048, 2560, 3840, 4096, 7680],
52
+ formats: ["webp", "jpeg"],
53
+ outputDir: `${OUTPUT_DIR}/assets/images/`,
54
+ urlPath: "/assets/images/",
55
+ });
56
+
57
+ return Image.generateHTML(metadata, {
58
+ alt,
59
+ sizes: "(max-width: 768px) 100vw, 50vw",
60
+ loading: "lazy",
61
+ decoding: "async",
62
+ });
63
+ });
64
+
65
+ eleventyConfig.addWatchTarget("./src/frontend/scss");
66
+ eleventyConfig.addWatchTarget("./src/frontend/routes");
67
+ eleventyConfig.addWatchTarget("./src/frontend/data");
68
+
69
+ eleventyConfig.setServerOptions({
70
+ watch: [`${OUTPUT_DIR}/js/**/*.js`]
71
+ });
72
+
73
+ return {
74
+ dir: {
75
+ input: "src/frontend",
76
+ output: OUTPUT_DIR,
77
+ includes: "components",
78
+ layouts: "layouts",
79
+ data: "data",
80
+ },
81
+ };
82
82
  };
package/.eleventyignore CHANGED
@@ -1,4 +1,4 @@
1
- src/frontend/assets/**
2
- src/frontend/js/**
3
- src/frontend/scss/**
1
+ src/frontend/assets/**
2
+ src/frontend/js/**
3
+ src/frontend/scss/**
4
4
  src/backend/**
@@ -0,0 +1,37 @@
1
+ name: Publish to npm
2
+
3
+ on:
4
+ release:
5
+ types: [published]
6
+ workflow_dispatch:
7
+
8
+ permissions:
9
+ contents: read
10
+ id-token: write
11
+
12
+ jobs:
13
+ publish:
14
+ runs-on: ubuntu-latest
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+
18
+ - uses: actions/setup-node@v4
19
+ with:
20
+ node-version: 22
21
+ registry-url: https://registry.npmjs.org
22
+
23
+ - name: Check that package.json matches the tag
24
+ if: github.event_name == 'release'
25
+ run: |
26
+ TAG="${GITHUB_REF_NAME#v}"
27
+ PKG=$(node -p "require('./package.json').version")
28
+ if [ "$TAG" != "$PKG" ]; then
29
+ echo "Tag $TAG does not match package.json version $PKG"
30
+ exit 1
31
+ fi
32
+
33
+ - run: npm install -g npm@latest
34
+
35
+ - run: npm ci
36
+
37
+ - run: npm publish --provenance --access public
package/CHANGELOG.md CHANGED
@@ -1,148 +1,166 @@
1
- # Changelog
2
-
3
- All notable changes to Nibula are documented here.
4
-
5
- The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
- and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
-
8
- ## [1.2.4] - 2026-07-31
9
-
10
- ### Changed
11
- - Refactor interno di `tools/`: la logica è divisa in `lib/`, `cli/` e
12
- `config/`, con valori e messaggi estratti in `settings.json` e
13
- `messages.json`. Nessun cambiamento di comportamento.
14
- - La CLI usa una palette uniforme: il colore resta solo sul riquadro del
15
- titolo, i numeri delle voci sono attenuati.
16
-
17
- ### Fixed
18
- - L'ultima riga del menu non chiudeva il codice colore `dim`, che restava
19
- attivo sulla riga successiva.
20
-
21
- ## [1.2.3] - 2026-07-29
22
-
23
- ### Fixed
24
- - `updateOutputPath` no longer strips custom flags from `build:css` and `serve:css`: the output path is now replaced in place instead of regenerating the whole script
25
- - Missing `--load-path=node_modules` in the regenerated Sass scripts, which broke Bootstrap SCSS imports
26
- - Malformed `outDir` in `tsconfig.json` when the output path is absolute (`./c:/...`)
27
-
28
- ## [1.2.2] - 2026-07-23
29
-
30
- ### Added
31
- - **Full favicon set**: `favicon.svg`, `favicon-32.png` and `apple-touch-icon.png`
32
- (180×180, opaque) in `assets/brand/`. iOS home-screen icons no longer fall back
33
- to a screenshot of the page.
34
-
35
- ### Changed
36
- - **`data_bs_theme` renamed to `theme`** in `site.json`. It still drives
37
- `data-bs-theme` on the `<html>` tag; the shorter name keeps the config readable
38
- and independent from the framework naming.
39
- - **`theme_color` is now a single value** instead of a `light`/`dark` pair. The
40
- theme is fixed per build, so two per-scheme colors could contradict the
41
- rendered page.
42
- - **Favicon paths are hardcoded in `base.njk`.** The `favicon` key was removed
43
- from `site.json`: it only ever covered one of the three tags, which was more
44
- confusing than helpful. Replace the files in `assets/brand/` instead.
45
- - `_routes/` renamed to `routes/` — it holds entry points, not internals.
46
-
47
- ### Removed
48
- - **`mdFile` shortcode** and the `markdown-it` dependency.
49
- - **`github-markdown-css`** and its two passthrough copies.
50
-
51
- ### Migration
52
- - In `site.json`: rename `data_bs_theme` to `theme`, flatten `theme_color` to a
53
- single string, drop `favicon`.
54
- - Place `favicon.svg`, `favicon-32.png` and `apple-touch-icon.png` in
55
- `src/frontend/assets/brand/`.
56
- - If you used `{% mdFile %}`, render the Markdown ahead of time or add
57
- `markdown-it` back to your own project.
58
-
59
- ## [1.1.3] - 2026-07-22
60
-
61
- ### Changed
62
- - **The update check no longer runs on every command.** Previously every
63
- invocation of `nib` (and the `nbl` / `nibula` aliases) contacted the npm
64
- registry before doing anything, adding up to 2.5s of latency to `nib run`,
65
- `nib build`, `nib cli` and `nib clean`. The check now runs only for `nib new`
66
- and `nib update`; all other commands work entirely offline.
67
- - **`nib new` now completes the update automatically.** When a newer version is
68
- available and you accept the prompt, Nibula installs it and immediately
69
- re-runs the scaffolding with the new version, instead of asking you to type
70
- `nib new <project-name>` a second time.
71
- - **New projects are scaffolded at version `0.0.0`** instead of `1.0.0`, so a
72
- freshly created site no longer claims a stable public release. Bump it
73
- yourself as the project grows, and reach `1.0.0` when you go to production.
74
- - **Framework SCSS imports are now short and readable.** The framework modules
75
- in `src/frontend/scss/modules/frameworks/` used a five-level relative path
76
- back to `node_modules`; they now import directly by package name, e.g.
77
- `@import "bootstrap/scss/card";`. This matches what the styling docs already
78
- showed, and makes commenting modules out far less error-prone.
79
- - `nib help` no longer appends an "a newer version is available" line, since it
80
- no longer performs the check.
81
-
82
- ### Added
83
- - Internal `--skip-update-check` flag on `nib new`, set automatically when the
84
- command is re-run after a self-update. It prevents a loop if the registry is
85
- slow to propagate the new version.
86
- - `--load-path=node_modules` on the repository's own `build:css` and `serve:css`
87
- scripts, so the short framework imports resolve. Generated projects already
88
- carried this flag.
89
-
90
- ### Fixed
91
- - Repaired the ASCII header boxes and the commented-out example import inside
92
- `_bootstrap.scss`, `_bulma.scss` and `_foundation.scss`, where an earlier
93
- find-and-replace had injected the `node_modules` path into comment text and
94
- broken the alignment.
95
- - `src/frontend/data` is no longer copied to the output folder. It holds the
96
- Eleventy global data file, which is consumed at build time to render meta
97
- tags and page config publishing it produced a dead file in `out/` and
98
- exposed the full page map, including `noindex` entries. It remains a watch
99
- target, so edits still trigger a rebuild.
100
-
101
- ### Notes
102
- - If the updated installation can't be located after `npm install -g` (an
103
- unusual `npm root -g` setup, for example), Nibula reports the problem and
104
- asks you to re-run the command, rather than scaffolding silently with the
105
- old templates.
106
- - Existing projects are unaffected by the version change: it applies only to
107
- newly created ones.
108
- - Short SCSS imports rely on Sass's `--load-path`, which is passed by the npm
109
- scripts. Compiling the stylesheets with a different tool (a VS Code Sass
110
- extension, for instance) will need the same load path configured.
111
-
112
- ## [1.1.0] - 2026-07-21
113
-
114
- ### Added
115
- - **Node.js backend** as an alternative to PHP, living side by side in
116
- `src/backend/`: `_core/index.js` front controller (which is also the HTTP
117
- server), `Response` and `RateLimiter` modules, a `mysql2` pool singleton
118
- `Database.js`, `example.config.js`, and a `package.json` for the backend's
119
- own dependencies. Same REST API as PHP: routing, `X-Api-Key` auth, CORS and
120
- file-based rate limiting are identical.
121
- - **Backend choice at scaffold time**: `nib new` now asks whether to use Node.js
122
- or PHP, in addition to language and CSS framework.
123
- - `backend/backend-node.service.example` — a ready-to-adapt **systemd** unit for
124
- keeping the Node backend running on a server.
125
- - `config.js` is generated from `example.config.js` at scaffold time (mirroring
126
- the existing `config.php` generation).
127
- - Deployment docs now cover running the Node backend with **`screen`** (quick /
128
- small setups) and **systemd** (production), plus environment variables.
129
-
130
- ### Changed
131
- - **Composer is now required only when the PHP backend is chosen.** If you pick
132
- Node, `composer install` is skipped entirely and the backend's npm
133
- dependencies (`mysql2`) are installed instead.
134
- - `.htaccess`, `web.config` and `nginx.conf` now cover **both** backends. On
135
- nginx, `/api` goes to Node and automatically falls back to the PHP front
136
- controller when Node is unreachable. On Apache/IIS the active backend is
137
- selected by configuration (documented), since per-directory configs can't
138
- health-check an upstream.
139
- - `.gitignore` now also ignores `src/backend/config.js`,
140
- `src/backend/node_modules/` and `src/backend/cache/`.
141
- - Documentation (`README.md`, `docs/Backend.md`, `docs/Deploy.md`) updated:
142
- backend examples now use JavaScript/Node as the reference, with the equivalent
143
- PHP shown alongside and a note that PHP behaves identically.
144
-
145
- ### Notes
146
- - Both backends are always scaffolded, so you can switch later without
147
- re-creating the project. The PHP front controller only serves `.php` endpoint
148
- files and the Node one only `.js`, so they coexist without conflict.
1
+ # Changelog
2
+
3
+ All notable changes to Nibula are documented here.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [1.2.5] - 2026-08-01
9
+
10
+ ### Added
11
+ - `nib new` now refuses to run from inside an existing Nibula project. Creating
12
+ a project inside another one produced a broken setup, since the outer build
13
+ would pick up the inner project's files. The error message reports the path of
14
+ the project that was detected, so it's clear which one triggered the check.
15
+ - A GitHub Actions workflow that publishes the package to npm whenever a release
16
+ is created, using npm's trusted publishing. The workflow verifies that the git
17
+ tag matches the version in `package.json` before publishing, and attaches a
18
+ provenance attestation to the published package.
19
+
20
+ ### Changed
21
+ - Rewrote the README: added a section on when Nibula is *not* the right tool,
22
+ clarified that Composer is only needed with the PHP backend, and moved the
23
+ editor extensions from the required to the recommended prerequisites.
24
+
25
+ ## [1.2.4] - 2026-07-31
26
+
27
+ ### Changed
28
+ - Internal refactor of `tools/`: the logic is now split across `lib/`, `cli/`
29
+ and `config/`, with values and messages extracted into `settings.json` and
30
+ `messages.json`. No behaviour changes — pages, `site.json` and
31
+ `page-components.njk` are written exactly as before.
32
+ - The CLI now uses a uniform palette: colour is limited to the title box, and
33
+ the menu numbers are dimmed instead of each carrying its own colour.
34
+
35
+ ### Fixed
36
+ - The last line of the menu never closed the `dim` colour code, which stayed
37
+ active on the following line.
38
+
39
+ ## [1.2.3] - 2026-07-29
40
+
41
+ ### Fixed
42
+ - `updateOutputPath` no longer strips custom flags from `build:css` and `serve:css`: the output path is now replaced in place instead of regenerating the whole script
43
+ - Missing `--load-path=node_modules` in the regenerated Sass scripts, which broke Bootstrap SCSS imports
44
+ - Malformed `outDir` in `tsconfig.json` when the output path is absolute (`./c:/...`)
45
+
46
+ ## [1.2.2] - 2026-07-23
47
+
48
+ ### Added
49
+ - **Full favicon set**: `favicon.svg`, `favicon-32.png` and `apple-touch-icon.png`
50
+ (180×180, opaque) in `assets/brand/`. iOS home-screen icons no longer fall back
51
+ to a screenshot of the page.
52
+
53
+ ### Changed
54
+ - **`data_bs_theme` renamed to `theme`** in `site.json`. It still drives
55
+ `data-bs-theme` on the `<html>` tag; the shorter name keeps the config readable
56
+ and independent from the framework naming.
57
+ - **`theme_color` is now a single value** instead of a `light`/`dark` pair. The
58
+ theme is fixed per build, so two per-scheme colors could contradict the
59
+ rendered page.
60
+ - **Favicon paths are hardcoded in `base.njk`.** The `favicon` key was removed
61
+ from `site.json`: it only ever covered one of the three tags, which was more
62
+ confusing than helpful. Replace the files in `assets/brand/` instead.
63
+ - `_routes/` renamed to `routes/` it holds entry points, not internals.
64
+
65
+ ### Removed
66
+ - **`mdFile` shortcode** and the `markdown-it` dependency.
67
+ - **`github-markdown-css`** and its two passthrough copies.
68
+
69
+ ### Migration
70
+ - In `site.json`: rename `data_bs_theme` to `theme`, flatten `theme_color` to a
71
+ single string, drop `favicon`.
72
+ - Place `favicon.svg`, `favicon-32.png` and `apple-touch-icon.png` in
73
+ `src/frontend/assets/brand/`.
74
+ - If you used `{% mdFile %}`, render the Markdown ahead of time or add
75
+ `markdown-it` back to your own project.
76
+
77
+ ## [1.1.3] - 2026-07-22
78
+
79
+ ### Changed
80
+ - **The update check no longer runs on every command.** Previously every
81
+ invocation of `nib` (and the `nbl` / `nibula` aliases) contacted the npm
82
+ registry before doing anything, adding up to 2.5s of latency to `nib run`,
83
+ `nib build`, `nib cli` and `nib clean`. The check now runs only for `nib new`
84
+ and `nib update`; all other commands work entirely offline.
85
+ - **`nib new` now completes the update automatically.** When a newer version is
86
+ available and you accept the prompt, Nibula installs it and immediately
87
+ re-runs the scaffolding with the new version, instead of asking you to type
88
+ `nib new <project-name>` a second time.
89
+ - **New projects are scaffolded at version `0.0.0`** instead of `1.0.0`, so a
90
+ freshly created site no longer claims a stable public release. Bump it
91
+ yourself as the project grows, and reach `1.0.0` when you go to production.
92
+ - **Framework SCSS imports are now short and readable.** The framework modules
93
+ in `src/frontend/scss/modules/frameworks/` used a five-level relative path
94
+ back to `node_modules`; they now import directly by package name, e.g.
95
+ `@import "bootstrap/scss/card";`. This matches what the styling docs already
96
+ showed, and makes commenting modules out far less error-prone.
97
+ - `nib help` no longer appends an "a newer version is available" line, since it
98
+ no longer performs the check.
99
+
100
+ ### Added
101
+ - Internal `--skip-update-check` flag on `nib new`, set automatically when the
102
+ command is re-run after a self-update. It prevents a loop if the registry is
103
+ slow to propagate the new version.
104
+ - `--load-path=node_modules` on the repository's own `build:css` and `serve:css`
105
+ scripts, so the short framework imports resolve. Generated projects already
106
+ carried this flag.
107
+
108
+ ### Fixed
109
+ - Repaired the ASCII header boxes and the commented-out example import inside
110
+ `_bootstrap.scss`, `_bulma.scss` and `_foundation.scss`, where an earlier
111
+ find-and-replace had injected the `node_modules` path into comment text and
112
+ broken the alignment.
113
+ - `src/frontend/data` is no longer copied to the output folder. It holds the
114
+ Eleventy global data file, which is consumed at build time to render meta
115
+ tags and page config publishing it produced a dead file in `out/` and
116
+ exposed the full page map, including `noindex` entries. It remains a watch
117
+ target, so edits still trigger a rebuild.
118
+
119
+ ### Notes
120
+ - If the updated installation can't be located after `npm install -g` (an
121
+ unusual `npm root -g` setup, for example), Nibula reports the problem and
122
+ asks you to re-run the command, rather than scaffolding silently with the
123
+ old templates.
124
+ - Existing projects are unaffected by the version change: it applies only to
125
+ newly created ones.
126
+ - Short SCSS imports rely on Sass's `--load-path`, which is passed by the npm
127
+ scripts. Compiling the stylesheets with a different tool (a VS Code Sass
128
+ extension, for instance) will need the same load path configured.
129
+
130
+ ## [1.1.0] - 2026-07-21
131
+
132
+ ### Added
133
+ - **Node.js backend** as an alternative to PHP, living side by side in
134
+ `src/backend/`: `_core/index.js` front controller (which is also the HTTP
135
+ server), `Response` and `RateLimiter` modules, a `mysql2` pool singleton
136
+ `Database.js`, `example.config.js`, and a `package.json` for the backend's
137
+ own dependencies. Same REST API as PHP: routing, `X-Api-Key` auth, CORS and
138
+ file-based rate limiting are identical.
139
+ - **Backend choice at scaffold time**: `nib new` now asks whether to use Node.js
140
+ or PHP, in addition to language and CSS framework.
141
+ - `backend/backend-node.service.example` — a ready-to-adapt **systemd** unit for
142
+ keeping the Node backend running on a server.
143
+ - `config.js` is generated from `example.config.js` at scaffold time (mirroring
144
+ the existing `config.php` generation).
145
+ - Deployment docs now cover running the Node backend with **`screen`** (quick /
146
+ small setups) and **systemd** (production), plus environment variables.
147
+
148
+ ### Changed
149
+ - **Composer is now required only when the PHP backend is chosen.** If you pick
150
+ Node, `composer install` is skipped entirely and the backend's npm
151
+ dependencies (`mysql2`) are installed instead.
152
+ - `.htaccess`, `web.config` and `nginx.conf` now cover **both** backends. On
153
+ nginx, `/api` goes to Node and automatically falls back to the PHP front
154
+ controller when Node is unreachable. On Apache/IIS the active backend is
155
+ selected by configuration (documented), since per-directory configs can't
156
+ health-check an upstream.
157
+ - `.gitignore` now also ignores `src/backend/config.js`,
158
+ `src/backend/node_modules/` and `src/backend/cache/`.
159
+ - Documentation (`README.md`, `docs/Backend.md`, `docs/Deploy.md`) updated:
160
+ backend examples now use JavaScript/Node as the reference, with the equivalent
161
+ PHP shown alongside and a note that PHP behaves identically.
162
+
163
+ ### Notes
164
+ - Both backends are always scaffolded, so you can switch later without
165
+ re-creating the project. The PHP front controller only serves `.php` endpoint
166
+ files and the Node one only `.js`, so they coexist without conflict.