nibula 1.2.3 → 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 (106) 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 -135
  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 +316 -307
  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/assistant.js +122 -151
  77. package/tools/buildJs.js +39 -37
  78. package/tools/cleanOutput.js +23 -25
  79. package/tools/cli/prompt.js +40 -0
  80. package/tools/cli/ui.js +74 -0
  81. package/tools/config/messages.json +78 -0
  82. package/tools/config/settings.json +135 -0
  83. package/tools/lib/colors.js +17 -0
  84. package/tools/lib/files.js +65 -0
  85. package/tools/lib/logger.js +22 -0
  86. package/tools/lib/outputPath.js +141 -0
  87. package/tools/lib/pageActions.js +138 -0
  88. package/tools/lib/pageArtifacts.js +46 -0
  89. package/tools/lib/pageComponents.js +88 -0
  90. package/tools/lib/paths.js +61 -0
  91. package/tools/lib/project.js +54 -0
  92. package/tools/lib/siteData.js +93 -0
  93. package/tools/lib/text.js +47 -0
  94. package/tools/lib/validation.js +39 -0
  95. package/tools/res/templates/template.js +7 -5
  96. package/tools/res/templates/template.njk +8 -8
  97. package/tools/res/templates/template.scss +22 -22
  98. package/tools/res/templates/template.ts +7 -5
  99. package/tsconfig.json +24 -24
  100. package/tools/modules/constants.js +0 -66
  101. package/tools/modules/pageComponents.js +0 -77
  102. package/tools/modules/updateData.js +0 -90
  103. package/tools/modules/updateOutputPath.js +0 -133
  104. package/tools/modules/updatePage.js +0 -162
  105. package/tools/modules/utils.js +0 -27
  106. package/tools/modules/validation.js +0 -30
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,135 +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.3] - 2026-07-29
9
-
10
- ### Fixed
11
- - `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
12
- - Missing `--load-path=node_modules` in the regenerated Sass scripts, which broke Bootstrap SCSS imports
13
- - Malformed `outDir` in `tsconfig.json` when the output path is absolute (`./c:/...`)
14
-
15
- ## [1.2.2] - 2026-07-23
16
-
17
- ### Added
18
- - **Full favicon set**: `favicon.svg`, `favicon-32.png` and `apple-touch-icon.png`
19
- (180×180, opaque) in `assets/brand/`. iOS home-screen icons no longer fall back
20
- to a screenshot of the page.
21
-
22
- ### Changed
23
- - **`data_bs_theme` renamed to `theme`** in `site.json`. It still drives
24
- `data-bs-theme` on the `<html>` tag; the shorter name keeps the config readable
25
- and independent from the framework naming.
26
- - **`theme_color` is now a single value** instead of a `light`/`dark` pair. The
27
- theme is fixed per build, so two per-scheme colors could contradict the
28
- rendered page.
29
- - **Favicon paths are hardcoded in `base.njk`.** The `favicon` key was removed
30
- from `site.json`: it only ever covered one of the three tags, which was more
31
- confusing than helpful. Replace the files in `assets/brand/` instead.
32
- - `_routes/` renamed to `routes/` it holds entry points, not internals.
33
-
34
- ### Removed
35
- - **`mdFile` shortcode** and the `markdown-it` dependency.
36
- - **`github-markdown-css`** and its two passthrough copies.
37
-
38
- ### Migration
39
- - In `site.json`: rename `data_bs_theme` to `theme`, flatten `theme_color` to a
40
- single string, drop `favicon`.
41
- - Place `favicon.svg`, `favicon-32.png` and `apple-touch-icon.png` in
42
- `src/frontend/assets/brand/`.
43
- - If you used `{% mdFile %}`, render the Markdown ahead of time or add
44
- `markdown-it` back to your own project.
45
-
46
- ## [1.1.3] - 2026-07-22
47
-
48
- ### Changed
49
- - **The update check no longer runs on every command.** Previously every
50
- invocation of `nib` (and the `nbl` / `nibula` aliases) contacted the npm
51
- registry before doing anything, adding up to 2.5s of latency to `nib run`,
52
- `nib build`, `nib cli` and `nib clean`. The check now runs only for `nib new`
53
- and `nib update`; all other commands work entirely offline.
54
- - **`nib new` now completes the update automatically.** When a newer version is
55
- available and you accept the prompt, Nibula installs it and immediately
56
- re-runs the scaffolding with the new version, instead of asking you to type
57
- `nib new <project-name>` a second time.
58
- - **New projects are scaffolded at version `0.0.0`** instead of `1.0.0`, so a
59
- freshly created site no longer claims a stable public release. Bump it
60
- yourself as the project grows, and reach `1.0.0` when you go to production.
61
- - **Framework SCSS imports are now short and readable.** The framework modules
62
- in `src/frontend/scss/modules/frameworks/` used a five-level relative path
63
- back to `node_modules`; they now import directly by package name, e.g.
64
- `@import "bootstrap/scss/card";`. This matches what the styling docs already
65
- showed, and makes commenting modules out far less error-prone.
66
- - `nib help` no longer appends an "a newer version is available" line, since it
67
- no longer performs the check.
68
-
69
- ### Added
70
- - Internal `--skip-update-check` flag on `nib new`, set automatically when the
71
- command is re-run after a self-update. It prevents a loop if the registry is
72
- slow to propagate the new version.
73
- - `--load-path=node_modules` on the repository's own `build:css` and `serve:css`
74
- scripts, so the short framework imports resolve. Generated projects already
75
- carried this flag.
76
-
77
- ### Fixed
78
- - Repaired the ASCII header boxes and the commented-out example import inside
79
- `_bootstrap.scss`, `_bulma.scss` and `_foundation.scss`, where an earlier
80
- find-and-replace had injected the `node_modules` path into comment text and
81
- broken the alignment.
82
- - `src/frontend/data` is no longer copied to the output folder. It holds the
83
- Eleventy global data file, which is consumed at build time to render meta
84
- tags and page config publishing it produced a dead file in `out/` and
85
- exposed the full page map, including `noindex` entries. It remains a watch
86
- target, so edits still trigger a rebuild.
87
-
88
- ### Notes
89
- - If the updated installation can't be located after `npm install -g` (an
90
- unusual `npm root -g` setup, for example), Nibula reports the problem and
91
- asks you to re-run the command, rather than scaffolding silently with the
92
- old templates.
93
- - Existing projects are unaffected by the version change: it applies only to
94
- newly created ones.
95
- - Short SCSS imports rely on Sass's `--load-path`, which is passed by the npm
96
- scripts. Compiling the stylesheets with a different tool (a VS Code Sass
97
- extension, for instance) will need the same load path configured.
98
-
99
- ## [1.1.0] - 2026-07-21
100
-
101
- ### Added
102
- - **Node.js backend** as an alternative to PHP, living side by side in
103
- `src/backend/`: `_core/index.js` front controller (which is also the HTTP
104
- server), `Response` and `RateLimiter` modules, a `mysql2` pool singleton
105
- `Database.js`, `example.config.js`, and a `package.json` for the backend's
106
- own dependencies. Same REST API as PHP: routing, `X-Api-Key` auth, CORS and
107
- file-based rate limiting are identical.
108
- - **Backend choice at scaffold time**: `nib new` now asks whether to use Node.js
109
- or PHP, in addition to language and CSS framework.
110
- - `backend/backend-node.service.example` a ready-to-adapt **systemd** unit for
111
- keeping the Node backend running on a server.
112
- - `config.js` is generated from `example.config.js` at scaffold time (mirroring
113
- the existing `config.php` generation).
114
- - Deployment docs now cover running the Node backend with **`screen`** (quick /
115
- small setups) and **systemd** (production), plus environment variables.
116
-
117
- ### Changed
118
- - **Composer is now required only when the PHP backend is chosen.** If you pick
119
- Node, `composer install` is skipped entirely and the backend's npm
120
- dependencies (`mysql2`) are installed instead.
121
- - `.htaccess`, `web.config` and `nginx.conf` now cover **both** backends. On
122
- nginx, `/api` goes to Node and automatically falls back to the PHP front
123
- controller when Node is unreachable. On Apache/IIS the active backend is
124
- selected by configuration (documented), since per-directory configs can't
125
- health-check an upstream.
126
- - `.gitignore` now also ignores `src/backend/config.js`,
127
- `src/backend/node_modules/` and `src/backend/cache/`.
128
- - Documentation (`README.md`, `docs/Backend.md`, `docs/Deploy.md`) updated:
129
- backend examples now use JavaScript/Node as the reference, with the equivalent
130
- PHP shown alongside and a note that PHP behaves identically.
131
-
132
- ### Notes
133
- - Both backends are always scaffolded, so you can switch later without
134
- re-creating the project. The PHP front controller only serves `.php` endpoint
135
- 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.