nibula 1.1.3 → 1.2.0
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.
- package/.eleventy.js +2 -9
- package/CHANGELOG.md +34 -49
- package/README.md +7 -3
- package/bin/create.js +3 -4
- package/bin/nibula.js +27 -55
- package/docs/Assistant CLI.md +1 -1
- package/docs/Components.md +3 -14
- package/docs/Creating pages.md +5 -5
- package/docs/Head and SEO.md +36 -14
- package/docs/Javascript.md +1 -3
- package/docs/Styling with SCSS.md +9 -3
- package/nginx.conf +75 -75
- package/package.json +5 -5
- package/src/backend/_core/index.js +267 -267
- package/src/backend/_core/init.js +52 -52
- package/src/backend/_core/modules/RateLimiter.js +58 -58
- package/src/backend/_core/modules/Response.js +59 -59
- package/src/backend/api/protected/example-protected.js +23 -23
- package/src/backend/api/public/example-public.js +24 -24
- package/src/backend/backend-node.service.example +30 -30
- package/src/backend/database/Database.js +46 -46
- package/src/backend/example.config.js +37 -37
- package/src/backend/package.json +18 -18
- package/src/frontend/.htaccess +51 -51
- package/src/frontend/assets/brand/apple-touch-icon.png +0 -0
- package/src/frontend/assets/brand/favicon-32.png +0 -0
- package/src/frontend/assets/brand/favicon-48.png +0 -0
- package/src/frontend/assets/brand/favicon.svg +54 -54
- package/src/frontend/assets/brand/logo.svg +54 -54
- package/src/frontend/components/global/header.njk +1 -1
- package/src/frontend/components/welcome.njk +0 -1
- package/src/frontend/data/site.json +48 -54
- package/src/frontend/layouts/base.njk +6 -15
- package/src/frontend/scss/modules/frameworks/_bootstrap.scss +66 -66
- package/src/frontend/scss/modules/frameworks/_bulma.scss +65 -65
- package/src/frontend/scss/modules/frameworks/_foundation.scss +98 -98
- package/src/frontend/scss/modules/frameworks/_uikit.scss +79 -79
- package/src/frontend/web.config +55 -55
- package/{_tools → tools}/modules/constants.js +2 -2
- /package/{_tools → tools}/assistant.js +0 -0
- /package/{_tools → tools}/buildJs.js +0 -0
- /package/{_tools → tools}/cleanOutput.js +0 -0
- /package/{_tools → tools}/modules/pageComponents.js +0 -0
- /package/{_tools → tools}/modules/updateData.js +0 -0
- /package/{_tools → tools}/modules/updateOutputPath.js +0 -0
- /package/{_tools → tools}/modules/updatePage.js +0 -0
- /package/{_tools → tools}/modules/utils.js +0 -0
- /package/{_tools → tools}/modules/validation.js +0 -0
- /package/{_tools → tools}/res/templates/template.js +0 -0
- /package/{_tools → tools}/res/templates/template.njk +0 -0
- /package/{_tools → tools}/res/templates/template.scss +0 -0
- /package/{_tools → tools}/res/templates/template.ts +0 -0
package/.eleventy.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
const esbuild = require("esbuild");
|
|
2
2
|
const glob = require("glob");
|
|
3
3
|
const Image = require("@11ty/eleventy-img");
|
|
4
|
-
const markdownIt = require('markdown-it');
|
|
5
4
|
const fs = require("fs");
|
|
6
5
|
const path = require("path");
|
|
7
6
|
|
|
@@ -24,18 +23,11 @@ module.exports = function (eleventyConfig) {
|
|
|
24
23
|
}
|
|
25
24
|
}
|
|
26
25
|
|
|
27
|
-
const md = markdownIt({ html: true });
|
|
28
|
-
|
|
29
26
|
eleventyConfig.addShortcode('mdFile', function(filePath) {
|
|
30
27
|
const content = fs.readFileSync(filePath, 'utf8');
|
|
31
28
|
return md.render(content);
|
|
32
29
|
});
|
|
33
30
|
|
|
34
|
-
eleventyConfig.addPassthroughCopy({
|
|
35
|
-
"node_modules/github-markdown-css/github-markdown-dark.css": "css/github-markdown-dark.css",
|
|
36
|
-
"node_modules/github-markdown-css/github-markdown-light.css": "css/github-markdown-light.css",
|
|
37
|
-
});
|
|
38
|
-
|
|
39
31
|
eleventyConfig.on("eleventy.before", () => {
|
|
40
32
|
copyRecursiveSync("src/backend", `${OUTPUT_DIR}/backend`);
|
|
41
33
|
});
|
|
@@ -43,6 +35,7 @@ module.exports = function (eleventyConfig) {
|
|
|
43
35
|
eleventyConfig.addPassthroughCopy("src/frontend/.htaccess");
|
|
44
36
|
eleventyConfig.addPassthroughCopy("src/frontend/web.config");
|
|
45
37
|
eleventyConfig.addPassthroughCopy("src/frontend/assets");
|
|
38
|
+
eleventyConfig.addPassthroughCopy("src/frontend/data");
|
|
46
39
|
eleventyConfig.addPassthroughCopy("src/frontend/robots.txt");
|
|
47
40
|
|
|
48
41
|
eleventyConfig.addPassthroughCopy({
|
|
@@ -76,7 +69,7 @@ module.exports = function (eleventyConfig) {
|
|
|
76
69
|
});
|
|
77
70
|
|
|
78
71
|
eleventyConfig.addWatchTarget("./src/frontend/scss");
|
|
79
|
-
eleventyConfig.addWatchTarget("./src/frontend/
|
|
72
|
+
eleventyConfig.addWatchTarget("./src/frontend/routes");
|
|
80
73
|
eleventyConfig.addWatchTarget("./src/frontend/data");
|
|
81
74
|
|
|
82
75
|
eleventyConfig.setServerOptions({
|
package/CHANGELOG.md
CHANGED
|
@@ -5,58 +5,36 @@ All notable changes to Nibula are documented here.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
-
## [1.
|
|
9
|
-
|
|
10
|
-
### Changed
|
|
11
|
-
- **The update check no longer runs on every command.** Previously every
|
|
12
|
-
invocation of `nib` (and the `nbl` / `nibula` aliases) contacted the npm
|
|
13
|
-
registry before doing anything, adding up to 2.5s of latency to `nib run`,
|
|
14
|
-
`nib build`, `nib cli` and `nib clean`. The check now runs only for `nib new`
|
|
15
|
-
and `nib update`; all other commands work entirely offline.
|
|
16
|
-
- **`nib new` now completes the update automatically.** When a newer version is
|
|
17
|
-
available and you accept the prompt, Nibula installs it and immediately
|
|
18
|
-
re-runs the scaffolding with the new version, instead of asking you to type
|
|
19
|
-
`nib new <project-name>` a second time.
|
|
20
|
-
- **New projects are scaffolded at version `0.0.0`** instead of `1.0.0`, so a
|
|
21
|
-
freshly created site no longer claims a stable public release. Bump it
|
|
22
|
-
yourself as the project grows, and reach `1.0.0` when you go to production.
|
|
23
|
-
- **Framework SCSS imports are now short and readable.** The framework modules
|
|
24
|
-
in `src/frontend/scss/modules/frameworks/` used a five-level relative path
|
|
25
|
-
back to `node_modules`; they now import directly by package name, e.g.
|
|
26
|
-
`@import "bootstrap/scss/card";`. This matches what the styling docs already
|
|
27
|
-
showed, and makes commenting modules out far less error-prone.
|
|
28
|
-
- `nib help` no longer appends an "a newer version is available" line, since it
|
|
29
|
-
no longer performs the check.
|
|
8
|
+
## [1.2.0] - 2026-07-23
|
|
30
9
|
|
|
31
10
|
### Added
|
|
32
|
-
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
- `--load-path=node_modules` on the repository's own `build:css` and `serve:css`
|
|
36
|
-
scripts, so the short framework imports resolve. Generated projects already
|
|
37
|
-
carried this flag.
|
|
11
|
+
- **Full favicon set**: `favicon.svg`, `favicon-32.png` and `apple-touch-icon.png`
|
|
12
|
+
(180×180, opaque) in `assets/brand/`. iOS home-screen icons no longer fall back
|
|
13
|
+
to a screenshot of the page.
|
|
38
14
|
|
|
39
|
-
###
|
|
40
|
-
-
|
|
41
|
-
`
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
15
|
+
### Changed
|
|
16
|
+
- **`data_bs_theme` renamed to `theme`** in `site.json`. It still drives
|
|
17
|
+
`data-bs-theme` on the `<html>` tag; the shorter name keeps the config readable
|
|
18
|
+
and independent from the framework naming.
|
|
19
|
+
- **`theme_color` is now a single value** instead of a `light`/`dark` pair. The
|
|
20
|
+
theme is fixed per build, so two per-scheme colors could contradict the
|
|
21
|
+
rendered page.
|
|
22
|
+
- **Favicon paths are hardcoded in `base.njk`.** The `favicon` key was removed
|
|
23
|
+
from `site.json`: it only ever covered one of the three tags, which was more
|
|
24
|
+
confusing than helpful. Replace the files in `assets/brand/` instead.
|
|
25
|
+
- `_routes/` renamed to `routes/` — it holds entry points, not internals.
|
|
49
26
|
|
|
50
|
-
###
|
|
51
|
-
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
-
|
|
56
|
-
|
|
57
|
-
-
|
|
58
|
-
|
|
59
|
-
|
|
27
|
+
### Removed
|
|
28
|
+
- **`mdFile` shortcode** and the `markdown-it` dependency.
|
|
29
|
+
- **`github-markdown-css`** and its two passthrough copies.
|
|
30
|
+
|
|
31
|
+
### Migration
|
|
32
|
+
- In `site.json`: rename `data_bs_theme` to `theme`, flatten `theme_color` to a
|
|
33
|
+
single string, drop `favicon`.
|
|
34
|
+
- Place `favicon.svg`, `favicon-32.png` and `apple-touch-icon.png` in
|
|
35
|
+
`src/frontend/assets/brand/`.
|
|
36
|
+
- If you used `{% mdFile %}`, render the Markdown ahead of time or add
|
|
37
|
+
`markdown-it` back to your own project.
|
|
60
38
|
|
|
61
39
|
## [1.1.0] - 2026-07-21
|
|
62
40
|
|
|
@@ -94,4 +72,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
94
72
|
### Notes
|
|
95
73
|
- Both backends are always scaffolded, so you can switch later without
|
|
96
74
|
re-creating the project. The PHP front controller only serves `.php` endpoint
|
|
97
|
-
files and the Node one only `.js`, so they coexist without conflict.
|
|
75
|
+
files and the Node one only `.js`, so they coexist without conflict.
|
|
76
|
+
|
|
77
|
+
## [1.0.2]
|
|
78
|
+
|
|
79
|
+
- Previous release (PHP backend only).
|
|
80
|
+
|
|
81
|
+
[1.1.0]: https://github.com/Rhaastrake/Nibula/releases/tag/v1.1.0
|
|
82
|
+
[1.0.2]: https://github.com/Rhaastrake/Nibula/releases/tag/v1.0.2
|
package/README.md
CHANGED
|
@@ -21,7 +21,7 @@ Building a website from scratch involves a lot of moving parts: templating, buil
|
|
|
21
21
|
- 🪶 **Lightweight by default** — SCSS frameworks can be filtered so you ship only what you actually use
|
|
22
22
|
- 🌍 **Open source** — free to use, free to modify, free to share
|
|
23
23
|
|
|
24
|
-

|
|
25
25
|

|
|
26
26
|

|
|
27
27
|
|
|
@@ -44,9 +44,13 @@ Nibula ships with a clean, opinionated layout so beginners are never lost. But i
|
|
|
44
44
|
|
|
45
45
|
## Prerequisites
|
|
46
46
|
|
|
47
|
+
### Required
|
|
48
|
+
|
|
47
49
|
* **Node.js**: v18.0.0 or higher — **always required** (the Nibula CLI, the build, and the optional Node backend all run on Node)
|
|
48
50
|
* **Composer**: **only required if you choose the PHP backend**, to install its PHP dependencies. If you pick the **Node** backend, Composer is never used — you can skip installing it entirely.
|
|
49
|
-
|
|
51
|
+
### Recomended
|
|
52
|
+
* *Suggested:* **Better Nunjucks** VS Code extension by Ed Heltzel
|
|
53
|
+
* *Suggester:* **Material Icon Theme** VS Code extension by Philipp Kief
|
|
50
54
|
|
|
51
55
|
## Installation
|
|
52
56
|
|
|
@@ -88,7 +92,7 @@ Run these from anywhere inside a project (except `nib new`, which you run wherev
|
|
|
88
92
|
| `nib clean` | Remove the output directory |
|
|
89
93
|
| `nib update` | Update the CLI to the latest version |
|
|
90
94
|
|
|
91
|
-
Before scaffolding, nib new checks the npm registry for a newer version and offers to update first
|
|
95
|
+
Before scaffolding, `nib new` checks the npm registry for a newer version and offers to update first (via `nib update`). If the registry is unreachable, the check is skipped and creation proceeds normally.
|
|
92
96
|
|
|
93
97
|
## Managing pages
|
|
94
98
|
|
package/bin/create.js
CHANGED
|
@@ -5,7 +5,7 @@ const path = require('path');
|
|
|
5
5
|
const readline = require('readline');
|
|
6
6
|
const { writeSync } = require('fs');
|
|
7
7
|
const { spawnSync } = require('child_process');
|
|
8
|
-
const { color } = require('../
|
|
8
|
+
const { color } = require('../tools/modules/constants');
|
|
9
9
|
|
|
10
10
|
// ── PATHS ────────────────────────────────────────────────────────────────────
|
|
11
11
|
|
|
@@ -75,7 +75,7 @@ const FRONTEND_EXCLUDE = {
|
|
|
75
75
|
};
|
|
76
76
|
|
|
77
77
|
const CREATE_DIRS = [
|
|
78
|
-
'src/frontend/
|
|
78
|
+
'src/frontend/routes',
|
|
79
79
|
];
|
|
80
80
|
|
|
81
81
|
// Backend files that belong to exactly one backend, matched by basename.
|
|
@@ -148,7 +148,7 @@ src/backend/cache/
|
|
|
148
148
|
|
|
149
149
|
const PROJECT_PACKAGE = {
|
|
150
150
|
name: path.basename(targetDir),
|
|
151
|
-
version: '
|
|
151
|
+
version: '1.0.0',
|
|
152
152
|
private: true,
|
|
153
153
|
outputDir: 'out',
|
|
154
154
|
"scripts": {
|
|
@@ -170,7 +170,6 @@ const PROJECT_PACKAGE = {
|
|
|
170
170
|
'bootstrap-icons': '^1.13.1',
|
|
171
171
|
'bulma': '^1.0.4',
|
|
172
172
|
'foundation-sites': '^6.9.0',
|
|
173
|
-
'github-markdown-css': '^5.9.0',
|
|
174
173
|
'glob': '^13.0.6',
|
|
175
174
|
'uikit': '^3.25.13',
|
|
176
175
|
},
|
package/bin/nibula.js
CHANGED
|
@@ -5,20 +5,19 @@ const path = require('path');
|
|
|
5
5
|
const https = require('https');
|
|
6
6
|
const readline = require('readline');
|
|
7
7
|
const { spawnSync } = require('child_process');
|
|
8
|
-
const { findProjectRoot, color, NOT_INSIDE_PROJECT_MESSAGE } = require('../
|
|
8
|
+
const { findProjectRoot, color, NOT_INSIDE_PROJECT_MESSAGE } = require('../tools/modules/constants');
|
|
9
9
|
|
|
10
10
|
const pkg = require('../package.json');
|
|
11
11
|
|
|
12
12
|
const [, , cmd, ...rest] = process.argv;
|
|
13
13
|
|
|
14
14
|
const CREATE = path.join(__dirname, 'create.js');
|
|
15
|
-
const ASSISTANT = path.join(__dirname, '..', '
|
|
16
|
-
const BUILDJS = path.join(__dirname, '..', '
|
|
17
|
-
const CLEAN = path.join(__dirname, '..', '
|
|
15
|
+
const ASSISTANT = path.join(__dirname, '..', 'tools', 'assistant.js');
|
|
16
|
+
const BUILDJS = path.join(__dirname, '..', 'tools', 'buildJs.js');
|
|
17
|
+
const CLEAN = path.join(__dirname, '..', 'tools', 'cleanOutput.js');
|
|
18
18
|
|
|
19
19
|
const REGISTRY = 'https://registry.npmjs.org/nibula/latest';
|
|
20
20
|
const CHECK_TIMEOUT = 2500;
|
|
21
|
-
const SKIP_FLAG = '--skip-update-check';
|
|
22
21
|
|
|
23
22
|
function run(script, args) {
|
|
24
23
|
const res = spawnSync('node', [script, ...args], {
|
|
@@ -140,32 +139,6 @@ function updateGlobal(version) {
|
|
|
140
139
|
return res.status ?? 0;
|
|
141
140
|
}
|
|
142
141
|
|
|
143
|
-
function globalNibulaPath() {
|
|
144
|
-
const res = spawnSync('npm', ['root', '-g'], {
|
|
145
|
-
encoding: 'utf8',
|
|
146
|
-
shell: process.platform === 'win32',
|
|
147
|
-
});
|
|
148
|
-
if (res.status !== 0 || !res.stdout) return null;
|
|
149
|
-
const candidate = path.join(res.stdout.trim(), 'nibula', 'bin', 'nibula.js');
|
|
150
|
-
return fs.existsSync(candidate) ? candidate : null;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
// Riesegue il comando con la versione appena installata: questo processo ha
|
|
154
|
-
// ancora in memoria il codice vecchio, quindi non può scaffoldare da solo.
|
|
155
|
-
function reexecAfterUpdate(args) {
|
|
156
|
-
const target = globalNibulaPath();
|
|
157
|
-
if (!target) {
|
|
158
|
-
console.error(`${color.red}Could not locate the updated Nibula installation.${color.reset}`);
|
|
159
|
-
console.error(`Run "nib new ${args[1]}" again to continue.`);
|
|
160
|
-
return 1;
|
|
161
|
-
}
|
|
162
|
-
const res = spawnSync(process.execPath, [target, ...args, SKIP_FLAG], {
|
|
163
|
-
stdio: 'inherit',
|
|
164
|
-
cwd: process.cwd(),
|
|
165
|
-
});
|
|
166
|
-
return res.status ?? 0;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
142
|
function findExistingProject(baseDir, projectName) {
|
|
170
143
|
let entries;
|
|
171
144
|
try {
|
|
@@ -203,37 +176,33 @@ ${color.yellow}nib update${color.reset} Update to the latest versi
|
|
|
203
176
|
}
|
|
204
177
|
|
|
205
178
|
async function main() {
|
|
179
|
+
const info = await checkVersion();
|
|
206
180
|
switch (cmd) {
|
|
207
181
|
case 'new': {
|
|
208
|
-
|
|
209
|
-
const skipCheck = rest.includes(SKIP_FLAG);
|
|
210
|
-
|
|
211
|
-
if (!args[0]) {
|
|
182
|
+
if (!rest[0]) {
|
|
212
183
|
console.error('Missing project name. Usage: nib new <project-name>');
|
|
213
184
|
process.exit(1);
|
|
214
185
|
}
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
const code = updateGlobal(info.latest);
|
|
224
|
-
if (code !== 0) process.exit(code);
|
|
225
|
-
console.log(`\n${color.green}Updated.${color.reset} Continuing with the new version...\n`);
|
|
226
|
-
process.exit(reexecAfterUpdate(['new', args[0]]));
|
|
186
|
+
if (info.behind) {
|
|
187
|
+
console.log(`\nA newer version of Nibula is available: ${info.current} → ${info.latest}`);
|
|
188
|
+
if (process.stdin.isTTY) {
|
|
189
|
+
const answer = await ask('Update before creating the project? [Y/n] ');
|
|
190
|
+
if (answer === '' || answer === 'y' || answer === 'yes') {
|
|
191
|
+
const code = updateGlobal(info.latest);
|
|
192
|
+
if (code === 0) {
|
|
193
|
+
console.log(`\nUpdated. Re-run "nib new ${rest[0]}" to scaffold with the latest version.`);
|
|
227
194
|
}
|
|
228
|
-
|
|
229
|
-
console.log('Run "nib update" to update.\n');
|
|
195
|
+
process.exit(code);
|
|
230
196
|
}
|
|
197
|
+
} else {
|
|
198
|
+
console.log('Run "nib update" to update.\n');
|
|
231
199
|
}
|
|
232
200
|
}
|
|
233
201
|
|
|
234
|
-
|
|
202
|
+
// Controllo progetto già esistente con lo stesso "name" nel package.json
|
|
203
|
+
const existing = findExistingProject(process.cwd(), rest[0]);
|
|
235
204
|
if (existing) {
|
|
236
|
-
console.log(`\n${color.yellow}A project named "${
|
|
205
|
+
console.log(`\n${color.yellow}A project named "${rest[0]}" already exists:${color.reset} ${existing}`);
|
|
237
206
|
let overwrite = false;
|
|
238
207
|
if (process.stdin.isTTY) {
|
|
239
208
|
const answer = await ask('Do you want to overwrite it? [y/N] ');
|
|
@@ -245,6 +214,7 @@ async function main() {
|
|
|
245
214
|
console.log('Stopped creating the new project');
|
|
246
215
|
process.exit(0);
|
|
247
216
|
}
|
|
217
|
+
// Sovrascrittura: cancello completamente la cartella preesistente
|
|
248
218
|
try {
|
|
249
219
|
fs.rmSync(existing, { recursive: true, force: true });
|
|
250
220
|
console.log(`${color.green}Removed existing project.${color.reset}`);
|
|
@@ -254,7 +224,7 @@ async function main() {
|
|
|
254
224
|
}
|
|
255
225
|
}
|
|
256
226
|
|
|
257
|
-
run(CREATE, [
|
|
227
|
+
run(CREATE, [rest[0]]);
|
|
258
228
|
break;
|
|
259
229
|
}
|
|
260
230
|
case 'cli': {
|
|
@@ -283,7 +253,6 @@ async function main() {
|
|
|
283
253
|
break;
|
|
284
254
|
}
|
|
285
255
|
case 'update': {
|
|
286
|
-
const info = await checkVersion();
|
|
287
256
|
if (info.latest !== null && !info.behind) {
|
|
288
257
|
console.log(`Already on the latest version (${info.current}).`);
|
|
289
258
|
process.exit(0);
|
|
@@ -296,12 +265,15 @@ async function main() {
|
|
|
296
265
|
case '--help':
|
|
297
266
|
case 'h':
|
|
298
267
|
case '-h': {
|
|
299
|
-
usage(
|
|
268
|
+
usage(info.current);
|
|
269
|
+
if (info.behind) {
|
|
270
|
+
console.log(`A newer version is available: ${info.current} → ${info.latest}. Run "nib update".`);
|
|
271
|
+
}
|
|
300
272
|
break;
|
|
301
273
|
}
|
|
302
274
|
default:
|
|
303
275
|
console.error(`${color.red}\nUnknown command:${color.reset} ${cmd}`);
|
|
304
|
-
usage(
|
|
276
|
+
usage(info.current);
|
|
305
277
|
process.exit(1);
|
|
306
278
|
}
|
|
307
279
|
}
|
package/docs/Assistant CLI.md
CHANGED
|
@@ -31,7 +31,7 @@ For a page named `my-page`, the following files are created:
|
|
|
31
31
|
|---|---|
|
|
32
32
|
| `src/frontend/scss/pages/myPage.scss` | SCSS entry point |
|
|
33
33
|
| `src/frontend/js/pages/myPage.js` | JS entry point |
|
|
34
|
-
| `src/frontend/
|
|
34
|
+
| `src/frontend/routes/my-page.njk` | Nunjucks template |
|
|
35
35
|
|
|
36
36
|
It also adds an `elif` block in `page-components.njk` and a stub entry in `site.json`:
|
|
37
37
|
|
package/docs/Components.md
CHANGED
|
@@ -43,18 +43,6 @@ Add a new `{% elif %}` block for each page, listing its components in order. If
|
|
|
43
43
|
|
|
44
44
|
> ⚠️ If you move or delete a component, always update `page-components.njk` or the site will break
|
|
45
45
|
|
|
46
|
-
### Using Markdown files in components
|
|
47
|
-
|
|
48
|
-
You can also render a `.md` file directly inside any `.njk` component using the `mdFile` shortcode:
|
|
49
|
-
|
|
50
|
-
```njk
|
|
51
|
-
{% mdFile "docs/your-file.md" %}
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
The path is relative to the project root (where `.eleventy.js` lives).
|
|
55
|
-
|
|
56
|
-
> ⚠️ The file is read at build time — changes to the `.md` file trigger a rebuild in watch mode.
|
|
57
|
-
|
|
58
46
|
## Nest components
|
|
59
47
|
|
|
60
48
|
A component can include other components. This is useful for breaking complex sections into smaller, reusable pieces.
|
|
@@ -77,11 +65,12 @@ Header and footer live in `src/frontend/components/global/` and are automaticall
|
|
|
77
65
|
|
|
78
66
|
All values defined in `src/frontend/data/site.json` are globally available in every component via `{{ site.* }}`
|
|
79
67
|
|
|
80
|
-
### site.json <small>(`src/data/`)</small>
|
|
68
|
+
### site.json <small>(`src/frontend/data/`)</small>
|
|
81
69
|
```json
|
|
82
70
|
{
|
|
83
71
|
"title": "My Site",
|
|
84
|
-
"
|
|
72
|
+
"theme": "dark",
|
|
73
|
+
"logo": "/assets/brand/logo.svg",
|
|
85
74
|
"legal": {
|
|
86
75
|
"privacy": "/privacy"
|
|
87
76
|
}
|
package/docs/Creating pages.md
CHANGED
|
@@ -9,7 +9,7 @@ For a page named `my-page`:
|
|
|
9
9
|
|
|
10
10
|
| File | Purpose |
|
|
11
11
|
|---|---|
|
|
12
|
-
| `src/frontend/
|
|
12
|
+
| `src/frontend/routes/my-page.njk` | Template with front matter |
|
|
13
13
|
| `src/frontend/scss/pages/myPage.scss` | Imports framework + modules |
|
|
14
14
|
| `src/frontend/js/pages/myPage.js` | Imports JS modules |
|
|
15
15
|
|
|
@@ -31,7 +31,7 @@ The URL is the kebab-case name (`/my-page/`). The `title` in the front matter is
|
|
|
31
31
|
|
|
32
32
|
## Subpages (nested URLs)
|
|
33
33
|
|
|
34
|
-
To create a URL like `domain.it/about/team`, edit the `permalink` in `src/frontend/
|
|
34
|
+
To create a URL like `domain.it/about/team`, edit the `permalink` in `src/frontend/routes/team.njk` and add the parent segment before the final slash:
|
|
35
35
|
|
|
36
36
|
```njk
|
|
37
37
|
---
|
|
@@ -45,9 +45,9 @@ The parent path (`about`) does **not** need to exist as a real page — it's jus
|
|
|
45
45
|
|
|
46
46
|
| Goal URL | permalink value | File |
|
|
47
47
|
|---|---|---|
|
|
48
|
-
| `/team/` | `/team/` | `
|
|
49
|
-
| `/about/team/` | `/about/team/` | `
|
|
50
|
-
| `/company/about/team/` | `/company/about/team/` | `
|
|
48
|
+
| `/team/` | `/team/` | `routes/team.njk` |
|
|
49
|
+
| `/about/team/` | `/about/team/` | `routes/team.njk` |
|
|
50
|
+
| `/company/about/team/` | `/company/about/team/` | `routes/team.njk` |
|
|
51
51
|
|
|
52
52
|
## SEO
|
|
53
53
|
|
package/docs/Head and SEO.md
CHANGED
|
@@ -14,12 +14,7 @@ Global settings live in `src/frontend/data/site.json` and are available everywhe
|
|
|
14
14
|
"url": "https://yoursite.com",
|
|
15
15
|
"lang": "en",
|
|
16
16
|
"author": "Name and surname",
|
|
17
|
-
"
|
|
18
|
-
"theme_color": {
|
|
19
|
-
"light": "#ffffff",
|
|
20
|
-
"dark": "#0d1117"
|
|
21
|
-
},
|
|
22
|
-
"favicon": "/assets/brand/favicon.svg",
|
|
17
|
+
"theme": "dark",
|
|
23
18
|
"logo": "/assets/brand/logo.svg",
|
|
24
19
|
"legal": {
|
|
25
20
|
"privacy": "",
|
|
@@ -43,9 +38,8 @@ Global settings live in `src/frontend/data/site.json` and are available everywhe
|
|
|
43
38
|
| `domain` / `url` | Canonical URLs, `og:url`, JSON-LD |
|
|
44
39
|
| `lang` | HTML `lang` attribute |
|
|
45
40
|
| `author` | Meta author and JSON-LD author |
|
|
46
|
-
| `
|
|
47
|
-
| `theme_color` | Browser UI / PWA color
|
|
48
|
-
| `favicon` | Path to the favicon |
|
|
41
|
+
| `theme` | Site color scheme (`light` / `dark`) — sets `data-theme`, `data-bs-theme` and `color-scheme` |
|
|
42
|
+
| `theme_color` | Browser UI / PWA bar color — should match the chosen `theme` |
|
|
49
43
|
| `logo` | Path to the logo, also used as social image |
|
|
50
44
|
| `legal.privacy` / `cookie` / `cookieControls` / `terms` | Legal page URLs |
|
|
51
45
|
| `legal.copyright.year` / `text` | Footer copyright |
|
|
@@ -93,16 +87,44 @@ Global values are defaults, not duplicates. A page value is used when present; o
|
|
|
93
87
|
|
|
94
88
|
`noindex` and `canonical` have no global default: `noindex` defaults to indexable behavior, `canonical` is computed from the URL. They exist per-page only.
|
|
95
89
|
|
|
96
|
-
##
|
|
90
|
+
## Theme
|
|
97
91
|
|
|
98
|
-
|
|
92
|
+
`theme` is a single fixed value that drives the whole site:
|
|
99
93
|
|
|
100
94
|
```njk
|
|
101
|
-
<
|
|
102
|
-
<meta name="
|
|
95
|
+
<html data-theme="{{ site.theme }}" data-bs-theme="{{ site.theme }}">
|
|
96
|
+
<meta name="color-scheme" content="{{ site.theme }}">
|
|
97
|
+
<meta name="theme-color" content="{{ site.theme_color }}">
|
|
103
98
|
```
|
|
104
99
|
|
|
105
|
-
|
|
100
|
+
| Attribute | Purpose |
|
|
101
|
+
|---|---|
|
|
102
|
+
| `data-theme` | Your own hook — target it in SCSS to define theme variables |
|
|
103
|
+
| `data-bs-theme` | Bootstrap's color mode. Ignored (harmless) if you use another framework |
|
|
104
|
+
| `color-scheme` | Standard CSS — makes scrollbars, form controls and autofill follow the theme |
|
|
105
|
+
| `theme-color` | Color of the browser UI bar on mobile |
|
|
106
|
+
|
|
107
|
+
Keep `theme` and `theme_color` consistent: a `dark` theme with a white `theme_color` gives a white browser bar over a dark page.
|
|
108
|
+
|
|
109
|
+
See the SCSS docs for how to hook your variables to `data-theme`.
|
|
110
|
+
|
|
111
|
+
## Favicon
|
|
112
|
+
|
|
113
|
+
The three favicon tags are hardcoded in `base.njk`. To change the icons, replace the files in `src/frontend/assets/brand/` keeping the same names:
|
|
114
|
+
|
|
115
|
+
```html
|
|
116
|
+
<link rel="icon" type="image/svg+xml" href="/assets/brand/favicon.svg">
|
|
117
|
+
<link rel="icon" type="image/png" sizes="32x32" href="/assets/brand/favicon-32.png">
|
|
118
|
+
<link rel="apple-touch-icon" sizes="180x180" href="/assets/brand/apple-touch-icon.png">
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
| File | Purpose |
|
|
122
|
+
|---|---|
|
|
123
|
+
| `favicon.svg` | Modern browsers, scales to any size |
|
|
124
|
+
| `favicon-32.png` | Fallback for older browsers and some crawlers |
|
|
125
|
+
| `apple-touch-icon.png` | iOS home screen icon — 180×180, must be opaque (iOS renders transparency as black) |
|
|
126
|
+
|
|
127
|
+
> ⚠️ Without `apple-touch-icon.png`, iOS uses a screenshot of the page as the home screen icon.
|
|
106
128
|
|
|
107
129
|
## AI & SEO bots
|
|
108
130
|
|
package/docs/Javascript.md
CHANGED
|
@@ -7,6 +7,7 @@ Each page has its own SCSS entry point in `src/frontend/scss/pages/`
|
|
|
7
7
|
It must contain `_root.scss` + other modules like `_global.scss` or any other one that you need and its own specific css rules
|
|
8
8
|
|
|
9
9
|
`_root.scss` uses `@use` to enable namespaced access (`root.$var`); other modules use `@import` as they don't expose variables.
|
|
10
|
+
|
|
10
11
|
### examplePage.scss <small>(`src/frontend/scss/pages/`)</small>
|
|
11
12
|
```scss
|
|
12
13
|
//==========================
|
|
@@ -39,7 +40,9 @@ header {
|
|
|
39
40
|
height: root.$header-height;
|
|
40
41
|
}
|
|
41
42
|
```
|
|
43
|
+
|
|
42
44
|
## Scss modules
|
|
45
|
+
|
|
43
46
|
You can create your custom css modules by creating a new `.scss` file in `src/frontend/scss/modules/` (the name of the file must start with `_`)
|
|
44
47
|
|
|
45
48
|
You can create subfolders if you want to refactor the structure, but be sure to update the relative paths in the pages that import them
|
|
@@ -70,7 +73,7 @@ body {
|
|
|
70
73
|
|---|---|
|
|
71
74
|
| `_root.scss` | Global variables (colors, spacing) |
|
|
72
75
|
| `_global.scss` | Site-wide base rules and frameworks |
|
|
73
|
-
| `_typography.scss` | Font rules
|
|
76
|
+
| `_typography.scss` | Font rules |
|
|
74
77
|
| `_header.scss` | Header styles |
|
|
75
78
|
| `_footer.scss` | Footer styles |
|
|
76
79
|
| `_mobile.scss` | Media query rules |
|
|
@@ -84,7 +87,6 @@ You can choose one or none of them (more than 1 works, but you may get in variou
|
|
|
84
87
|
|
|
85
88
|
To enable/disable them you have to modify 3 files around the project by just commenting them
|
|
86
89
|
|
|
87
|
-
|
|
88
90
|
### 1. _global.scss <small>(`src/frontend/scss/modules/`)</small>
|
|
89
91
|
```scss
|
|
90
92
|
@import "../modules/frameworks/bootstrap";
|
|
@@ -109,7 +111,7 @@ To enable/disable them you have to modify 3 files around the project by just com
|
|
|
109
111
|
{# Bulma — no JS needed #}
|
|
110
112
|
```
|
|
111
113
|
|
|
112
|
-
### 3.
|
|
114
|
+
### 3. eleventy.config.js
|
|
113
115
|
|
|
114
116
|
```javascript
|
|
115
117
|
eleventyConfig.addPassthroughCopy({
|
|
@@ -128,8 +130,12 @@ eleventyConfig.addPassthroughCopy({
|
|
|
128
130
|
});
|
|
129
131
|
```
|
|
130
132
|
|
|
133
|
+
> ⚠️ Changes to `eleventy.config.js` are not picked up while the dev server is running — restart it.
|
|
134
|
+
|
|
131
135
|
### Reducing bundle size
|
|
136
|
+
|
|
132
137
|
To reduce the bundle size, open the corresponding framework file (`src/frontend/scss/modules/frameworks/`) and comment out any modules you don't need
|
|
138
|
+
|
|
133
139
|
```scss
|
|
134
140
|
@import "bootstrap/scss/card"; // Cards
|
|
135
141
|
@import "bootstrap/scss/carousel"; // Carousel
|