nibula 1.6.0 → 1.6.1
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 +81 -81
- package/CHANGELOG.md +384 -377
- package/LICENSE +169 -169
- package/NOTICE +4 -4
- package/README.md +110 -110
- package/bin/create.js +505 -505
- package/bin/delegate.js +57 -57
- package/bin/nibula.js +302 -302
- package/docs/Assistant CLI.md +65 -65
- package/docs/Backend.md +201 -201
- package/docs/Components.md +140 -140
- package/docs/Creating pages.md +69 -69
- package/docs/Deploy.md +210 -210
- package/docs/Head and SEO.md +139 -139
- package/docs/Javascript.md +126 -126
- package/docs/Styling with SCSS.md +139 -139
- package/nginx.conf +113 -113
- package/package.json +69 -69
- package/src/backend/.htaccess +6 -6
- package/src/backend/_core/composer.json +5 -5
- package/src/backend/_core/composer.lock +492 -492
- package/src/backend/_core/index.js +267 -267
- package/src/backend/_core/index.php +160 -160
- package/src/backend/_core/init.js +52 -52
- package/src/backend/_core/init.php +33 -33
- package/src/backend/_core/modules/RateLimiter.js +58 -58
- package/src/backend/_core/modules/RateLimiter.php +30 -30
- package/src/backend/_core/modules/Response.js +59 -59
- package/src/backend/_core/modules/Response.php +48 -48
- package/src/backend/api/protected/example-protected.js +23 -23
- package/src/backend/api/protected/example-protected.php +16 -16
- package/src/backend/api/public/example-public.js +24 -24
- package/src/backend/api/public/example-public.php +16 -16
- package/src/backend/database/Database.js +46 -46
- package/src/backend/database/Database.php +23 -23
- package/src/backend/example.config.js +37 -37
- package/src/backend/example.config.php +37 -37
- package/src/backend/package.json +17 -17
- package/src/backend/web.config +43 -43
- package/src/frontend/.htaccess +51 -51
- package/src/frontend/404.njk +17 -17
- package/src/frontend/assets/brand/favicon.svg +54 -54
- package/src/frontend/assets/brand/logo.svg +54 -54
- package/src/frontend/components/global/footer.njk +25 -25
- package/src/frontend/components/global/header.njk +6 -6
- package/src/frontend/components/welcome.njk +115 -115
- package/src/frontend/index.njk +8 -8
- package/src/frontend/js/global.js +10 -10
- package/src/frontend/js/modules/exampleModule.js +2 -2
- package/src/frontend/js/pages/404.js +8 -8
- package/src/frontend/js/pages/homepage.js +8 -8
- package/src/frontend/layouts/base.njk +136 -136
- package/src/frontend/layouts/page-components.njk +13 -13
- package/src/frontend/llms.njk +17 -17
- package/src/frontend/robots.njk +7 -7
- package/src/frontend/scss/_global.scss +46 -46
- package/src/frontend/scss/_root.scss +13 -13
- package/src/frontend/scss/modules/_animations.scss +24 -24
- package/src/frontend/scss/modules/_footer.scss +28 -28
- package/src/frontend/scss/modules/_header.scss +26 -26
- package/src/frontend/scss/modules/_mobile.scss +29 -29
- package/src/frontend/scss/modules/_typography.scss +18 -18
- package/src/frontend/scss/modules/frameworks/_bootstrap.scss +109 -109
- package/src/frontend/scss/modules/frameworks/_bulma.scss +108 -108
- package/src/frontend/scss/modules/frameworks/_foundation.scss +137 -137
- package/src/frontend/scss/modules/frameworks/_uikit.scss +109 -109
- package/src/frontend/scss/pages/404.scss +27 -27
- package/src/frontend/scss/pages/homepage.scss +22 -22
- package/src/frontend/sitemap.njk +17 -17
- package/src/frontend/ts/global.ts +11 -11
- package/src/frontend/ts/modules/exampleModule.ts +2 -2
- package/src/frontend/ts/pages/404.ts +8 -8
- package/src/frontend/ts/pages/homepage.ts +8 -8
- package/src/frontend/web.config +51 -51
- package/tools/assistant.js +122 -122
- package/tools/buildJs.js +39 -39
- package/tools/cleanOutput.js +23 -23
- package/tools/cli/prompt.js +40 -40
- package/tools/cli/ui.js +87 -87
- package/tools/config/messages.json +80 -80
- package/tools/config/settings.json +130 -130
- package/tools/lib/colors.js +17 -17
- package/tools/lib/files.js +75 -75
- package/tools/lib/logger.js +22 -22
- package/tools/lib/outputPath.js +141 -141
- package/tools/lib/pageActions.js +146 -146
- package/tools/lib/pageArtifacts.js +46 -46
- package/tools/lib/pageComponents.js +88 -88
- package/tools/lib/pagesData.js +87 -87
- package/tools/lib/paths.js +63 -63
- package/tools/lib/project.js +54 -54
- package/tools/lib/text.js +47 -47
- package/tools/lib/validation.js +40 -40
- package/tools/res/templates/template.js +7 -7
- package/tools/res/templates/template.njk +8 -8
- package/tools/res/templates/template.scss +22 -22
- package/tools/res/templates/template.ts +8 -8
- package/tsconfig.json +24 -24
- package/src/frontend/scss/pages/prova.scss +0 -23
|
@@ -1,116 +1,116 @@
|
|
|
1
|
-
<div class="layout-container layout-my-3">
|
|
2
|
-
<h1>Welcome to <span class="boilerplate-name">Nibula</span></h1>
|
|
3
|
-
<div class="slogan">The boilerplate you need, simplified</div>
|
|
4
|
-
|
|
5
|
-
<div id="content-welcome" class="tab-content active">
|
|
6
|
-
<div style="display: flex; gap: 1rem; flex-wrap: wrap;">
|
|
7
|
-
<a href="https://github.com/rhaastrake/nibula" class="card" target="_blank" rel="noopener noreferrer" style="flex: 1; min-width: 250px;">
|
|
8
|
-
<svg class="card-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
9
|
-
<path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"></path>
|
|
10
|
-
</svg>
|
|
11
|
-
<h3>GitHub repository</h3>
|
|
12
|
-
<p>Explore the project and suggest improvements</p>
|
|
13
|
-
<span class="card-link">Open the repository
|
|
14
|
-
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" style="margin-left:4px;">
|
|
15
|
-
<path stroke-linecap="round" stroke-linejoin="round" d="M14 5l7 7m0 0l-7 7m7-7H3"></path>
|
|
16
|
-
</svg>
|
|
17
|
-
</span>
|
|
18
|
-
</a>
|
|
19
|
-
<a href="https://github.com/rhaastrake/nibula/tree/main/docs" class="card" target="_blank" rel="noopener noreferrer" style="flex: 1; min-width: 250px;">
|
|
20
|
-
<svg class="card-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
21
|
-
<path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"></path>
|
|
22
|
-
<path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"></path>
|
|
23
|
-
</svg>
|
|
24
|
-
<h3>Documentation</h3>
|
|
25
|
-
<p>Everything you need to get started</p>
|
|
26
|
-
<span class="card-link">Go to documentation
|
|
27
|
-
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" style="margin-left:4px;">
|
|
28
|
-
<path stroke-linecap="round" stroke-linejoin="round" d="M14 5l7 7m0 0l-7 7m7-7H3"></path>
|
|
29
|
-
</svg>
|
|
30
|
-
</span>
|
|
31
|
-
</a>
|
|
32
|
-
</div>
|
|
33
|
-
</div>
|
|
34
|
-
<div class="prova">{{ test.prova }}</div>
|
|
35
|
-
<style>
|
|
36
|
-
.layout-container {
|
|
37
|
-
width: 100%;
|
|
38
|
-
max-width: 1140px;
|
|
39
|
-
margin-right: auto;
|
|
40
|
-
margin-left: auto;
|
|
41
|
-
padding-right: 15px;
|
|
42
|
-
padding-left: 15px;
|
|
43
|
-
}
|
|
44
|
-
.layout-my-3 {
|
|
45
|
-
margin-top: 1rem;
|
|
46
|
-
margin-bottom: 1rem;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
h1 {
|
|
50
|
-
text-align: center;
|
|
51
|
-
font-weight: 400;
|
|
52
|
-
.boilerplate-name {
|
|
53
|
-
color: #42b883;
|
|
54
|
-
font-weight: 600;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
.slogan {
|
|
59
|
-
text-align: center;
|
|
60
|
-
color: #4b71a0;
|
|
61
|
-
font-size: 1.5rem;
|
|
62
|
-
margin-bottom: 1rem;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
.card {
|
|
66
|
-
background: #11474b;
|
|
67
|
-
border: 0.8px solid #1e2d4a;
|
|
68
|
-
border-radius: 10px;
|
|
69
|
-
padding: 18px;
|
|
70
|
-
display: flex;
|
|
71
|
-
flex-direction: column;
|
|
72
|
-
gap: 0.75rem;
|
|
73
|
-
margin-top: 1rem;
|
|
74
|
-
margin-bottom: 1rem;
|
|
75
|
-
transition: border-color 0.2s, transform 0.15s;
|
|
76
|
-
text-decoration: none;
|
|
77
|
-
h3 {
|
|
78
|
-
font-size: 1.5rem;
|
|
79
|
-
font-weight: 600;
|
|
80
|
-
color: #cbd5e1;
|
|
81
|
-
letter-spacing: 0.01em;
|
|
82
|
-
margin: 0;
|
|
83
|
-
}
|
|
84
|
-
p {
|
|
85
|
-
font-size: 1rem;
|
|
86
|
-
color: #5d8dc7;
|
|
87
|
-
line-height: 1.6;
|
|
88
|
-
margin: 0;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
.card:hover {
|
|
93
|
-
border-color: #42b883;
|
|
94
|
-
transform: translateY(-2px);
|
|
95
|
-
.card-link {
|
|
96
|
-
opacity: 1;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
.card-icon {
|
|
101
|
-
width: 2rem;
|
|
102
|
-
height: 2rem;
|
|
103
|
-
color: #42b883;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
.card-link {
|
|
107
|
-
display: flex;
|
|
108
|
-
align-items: center;
|
|
109
|
-
gap: 4px;
|
|
110
|
-
font-size: 1rem;
|
|
111
|
-
color: #42b883;
|
|
112
|
-
opacity: 0.8;
|
|
113
|
-
transition: opacity 0.15s;
|
|
114
|
-
margin-top: auto;
|
|
115
|
-
}
|
|
1
|
+
<div class="layout-container layout-my-3">
|
|
2
|
+
<h1>Welcome to <span class="boilerplate-name">Nibula</span></h1>
|
|
3
|
+
<div class="slogan">The boilerplate you need, simplified</div>
|
|
4
|
+
|
|
5
|
+
<div id="content-welcome" class="tab-content active">
|
|
6
|
+
<div style="display: flex; gap: 1rem; flex-wrap: wrap;">
|
|
7
|
+
<a href="https://github.com/rhaastrake/nibula" class="card" target="_blank" rel="noopener noreferrer" style="flex: 1; min-width: 250px;">
|
|
8
|
+
<svg class="card-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
9
|
+
<path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"></path>
|
|
10
|
+
</svg>
|
|
11
|
+
<h3>GitHub repository</h3>
|
|
12
|
+
<p>Explore the project and suggest improvements</p>
|
|
13
|
+
<span class="card-link">Open the repository
|
|
14
|
+
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" style="margin-left:4px;">
|
|
15
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M14 5l7 7m0 0l-7 7m7-7H3"></path>
|
|
16
|
+
</svg>
|
|
17
|
+
</span>
|
|
18
|
+
</a>
|
|
19
|
+
<a href="https://github.com/rhaastrake/nibula/tree/main/docs" class="card" target="_blank" rel="noopener noreferrer" style="flex: 1; min-width: 250px;">
|
|
20
|
+
<svg class="card-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
|
21
|
+
<path d="M2 3h6a4 4 0 0 1 4 4v14a3 3 0 0 0-3-3H2z"></path>
|
|
22
|
+
<path d="M22 3h-6a4 4 0 0 0-4 4v14a3 3 0 0 1 3-3h7z"></path>
|
|
23
|
+
</svg>
|
|
24
|
+
<h3>Documentation</h3>
|
|
25
|
+
<p>Everything you need to get started</p>
|
|
26
|
+
<span class="card-link">Go to documentation
|
|
27
|
+
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" style="margin-left:4px;">
|
|
28
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M14 5l7 7m0 0l-7 7m7-7H3"></path>
|
|
29
|
+
</svg>
|
|
30
|
+
</span>
|
|
31
|
+
</a>
|
|
32
|
+
</div>
|
|
33
|
+
</div>
|
|
34
|
+
<div class="prova">{{ test.prova }}</div>
|
|
35
|
+
<style>
|
|
36
|
+
.layout-container {
|
|
37
|
+
width: 100%;
|
|
38
|
+
max-width: 1140px;
|
|
39
|
+
margin-right: auto;
|
|
40
|
+
margin-left: auto;
|
|
41
|
+
padding-right: 15px;
|
|
42
|
+
padding-left: 15px;
|
|
43
|
+
}
|
|
44
|
+
.layout-my-3 {
|
|
45
|
+
margin-top: 1rem;
|
|
46
|
+
margin-bottom: 1rem;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
h1 {
|
|
50
|
+
text-align: center;
|
|
51
|
+
font-weight: 400;
|
|
52
|
+
.boilerplate-name {
|
|
53
|
+
color: #42b883;
|
|
54
|
+
font-weight: 600;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.slogan {
|
|
59
|
+
text-align: center;
|
|
60
|
+
color: #4b71a0;
|
|
61
|
+
font-size: 1.5rem;
|
|
62
|
+
margin-bottom: 1rem;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.card {
|
|
66
|
+
background: #11474b;
|
|
67
|
+
border: 0.8px solid #1e2d4a;
|
|
68
|
+
border-radius: 10px;
|
|
69
|
+
padding: 18px;
|
|
70
|
+
display: flex;
|
|
71
|
+
flex-direction: column;
|
|
72
|
+
gap: 0.75rem;
|
|
73
|
+
margin-top: 1rem;
|
|
74
|
+
margin-bottom: 1rem;
|
|
75
|
+
transition: border-color 0.2s, transform 0.15s;
|
|
76
|
+
text-decoration: none;
|
|
77
|
+
h3 {
|
|
78
|
+
font-size: 1.5rem;
|
|
79
|
+
font-weight: 600;
|
|
80
|
+
color: #cbd5e1;
|
|
81
|
+
letter-spacing: 0.01em;
|
|
82
|
+
margin: 0;
|
|
83
|
+
}
|
|
84
|
+
p {
|
|
85
|
+
font-size: 1rem;
|
|
86
|
+
color: #5d8dc7;
|
|
87
|
+
line-height: 1.6;
|
|
88
|
+
margin: 0;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.card:hover {
|
|
93
|
+
border-color: #42b883;
|
|
94
|
+
transform: translateY(-2px);
|
|
95
|
+
.card-link {
|
|
96
|
+
opacity: 1;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.card-icon {
|
|
101
|
+
width: 2rem;
|
|
102
|
+
height: 2rem;
|
|
103
|
+
color: #42b883;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.card-link {
|
|
107
|
+
display: flex;
|
|
108
|
+
align-items: center;
|
|
109
|
+
gap: 4px;
|
|
110
|
+
font-size: 1rem;
|
|
111
|
+
color: #42b883;
|
|
112
|
+
opacity: 0.8;
|
|
113
|
+
transition: opacity 0.15s;
|
|
114
|
+
margin-top: auto;
|
|
115
|
+
}
|
|
116
116
|
</style>
|
package/src/frontend/index.njk
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: homepage
|
|
3
|
-
permalink: /
|
|
4
|
-
layout: page-components.njk
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
<!-- !IMPORTANT -->
|
|
8
|
-
<!-- DO NOT ADD ANYTHING HERE -->
|
|
1
|
+
---
|
|
2
|
+
title: homepage
|
|
3
|
+
permalink: /
|
|
4
|
+
layout: page-components.njk
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
<!-- !IMPORTANT -->
|
|
8
|
+
<!-- DO NOT ADD ANYTHING HERE -->
|
|
9
9
|
<!-- You should create a new component.njk into src/components and include that in layouts/page-components.njk -->
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
// import { initExampleModule } from "./modules/exampleModule.js";
|
|
2
|
-
|
|
3
|
-
function initGlobal() {
|
|
4
|
-
// initExampleModule();
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
// Global logic here
|
|
8
|
-
|
|
9
|
-
// Do not touch
|
|
10
|
-
// This instruction starts global.js itself
|
|
1
|
+
// import { initExampleModule } from "./modules/exampleModule.js";
|
|
2
|
+
|
|
3
|
+
function initGlobal() {
|
|
4
|
+
// initExampleModule();
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
// Global logic here
|
|
8
|
+
|
|
9
|
+
// Do not touch
|
|
10
|
+
// This instruction starts global.js itself
|
|
11
11
|
document.addEventListener('DOMContentLoaded', initGlobal);
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export function initExampleModule() {
|
|
2
|
-
// Module logic here
|
|
1
|
+
export function initExampleModule() {
|
|
2
|
+
// Module logic here
|
|
3
3
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import '../global.js';
|
|
2
|
-
|
|
3
|
-
// import { initExampleModule } from '../modules/exampleModule';
|
|
4
|
-
|
|
5
|
-
document.addEventListener("DOMContentLoaded", () => {
|
|
6
|
-
// initExampleModule();
|
|
7
|
-
});
|
|
8
|
-
|
|
1
|
+
import '../global.js';
|
|
2
|
+
|
|
3
|
+
// import { initExampleModule } from '../modules/exampleModule';
|
|
4
|
+
|
|
5
|
+
document.addEventListener("DOMContentLoaded", () => {
|
|
6
|
+
// initExampleModule();
|
|
7
|
+
});
|
|
8
|
+
|
|
9
9
|
// Page logic here
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import '../global.js';
|
|
2
|
-
|
|
3
|
-
// import { initExampleModule } from '../modules/exampleModule';
|
|
4
|
-
|
|
5
|
-
document.addEventListener("DOMContentLoaded", () => {
|
|
6
|
-
// initExampleModule();
|
|
7
|
-
});
|
|
8
|
-
|
|
1
|
+
import '../global.js';
|
|
2
|
+
|
|
3
|
+
// import { initExampleModule } from '../modules/exampleModule';
|
|
4
|
+
|
|
5
|
+
document.addEventListener("DOMContentLoaded", () => {
|
|
6
|
+
// initExampleModule();
|
|
7
|
+
});
|
|
8
|
+
|
|
9
9
|
// Page logic here
|
|
@@ -1,137 +1,137 @@
|
|
|
1
|
-
<!-- This is the base of every page that you will create -->
|
|
2
|
-
|
|
3
|
-
<!DOCTYPE html>
|
|
4
|
-
<html lang="{{ site.lang or 'en' }}" data-bs-theme="{{ site.theme or 'light' }}">
|
|
5
|
-
|
|
6
|
-
<head>
|
|
7
|
-
<meta charset="UTF-8">
|
|
8
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
9
|
-
<meta name="color-scheme" content="{{ site.theme or 'light' }}">
|
|
10
|
-
|
|
11
|
-
{#╔══════════════════╗
|
|
12
|
-
║ PAGE DATA ║
|
|
13
|
-
╚══════════════════╝#}
|
|
14
|
-
|
|
15
|
-
{% set pageKey = title %}
|
|
16
|
-
{% set pageData = pages[pageKey] %}
|
|
17
|
-
|
|
18
|
-
{#╔══════════════════╗
|
|
19
|
-
║ SEO ║
|
|
20
|
-
╚══════════════════╝#}
|
|
21
|
-
|
|
22
|
-
<link rel="canonical" href="{{ pageData.seo.canonical or (site.url + page.url) }}"/>
|
|
23
|
-
<title>{{ pageData.seo.title or title or site.title }}</title>
|
|
24
|
-
<meta name="description" content="{{ pageData.seo.description or site.description }}">
|
|
25
|
-
<meta name="keywords" content="{{ pageData.seo.keywords or site.keywords }}">
|
|
26
|
-
<meta name="author" content="{{ site.author }}">
|
|
27
|
-
<meta name="theme-color" content="{{ site.theme }}">
|
|
28
|
-
|
|
29
|
-
{% if pageData.seo.noindex %}
|
|
30
|
-
<meta name="robots" content="noindex, follow">
|
|
31
|
-
{% endif %}
|
|
32
|
-
|
|
33
|
-
{# Open Graph #}
|
|
34
|
-
<meta property="og:title" content="{{ pageData.seo.title }}">
|
|
35
|
-
<meta property="og:description" content="{{ pageData.seo.description }}">
|
|
36
|
-
<meta property="og:type" content="website">
|
|
37
|
-
<meta property="og:url" content="{{ site.url }}{{ page.url }}">
|
|
38
|
-
<meta property="og:image" content="{{ site.url }}{{ site.logo }}">
|
|
39
|
-
<meta property="og:site_name" content="{{ site.site_name }}">
|
|
40
|
-
|
|
41
|
-
{# Twitter Card #}
|
|
42
|
-
<meta name="twitter:card" content="summary_large_image">
|
|
43
|
-
<meta name="twitter:title" content="{{ pageData.seo.title }}">
|
|
44
|
-
<meta name="twitter:description" content="{{ pageData.seo.description }}">
|
|
45
|
-
<meta name="twitter:image" content="{{ site.url }}{{ site.logo }}">
|
|
46
|
-
|
|
47
|
-
{#╔══════════════════════════════════════════╗
|
|
48
|
-
║ JSON-LD — Structured data for SEO/AI ║
|
|
49
|
-
╚══════════════════════════════════════════╝#}
|
|
50
|
-
|
|
51
|
-
<script type="application/ld+json">
|
|
52
|
-
{
|
|
53
|
-
"@context": "https://schema.org",
|
|
54
|
-
"@type": "WebPage",
|
|
55
|
-
"name": {{ (pageData.seo.title or title or site.title) | dump }},
|
|
56
|
-
"description": {{ (pageData.seo.description or site.description) | dump }},
|
|
57
|
-
"url": {{ (site.url + page.url) | dump }},
|
|
58
|
-
"author": {
|
|
59
|
-
"@type": "Person",
|
|
60
|
-
"name": {{ site.author | dump }}
|
|
61
|
-
},
|
|
62
|
-
"publisher": {
|
|
63
|
-
"@type": "Organization",
|
|
64
|
-
"name": {{ site.site_name | dump }},
|
|
65
|
-
"logo": {
|
|
66
|
-
"@type": "ImageObject",
|
|
67
|
-
"url": {{ (site.url + site.logo) | dump }}
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
</script>
|
|
72
|
-
|
|
73
|
-
{#╔══════════════════╗
|
|
74
|
-
║ FAVICON ║
|
|
75
|
-
╚══════════════════╝#}
|
|
76
|
-
|
|
77
|
-
<link rel="icon" type="image/svg+xml" href="{{ '/assets/brand/favicon.svg' | url }}">
|
|
78
|
-
<link rel="icon" type="image/png" sizes="32x32" href="{{ '/assets/brand/favicon-32.png' | url }}">
|
|
79
|
-
<link rel="apple-touch-icon" sizes="180x180" href="{{ '/assets/brand/apple-touch-icon.png' | url }}">
|
|
80
|
-
|
|
81
|
-
{#╔══════════════════╗
|
|
82
|
-
║ CSS ║
|
|
83
|
-
╚══════════════════╝#}
|
|
84
|
-
|
|
85
|
-
{# Page CSS #}
|
|
86
|
-
<link rel="stylesheet" href="{{ ('/css/pages/' + title + '.css') | url }}"/>
|
|
87
|
-
|
|
88
|
-
{# Per-page CDN CSS #}
|
|
89
|
-
{% if pageData and pageData.cdn and pageData.cdn.css %}
|
|
90
|
-
{% for link in pageData.cdn.css %}
|
|
91
|
-
<link rel="stylesheet" href="{{ link }}">
|
|
92
|
-
{% endfor %}
|
|
93
|
-
{% endif %}
|
|
94
|
-
|
|
95
|
-
</head>
|
|
96
|
-
|
|
97
|
-
<body>
|
|
98
|
-
|
|
99
|
-
{% include "global/header.njk" %}
|
|
100
|
-
|
|
101
|
-
<main>
|
|
102
|
-
{{ content | safe }}
|
|
103
|
-
</main>
|
|
104
|
-
|
|
105
|
-
{% include "global/footer.njk" %}
|
|
106
|
-
|
|
107
|
-
{#╔══════════════════╗
|
|
108
|
-
║ SCRIPTS ║
|
|
109
|
-
╚══════════════════╝#}
|
|
110
|
-
|
|
111
|
-
{# Framework — uncomment the one you are using #}
|
|
112
|
-
|
|
113
|
-
{# Bootstrap JS #}
|
|
114
|
-
<script src="{{ '/js/bootstrap.bundle.min.js' | url }}" defer></script>
|
|
115
|
-
|
|
116
|
-
{# Foundation JS #}
|
|
117
|
-
{# <script src="{{ '/js/foundation.min.js' | url }}" defer></script> #}
|
|
118
|
-
|
|
119
|
-
{# UIkit JS #}
|
|
120
|
-
{# <script src="{{ '/js/uikit.min.js' | url }}" defer></script> #}
|
|
121
|
-
{# <script src="{{ '/js/uikit-icons.min.js' | url }}" defer></script> #}
|
|
122
|
-
|
|
123
|
-
{# Bulma — no JS needed #}
|
|
124
|
-
|
|
125
|
-
{# Per-page CDN JS #}
|
|
126
|
-
{% if pageData and pageData.cdn and pageData.cdn.js %}
|
|
127
|
-
{% for script in pageData.cdn.js %}
|
|
128
|
-
<script src="{{ script }}" defer></script>
|
|
129
|
-
{% endfor %}
|
|
130
|
-
{% endif %}
|
|
131
|
-
|
|
132
|
-
{# Page JS #}
|
|
133
|
-
<script src="{{ ('/js/pages/' + title + '.js') | url }}"></script>
|
|
134
|
-
|
|
135
|
-
</body>
|
|
136
|
-
|
|
1
|
+
<!-- This is the base of every page that you will create -->
|
|
2
|
+
|
|
3
|
+
<!DOCTYPE html>
|
|
4
|
+
<html lang="{{ site.lang or 'en' }}" data-theme="{{ site.theme or 'light' }}" data-bs-theme="{{ site.theme or 'light' }}">
|
|
5
|
+
|
|
6
|
+
<head>
|
|
7
|
+
<meta charset="UTF-8">
|
|
8
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
9
|
+
<meta name="color-scheme" content="{{ site.theme or 'light' }}">
|
|
10
|
+
|
|
11
|
+
{#╔══════════════════╗
|
|
12
|
+
║ PAGE DATA ║
|
|
13
|
+
╚══════════════════╝#}
|
|
14
|
+
|
|
15
|
+
{% set pageKey = title %}
|
|
16
|
+
{% set pageData = pages[pageKey] %}
|
|
17
|
+
|
|
18
|
+
{#╔══════════════════╗
|
|
19
|
+
║ SEO ║
|
|
20
|
+
╚══════════════════╝#}
|
|
21
|
+
|
|
22
|
+
<link rel="canonical" href="{{ pageData.seo.canonical or (site.url + page.url) }}"/>
|
|
23
|
+
<title>{{ pageData.seo.title or title or site.title }}</title>
|
|
24
|
+
<meta name="description" content="{{ pageData.seo.description or site.description }}">
|
|
25
|
+
<meta name="keywords" content="{{ pageData.seo.keywords or site.keywords }}">
|
|
26
|
+
<meta name="author" content="{{ site.author }}">
|
|
27
|
+
<meta name="theme-color" content="{{ site.theme }}">
|
|
28
|
+
|
|
29
|
+
{% if pageData.seo.noindex %}
|
|
30
|
+
<meta name="robots" content="noindex, follow">
|
|
31
|
+
{% endif %}
|
|
32
|
+
|
|
33
|
+
{# Open Graph #}
|
|
34
|
+
<meta property="og:title" content="{{ pageData.seo.title or title or site.title }}">
|
|
35
|
+
<meta property="og:description" content="{{ pageData.seo.description or site.description }}">
|
|
36
|
+
<meta property="og:type" content="website">
|
|
37
|
+
<meta property="og:url" content="{{ site.url }}{{ page.url }}">
|
|
38
|
+
<meta property="og:image" content="{{ site.url }}{{ site.logo }}">
|
|
39
|
+
<meta property="og:site_name" content="{{ site.site_name }}">
|
|
40
|
+
|
|
41
|
+
{# Twitter Card #}
|
|
42
|
+
<meta name="twitter:card" content="summary_large_image">
|
|
43
|
+
<meta name="twitter:title" content="{{ pageData.seo.title or title or site.title }}">
|
|
44
|
+
<meta name="twitter:description" content="{{ pageData.seo.description or site.description }}">
|
|
45
|
+
<meta name="twitter:image" content="{{ site.url }}{{ site.logo }}">
|
|
46
|
+
|
|
47
|
+
{#╔══════════════════════════════════════════╗
|
|
48
|
+
║ JSON-LD — Structured data for SEO/AI ║
|
|
49
|
+
╚══════════════════════════════════════════╝#}
|
|
50
|
+
|
|
51
|
+
<script type="application/ld+json">
|
|
52
|
+
{
|
|
53
|
+
"@context": "https://schema.org",
|
|
54
|
+
"@type": "WebPage",
|
|
55
|
+
"name": {{ (pageData.seo.title or title or site.title) | dump }},
|
|
56
|
+
"description": {{ (pageData.seo.description or site.description) | dump }},
|
|
57
|
+
"url": {{ (site.url + page.url) | dump }},
|
|
58
|
+
"author": {
|
|
59
|
+
"@type": "Person",
|
|
60
|
+
"name": {{ site.author | dump }}
|
|
61
|
+
},
|
|
62
|
+
"publisher": {
|
|
63
|
+
"@type": "Organization",
|
|
64
|
+
"name": {{ site.site_name | dump }},
|
|
65
|
+
"logo": {
|
|
66
|
+
"@type": "ImageObject",
|
|
67
|
+
"url": {{ (site.url + site.logo) | dump }}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
</script>
|
|
72
|
+
|
|
73
|
+
{#╔══════════════════╗
|
|
74
|
+
║ FAVICON ║
|
|
75
|
+
╚══════════════════╝#}
|
|
76
|
+
|
|
77
|
+
<link rel="icon" type="image/svg+xml" href="{{ '/assets/brand/favicon.svg' | url }}">
|
|
78
|
+
<link rel="icon" type="image/png" sizes="32x32" href="{{ '/assets/brand/favicon-32.png' | url }}">
|
|
79
|
+
<link rel="apple-touch-icon" sizes="180x180" href="{{ '/assets/brand/apple-touch-icon.png' | url }}">
|
|
80
|
+
|
|
81
|
+
{#╔══════════════════╗
|
|
82
|
+
║ CSS ║
|
|
83
|
+
╚══════════════════╝#}
|
|
84
|
+
|
|
85
|
+
{# Page CSS #}
|
|
86
|
+
<link rel="stylesheet" href="{{ ('/css/pages/' + title + '.css') | url }}"/>
|
|
87
|
+
|
|
88
|
+
{# Per-page CDN CSS #}
|
|
89
|
+
{% if pageData and pageData.cdn and pageData.cdn.css %}
|
|
90
|
+
{% for link in pageData.cdn.css %}
|
|
91
|
+
<link rel="stylesheet" href="{{ link }}">
|
|
92
|
+
{% endfor %}
|
|
93
|
+
{% endif %}
|
|
94
|
+
|
|
95
|
+
</head>
|
|
96
|
+
|
|
97
|
+
<body>
|
|
98
|
+
|
|
99
|
+
{% include "global/header.njk" %}
|
|
100
|
+
|
|
101
|
+
<main>
|
|
102
|
+
{{ content | safe }}
|
|
103
|
+
</main>
|
|
104
|
+
|
|
105
|
+
{% include "global/footer.njk" %}
|
|
106
|
+
|
|
107
|
+
{#╔══════════════════╗
|
|
108
|
+
║ SCRIPTS ║
|
|
109
|
+
╚══════════════════╝#}
|
|
110
|
+
|
|
111
|
+
{# Framework — uncomment the one you are using #}
|
|
112
|
+
|
|
113
|
+
{# Bootstrap JS #}
|
|
114
|
+
<script src="{{ '/js/bootstrap.bundle.min.js' | url }}" defer></script>
|
|
115
|
+
|
|
116
|
+
{# Foundation JS #}
|
|
117
|
+
{# <script src="{{ '/js/foundation.min.js' | url }}" defer></script> #}
|
|
118
|
+
|
|
119
|
+
{# UIkit JS #}
|
|
120
|
+
{# <script src="{{ '/js/uikit.min.js' | url }}" defer></script> #}
|
|
121
|
+
{# <script src="{{ '/js/uikit-icons.min.js' | url }}" defer></script> #}
|
|
122
|
+
|
|
123
|
+
{# Bulma — no JS needed #}
|
|
124
|
+
|
|
125
|
+
{# Per-page CDN JS #}
|
|
126
|
+
{% if pageData and pageData.cdn and pageData.cdn.js %}
|
|
127
|
+
{% for script in pageData.cdn.js %}
|
|
128
|
+
<script src="{{ script }}" defer></script>
|
|
129
|
+
{% endfor %}
|
|
130
|
+
{% endif %}
|
|
131
|
+
|
|
132
|
+
{# Page JS #}
|
|
133
|
+
<script src="{{ ('/js/pages/' + title + '.js') | url }}"></script>
|
|
134
|
+
|
|
135
|
+
</body>
|
|
136
|
+
|
|
137
137
|
</html>
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
---
|
|
2
|
-
layout: base.njk
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
<!-- NJK (HTML) components per page -->
|
|
6
|
-
|
|
7
|
-
{% if title == "homepage" %}
|
|
8
|
-
{% include "welcome.njk" ignore missing %}
|
|
9
|
-
|
|
10
|
-
{% else %}
|
|
11
|
-
<!-- You should not touch this else statement -->
|
|
12
|
-
{% include "404/_404.njk" %}
|
|
13
|
-
{{ content | safe }}
|
|
1
|
+
---
|
|
2
|
+
layout: base.njk
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
<!-- NJK (HTML) components per page -->
|
|
6
|
+
|
|
7
|
+
{% if title == "homepage" %}
|
|
8
|
+
{% include "welcome.njk" ignore missing %}
|
|
9
|
+
|
|
10
|
+
{% else %}
|
|
11
|
+
<!-- You should not touch this else statement -->
|
|
12
|
+
{% include "404/_404.njk" %}
|
|
13
|
+
{{ content | safe }}
|
|
14
14
|
{% endif %}
|