@vojtaholik/create-static-kit 1.0.8 → 2.1.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/package.json +6 -34
- package/src/index.ts +41 -0
- package/template/blocks/feature-grid.block.html +28 -0
- package/template/blocks/feature-grid.block.ts +32 -0
- package/template/blocks/gen/feature-grid.render.ts +92 -0
- package/template/blocks/gen/hero.render.ts +79 -0
- package/template/blocks/gen/index.ts +4 -0
- package/template/blocks/gen/latest-posts.render.ts +114 -0
- package/template/blocks/gen/text-section.render.ts +69 -0
- package/template/blocks/hero.block.html +31 -0
- package/template/blocks/hero.block.ts +40 -0
- package/template/blocks/index.ts +46 -0
- package/template/blocks/latest-posts.block.html +38 -0
- package/template/blocks/latest-posts.block.ts +45 -0
- package/template/blocks/text-section.block.html +18 -0
- package/template/blocks/text-section.block.ts +25 -0
- package/template/package.json +21 -0
- package/template/public/css/styles.css +589 -0
- package/template/public/js/dev-overlay.js +366 -0
- package/template/public/js/index.js +35 -0
- package/template/public/sprite.svg +6 -0
- package/template/public/svg/magic-wand.svg +4 -0
- package/template/site/pages/about.page.ts +91 -0
- package/template/site/pages/base.html +38 -0
- package/template/site/pages/index.page.ts +107 -0
- package/template/site/pages/index.ts +16 -0
- package/template/static-kit.config.ts +10 -0
- package/template/tsconfig.json +23 -0
- package/bin/create-static-kit.js +0 -3
- package/dist/cli.d.ts +0 -3
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js +0 -488
- package/templates/default/.cursor/rules/configuration.mdc +0 -20
- package/templates/default/.cursor/rules/figma-integration.mdc +0 -22
- package/templates/default/.cursor/rules/html-components.mdc +0 -24
- package/templates/default/.cursor/rules/html-pages.mdc +0 -22
- package/templates/default/.cursor/rules/inline-tailwind-to-bem-with-apply-directive.mdc +0 -218
- package/templates/default/.cursor/rules/project-overview.mdc +0 -30
- package/templates/default/.cursor/rules/public-assets.mdc +0 -22
- package/templates/default/.cursor/rules/scss-styles.mdc +0 -22
- package/templates/default/.cursor/rules/svg-icons.mdc +0 -22
- package/templates/default/.cursor/rules/typescript-js.mdc +0 -23
- package/templates/default/public/favicon.ico +0 -1
- package/templates/default/src/components/button.html +0 -1
- package/templates/default/src/components/feature-card.html +0 -8
- package/templates/default/src/components/footer.html +0 -5
- package/templates/default/src/components/navigation.html +0 -11
- package/templates/default/src/icons/ui/star.svg +0 -3
- package/templates/default/src/js/index.ts +0 -28
- package/templates/default/src/pages/about.html +0 -24
- package/templates/default/src/pages/index.html +0 -23
- package/templates/default/src/styles/main.scss +0 -210
- package/templates/default/tsconfig.json +0 -19
- package/templates/minimal/.cursor/rules/configuration.mdc +0 -20
- package/templates/minimal/.cursor/rules/figma-integration.mdc +0 -22
- package/templates/minimal/.cursor/rules/html-components.mdc +0 -24
- package/templates/minimal/.cursor/rules/html-pages.mdc +0 -22
- package/templates/minimal/.cursor/rules/inline-tailwind-to-bem-with-apply-directive.mdc +0 -218
- package/templates/minimal/.cursor/rules/project-overview.mdc +0 -30
- package/templates/minimal/.cursor/rules/public-assets.mdc +0 -22
- package/templates/minimal/.cursor/rules/scss-styles.mdc +0 -22
- package/templates/minimal/.cursor/rules/svg-icons.mdc +0 -22
- package/templates/minimal/.cursor/rules/typescript-js.mdc +0 -23
- package/templates/minimal/public/favicon.ico +0 -1
- package/templates/minimal/src/components/footer.html +0 -3
- package/templates/minimal/src/components/header.html +0 -6
- package/templates/minimal/src/js/index.ts +0 -9
- package/templates/minimal/src/pages/index.html +0 -15
- package/templates/minimal/src/styles/main.scss +0 -77
- package/templates/minimal/tsconfig.json +0 -19
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Static Kit - Dev Overlay
|
|
3
|
+
*
|
|
4
|
+
* - Alt+click on any block to inspect its schema address
|
|
5
|
+
* - Hot reload via SSE connection
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
(function () {
|
|
9
|
+
"use strict";
|
|
10
|
+
|
|
11
|
+
// ==========================================================================
|
|
12
|
+
// Hot Reload Client
|
|
13
|
+
// ==========================================================================
|
|
14
|
+
|
|
15
|
+
var reconnectAttempts = 0;
|
|
16
|
+
var maxReconnectAttempts = 20;
|
|
17
|
+
var wasConnected = false;
|
|
18
|
+
var lastServerTime = null;
|
|
19
|
+
|
|
20
|
+
function connectHMR() {
|
|
21
|
+
var source = new EventSource("/__hmr");
|
|
22
|
+
|
|
23
|
+
source.onopen = function () {
|
|
24
|
+
console.log("[HMR] Connected");
|
|
25
|
+
|
|
26
|
+
// If we were previously connected and reconnected, reload
|
|
27
|
+
// This handles the case where the server restarted (--watch)
|
|
28
|
+
if (wasConnected) {
|
|
29
|
+
console.log("[HMR] Server restarted, reloading...");
|
|
30
|
+
window.location.reload();
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
wasConnected = true;
|
|
35
|
+
reconnectAttempts = 0;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
source.onmessage = function (event) {
|
|
39
|
+
try {
|
|
40
|
+
var data = JSON.parse(event.data);
|
|
41
|
+
|
|
42
|
+
if (data.type === "connected") {
|
|
43
|
+
// Store server start time to detect restarts
|
|
44
|
+
if (lastServerTime && data.time && lastServerTime !== data.time) {
|
|
45
|
+
console.log("[HMR] Server restarted, reloading...");
|
|
46
|
+
window.location.reload();
|
|
47
|
+
}
|
|
48
|
+
lastServerTime = data.time;
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (data.type === "css") {
|
|
53
|
+
// Hot reload CSS and SVG sprites without full page refresh
|
|
54
|
+
reloadCSS();
|
|
55
|
+
reloadSVGSprites();
|
|
56
|
+
} else if (data.type === "full") {
|
|
57
|
+
// Full page reload
|
|
58
|
+
console.log("[HMR] Reloading...");
|
|
59
|
+
window.location.reload();
|
|
60
|
+
}
|
|
61
|
+
} catch (e) {
|
|
62
|
+
console.error("[HMR] Failed to parse message:", e);
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
source.onerror = function () {
|
|
67
|
+
source.close();
|
|
68
|
+
reconnectAttempts++;
|
|
69
|
+
|
|
70
|
+
if (reconnectAttempts <= maxReconnectAttempts) {
|
|
71
|
+
// Quick reconnects at first, then slower
|
|
72
|
+
var delay =
|
|
73
|
+
reconnectAttempts < 3 ? 100 : Math.min(500 * reconnectAttempts, 3000);
|
|
74
|
+
console.log("[HMR] Disconnected, reconnecting in " + delay + "ms...");
|
|
75
|
+
setTimeout(connectHMR, delay);
|
|
76
|
+
} else {
|
|
77
|
+
console.log(
|
|
78
|
+
"[HMR] Max reconnection attempts reached. Refresh manually."
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function reloadCSS() {
|
|
85
|
+
var links = document.querySelectorAll('link[rel="stylesheet"]');
|
|
86
|
+
var reloaded = 0;
|
|
87
|
+
|
|
88
|
+
links.forEach(function (link) {
|
|
89
|
+
var href = link.href;
|
|
90
|
+
if (!href) return;
|
|
91
|
+
|
|
92
|
+
// Add cache-busting query param
|
|
93
|
+
var url = new URL(href);
|
|
94
|
+
url.searchParams.set("_hmr", Date.now());
|
|
95
|
+
|
|
96
|
+
// Create new link element
|
|
97
|
+
var newLink = document.createElement("link");
|
|
98
|
+
newLink.rel = "stylesheet";
|
|
99
|
+
newLink.href = url.toString();
|
|
100
|
+
|
|
101
|
+
newLink.onload = function () {
|
|
102
|
+
link.remove();
|
|
103
|
+
reloaded++;
|
|
104
|
+
if (reloaded === links.length) {
|
|
105
|
+
console.log("[HMR] CSS reloaded");
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
newLink.onerror = function () {
|
|
110
|
+
console.error("[HMR] Failed to reload CSS:", href);
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
link.parentNode.insertBefore(newLink, link.nextSibling);
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function reloadSVGSprites() {
|
|
118
|
+
// Find all <use> elements referencing sprite files
|
|
119
|
+
var uses = document.querySelectorAll("use[href*='sprite']");
|
|
120
|
+
if (uses.length === 0) return;
|
|
121
|
+
|
|
122
|
+
var timestamp = Date.now();
|
|
123
|
+
uses.forEach(function (use) {
|
|
124
|
+
var href = use.getAttribute("href");
|
|
125
|
+
if (!href) return;
|
|
126
|
+
|
|
127
|
+
// Parse href and add cache-busting param
|
|
128
|
+
var hashIndex = href.indexOf("#");
|
|
129
|
+
var path = hashIndex > -1 ? href.slice(0, hashIndex) : href;
|
|
130
|
+
var fragment = hashIndex > -1 ? href.slice(hashIndex) : "";
|
|
131
|
+
|
|
132
|
+
// Strip existing _hmr param if present
|
|
133
|
+
var cleanPath = path.replace(/[?&]_hmr=\d+/, "");
|
|
134
|
+
var separator = cleanPath.indexOf("?") > -1 ? "&" : "?";
|
|
135
|
+
var newHref = cleanPath + separator + "_hmr=" + timestamp + fragment;
|
|
136
|
+
|
|
137
|
+
use.setAttribute("href", newHref);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
console.log("[HMR] SVG sprites reloaded (" + uses.length + " refs)");
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Start HMR connection
|
|
144
|
+
connectHMR();
|
|
145
|
+
|
|
146
|
+
// ==========================================================================
|
|
147
|
+
// Block Inspector
|
|
148
|
+
// ==========================================================================
|
|
149
|
+
|
|
150
|
+
var overlay = null;
|
|
151
|
+
|
|
152
|
+
function createOverlay() {
|
|
153
|
+
var el = document.createElement("div");
|
|
154
|
+
el.id = "static-kit-dev-overlay";
|
|
155
|
+
el.innerHTML = [
|
|
156
|
+
"<style>",
|
|
157
|
+
"#static-kit-dev-overlay {",
|
|
158
|
+
" position: fixed;",
|
|
159
|
+
" z-index: 99999;",
|
|
160
|
+
" background: #1a1a2e;",
|
|
161
|
+
" color: #fff;",
|
|
162
|
+
" padding: 16px;",
|
|
163
|
+
" border-radius: 8px;",
|
|
164
|
+
" font-family: ui-monospace, monospace;",
|
|
165
|
+
" font-size: 13px;",
|
|
166
|
+
" line-height: 1.5;",
|
|
167
|
+
" max-width: 480px;",
|
|
168
|
+
" box-shadow: 0 10px 40px rgba(0,0,0,0.3);",
|
|
169
|
+
" display: none;",
|
|
170
|
+
"}",
|
|
171
|
+
"#static-kit-dev-overlay.visible { display: block; }",
|
|
172
|
+
"#static-kit-dev-overlay h4 {",
|
|
173
|
+
" margin: 0 0 12px;",
|
|
174
|
+
" font-size: 14px;",
|
|
175
|
+
" font-weight: 600;",
|
|
176
|
+
" color: #6366f1;",
|
|
177
|
+
"}",
|
|
178
|
+
"#static-kit-dev-overlay dl {",
|
|
179
|
+
" margin: 0;",
|
|
180
|
+
" display: grid;",
|
|
181
|
+
" grid-template-columns: auto 1fr;",
|
|
182
|
+
" gap: 4px 12px;",
|
|
183
|
+
"}",
|
|
184
|
+
"#static-kit-dev-overlay dt {",
|
|
185
|
+
" color: #9ca3af;",
|
|
186
|
+
"}",
|
|
187
|
+
"#static-kit-dev-overlay dd {",
|
|
188
|
+
" margin: 0;",
|
|
189
|
+
" word-break: break-all;",
|
|
190
|
+
"}",
|
|
191
|
+
"#static-kit-dev-overlay a {",
|
|
192
|
+
" color: #818cf8;",
|
|
193
|
+
" text-decoration: none;",
|
|
194
|
+
" display: inline-flex;",
|
|
195
|
+
" align-items: center;",
|
|
196
|
+
" gap: 4px;",
|
|
197
|
+
"}",
|
|
198
|
+
"#static-kit-dev-overlay a:hover {",
|
|
199
|
+
" color: #a5b4fc;",
|
|
200
|
+
" text-decoration: underline;",
|
|
201
|
+
"}",
|
|
202
|
+
"#static-kit-dev-overlay .file-links {",
|
|
203
|
+
" margin-top: 12px;",
|
|
204
|
+
" padding-top: 12px;",
|
|
205
|
+
" border-top: 1px solid #374151;",
|
|
206
|
+
" display: flex;",
|
|
207
|
+
" flex-direction: column;",
|
|
208
|
+
" gap: 6px;",
|
|
209
|
+
"}",
|
|
210
|
+
"#static-kit-dev-overlay .close-btn {",
|
|
211
|
+
" position: absolute;",
|
|
212
|
+
" top: 8px;",
|
|
213
|
+
" right: 8px;",
|
|
214
|
+
" background: none;",
|
|
215
|
+
" border: none;",
|
|
216
|
+
" color: #9ca3af;",
|
|
217
|
+
" cursor: pointer;",
|
|
218
|
+
" padding: 4px;",
|
|
219
|
+
" font-size: 16px;",
|
|
220
|
+
"}",
|
|
221
|
+
"#static-kit-dev-overlay .close-btn:hover { color: #fff; }",
|
|
222
|
+
"#static-kit-dev-overlay .loading {",
|
|
223
|
+
" color: #9ca3af;",
|
|
224
|
+
" font-style: italic;",
|
|
225
|
+
"}",
|
|
226
|
+
"[data-schema-address] { position: relative; }",
|
|
227
|
+
"[data-schema-address].inspecting {",
|
|
228
|
+
" outline: 2px dashed #6366f1;",
|
|
229
|
+
" outline-offset: 2px;",
|
|
230
|
+
"}",
|
|
231
|
+
"</style>",
|
|
232
|
+
'<button class="close-btn" aria-label="Close">×</button>',
|
|
233
|
+
"<h4>Block Inspector</h4>",
|
|
234
|
+
"<dl></dl>",
|
|
235
|
+
'<div class="file-links"></div>',
|
|
236
|
+
].join("\n");
|
|
237
|
+
document.body.appendChild(el);
|
|
238
|
+
|
|
239
|
+
el.querySelector(".close-btn").addEventListener("click", hideOverlay);
|
|
240
|
+
|
|
241
|
+
return el;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
function makeCursorLink(filePath, label) {
|
|
245
|
+
if (!filePath) return '<span style="color:#6b7280">-</span>';
|
|
246
|
+
// cursor://file/absolute/path
|
|
247
|
+
var href = "cursor://file" + filePath;
|
|
248
|
+
var shortPath = filePath.split("/").slice(-2).join("/");
|
|
249
|
+
return (
|
|
250
|
+
'<a href="' +
|
|
251
|
+
href +
|
|
252
|
+
'" title="' +
|
|
253
|
+
filePath +
|
|
254
|
+
'">' +
|
|
255
|
+
(label || shortPath) +
|
|
256
|
+
" ↗</a>"
|
|
257
|
+
);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
async function showOverlay(blockEl, x, y) {
|
|
261
|
+
if (!overlay) {
|
|
262
|
+
overlay = createOverlay();
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
var address = blockEl.getAttribute("data-schema-address");
|
|
266
|
+
var blockId = blockEl.getAttribute("data-block-id");
|
|
267
|
+
var parts = address ? address.split("::") : [];
|
|
268
|
+
|
|
269
|
+
// Remove previous inspecting class
|
|
270
|
+
var prev = document.querySelector(".inspecting");
|
|
271
|
+
if (prev) prev.classList.remove("inspecting");
|
|
272
|
+
blockEl.classList.add("inspecting");
|
|
273
|
+
|
|
274
|
+
// Position overlay
|
|
275
|
+
overlay.style.top = Math.min(y + 10, window.innerHeight - 200) + "px";
|
|
276
|
+
overlay.style.left = Math.min(x + 10, window.innerWidth - 500) + "px";
|
|
277
|
+
overlay.classList.add("visible");
|
|
278
|
+
|
|
279
|
+
var dl = overlay.querySelector("dl");
|
|
280
|
+
var fileLinks = overlay.querySelector(".file-links");
|
|
281
|
+
|
|
282
|
+
// Show loading state
|
|
283
|
+
dl.innerHTML = [
|
|
284
|
+
"<dt>Page</dt><dd>" + (parts[0] || "-") + "</dd>",
|
|
285
|
+
"<dt>Region</dt><dd>" + (parts[1] || "-") + "</dd>",
|
|
286
|
+
"<dt>Block ID</dt><dd>" + (blockId || "-") + "</dd>",
|
|
287
|
+
].join("");
|
|
288
|
+
fileLinks.innerHTML = '<span class="loading">Loading...</span>';
|
|
289
|
+
|
|
290
|
+
// Fetch full info from server
|
|
291
|
+
try {
|
|
292
|
+
var res = await fetch(
|
|
293
|
+
"/__inspect?address=" + encodeURIComponent(address)
|
|
294
|
+
);
|
|
295
|
+
var data = await res.json();
|
|
296
|
+
|
|
297
|
+
if (data.error) {
|
|
298
|
+
fileLinks.innerHTML =
|
|
299
|
+
'<span style="color:#ef4444">' + data.error + "</span>";
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
dl.innerHTML = [
|
|
304
|
+
"<dt>Block Type</dt><dd><strong>" +
|
|
305
|
+
(data.block?.type || "-") +
|
|
306
|
+
"</strong></dd>",
|
|
307
|
+
"<dt>Page</dt><dd>" + (data.page?.id || "-") + "</dd>",
|
|
308
|
+
"<dt>Region</dt><dd>" + (data.address?.region || "-") + "</dd>",
|
|
309
|
+
"<dt>Block ID</dt><dd>" + (data.block?.id || "-") + "</dd>",
|
|
310
|
+
].join("");
|
|
311
|
+
|
|
312
|
+
fileLinks.innerHTML =
|
|
313
|
+
[
|
|
314
|
+
data.block?.sourceFile
|
|
315
|
+
? makeCursorLink(data.block.sourceFile, "📦 Block Source")
|
|
316
|
+
: "",
|
|
317
|
+
data.block?.templateFile
|
|
318
|
+
? makeCursorLink(data.block.templateFile, "📄 Template")
|
|
319
|
+
: "",
|
|
320
|
+
data.page?.sourceFile
|
|
321
|
+
? makeCursorLink(data.page.sourceFile, "📄 Page Config")
|
|
322
|
+
: "",
|
|
323
|
+
]
|
|
324
|
+
.filter(Boolean)
|
|
325
|
+
.join("") ||
|
|
326
|
+
'<span style="color:#6b7280">No source files found</span>';
|
|
327
|
+
} catch (err) {
|
|
328
|
+
fileLinks.innerHTML = '<span style="color:#ef4444">Failed to load</span>';
|
|
329
|
+
console.error("[Inspector] Failed to fetch:", err);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
function hideOverlay() {
|
|
334
|
+
if (overlay) {
|
|
335
|
+
overlay.classList.remove("visible");
|
|
336
|
+
}
|
|
337
|
+
var prev = document.querySelector(".inspecting");
|
|
338
|
+
if (prev) prev.classList.remove("inspecting");
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// Alt+click handler
|
|
342
|
+
document.addEventListener("click", function (e) {
|
|
343
|
+
if (!e.altKey) {
|
|
344
|
+
hideOverlay();
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
e.preventDefault();
|
|
349
|
+
e.stopPropagation();
|
|
350
|
+
|
|
351
|
+
// Find closest block element
|
|
352
|
+
var blockEl = e.target.closest("[data-schema-address]");
|
|
353
|
+
if (blockEl) {
|
|
354
|
+
showOverlay(blockEl, e.clientX, e.clientY);
|
|
355
|
+
}
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
// ESC to close
|
|
359
|
+
document.addEventListener("keydown", function (e) {
|
|
360
|
+
if (e.key === "Escape") {
|
|
361
|
+
hideOverlay();
|
|
362
|
+
}
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
console.log("Static Kit Dev Overlay loaded. Alt+click on blocks to inspect.");
|
|
366
|
+
})();
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Static Kit - Client Runtime
|
|
3
|
+
*
|
|
4
|
+
* Minimal ES5-compatible enhancement script.
|
|
5
|
+
* Add interactive behaviors here as needed.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
(function () {
|
|
9
|
+
"use strict";
|
|
10
|
+
|
|
11
|
+
// Smooth scroll for anchor links
|
|
12
|
+
document.addEventListener("click", function (e) {
|
|
13
|
+
var target = e.target;
|
|
14
|
+
if (target.tagName === "A" && target.hash) {
|
|
15
|
+
var element = document.querySelector(target.hash);
|
|
16
|
+
if (element) {
|
|
17
|
+
e.preventDefault();
|
|
18
|
+
element.scrollIntoView({ behavior: "smooth" });
|
|
19
|
+
history.pushState(null, null, target.hash);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
// Mark external links
|
|
25
|
+
var links = document.querySelectorAll('a[href^="http"]');
|
|
26
|
+
for (var i = 0; i < links.length; i++) {
|
|
27
|
+
var link = links[i];
|
|
28
|
+
if (link.hostname !== window.location.hostname) {
|
|
29
|
+
link.setAttribute("target", "_blank");
|
|
30
|
+
link.setAttribute("rel", "noopener noreferrer");
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
console.log("Static Kit initialized");
|
|
35
|
+
})();
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="display:none;">
|
|
2
|
+
<symbol id="magic-wand" viewBox="0 0 24 24">
|
|
3
|
+
<path stroke="#141B34" stroke-linejoin="round" stroke-width="1.5" d="m10.938 11.077-7.527 7.528a1.403 1.403 0 1 0 1.985 1.984l7.527-7.527m-1.985-1.985 1.985 1.985m-1.985-1.985.744-.744m1.24 2.729.745-.744m-1.985-1.985.043-.042a.992.992 0 0 1 1.403 0l.581.58a.992.992 0 0 1 0 1.404l-.042.043m-1.985-1.985 1.985 1.985m4.571-9.151a.29.29 0 0 1 .524 0l.392.84c.173.37.47.666.84.839l.839.392a.29.29 0 0 1 0 .524l-.84.392c-.37.173-.666.47-.839.84l-.392.839a.29.29 0 0 1-.524 0l-.392-.84a1.737 1.737 0 0 0-.84-.839l-.839-.392a.29.29 0 0 1 0-.524l.84-.392c.37-.173.666-.47.839-.84l.392-.839Z"/>
|
|
4
|
+
<path stroke="#141B34" stroke-linejoin="round" stroke-width="1.5" d="M18.238 14.167a.29.29 0 0 1 .524 0l.392.84c.173.37.47.666.84.839l.839.392a.29.29 0 0 1 0 .524l-.84.392c-.37.173-.666.47-.839.84l-.392.839a.29.29 0 0 1-.524 0l-.392-.84a1.737 1.737 0 0 0-.84-.839l-.839-.392a.29.29 0 0 1 0-.524l.84-.392c.37-.173.666-.47.839-.84l.392-.839Zm-11-11a.29.29 0 0 1 .524 0l.392.84c.173.37.47.666.84.839l.839.392a.29.29 0 0 1 0 .524l-.84.392c-.37.173-.666.47-.839.84l-.392.839a.29.29 0 0 1-.524 0l-.392-.84a1.737 1.737 0 0 0-.84-.839l-.839-.392a.29.29 0 0 1 0-.524l.84-.392c.37-.173.666-.47.839-.84l.392-.839Z" opacity=".4"/>
|
|
5
|
+
</symbol>
|
|
6
|
+
</svg>
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
|
|
2
|
+
<path stroke="#141B34" stroke-linejoin="round" stroke-width="1.5" d="m10.938 11.077-7.527 7.528a1.403 1.403 0 1 0 1.985 1.984l7.527-7.527m-1.985-1.985 1.985 1.985m-1.985-1.985.744-.744m1.24 2.729.745-.744m-1.985-1.985.043-.042a.992.992 0 0 1 1.403 0l.581.58a.992.992 0 0 1 0 1.404l-.042.043m-1.985-1.985 1.985 1.985m4.571-9.151a.29.29 0 0 1 .524 0l.392.84c.173.37.47.666.84.839l.839.392a.29.29 0 0 1 0 .524l-.84.392c-.37.173-.666.47-.839.84l-.392.839a.29.29 0 0 1-.524 0l-.392-.84a1.737 1.737 0 0 0-.84-.839l-.839-.392a.29.29 0 0 1 0-.524l.84-.392c.37-.173.666-.47.839-.84l.392-.839Z"/>
|
|
3
|
+
<path stroke="#141B34" stroke-linejoin="round" stroke-width="1.5" d="M18.238 14.167a.29.29 0 0 1 .524 0l.392.84c.173.37.47.666.84.839l.839.392a.29.29 0 0 1 0 .524l-.84.392c-.37.173-.666.47-.839.84l-.392.839a.29.29 0 0 1-.524 0l-.392-.84a1.737 1.737 0 0 0-.84-.839l-.839-.392a.29.29 0 0 1 0-.524l.84-.392c.37-.173.666-.47.839-.84l.392-.839Zm-11-11a.29.29 0 0 1 .524 0l.392.84c.173.37.47.666.84.839l.839.392a.29.29 0 0 1 0 .524l-.84.392c-.37.173-.666.47-.839.84l-.392.839a.29.29 0 0 1-.524 0l-.392-.84a1.737 1.737 0 0 0-.84-.839l-.839-.392a.29.29 0 0 1 0-.524l.84-.392c.37-.173.666-.47.839-.84l.392-.839Z" opacity=".4"/>
|
|
4
|
+
</svg>
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import type { PageConfig } from "@vojtaholik/static-kit-core";
|
|
2
|
+
|
|
3
|
+
export const aboutPage: PageConfig = {
|
|
4
|
+
id: "about",
|
|
5
|
+
path: "/about",
|
|
6
|
+
title: "About Static Kit",
|
|
7
|
+
template: "base.html",
|
|
8
|
+
density: "comfortable",
|
|
9
|
+
regions: {
|
|
10
|
+
main: {
|
|
11
|
+
blocks: [
|
|
12
|
+
{
|
|
13
|
+
id: "hero-about",
|
|
14
|
+
type: "hero",
|
|
15
|
+
props: {
|
|
16
|
+
eyebrow: "About",
|
|
17
|
+
headline: "The Philosophy Behind Static Kit",
|
|
18
|
+
subheadline:
|
|
19
|
+
"We believe static sites should be fast, maintainable, and a joy to build.",
|
|
20
|
+
},
|
|
21
|
+
layout: {
|
|
22
|
+
tone: "surface",
|
|
23
|
+
contentAlign: "center",
|
|
24
|
+
contentWidth: "narrow",
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
id: "text-mission",
|
|
29
|
+
type: "textSection",
|
|
30
|
+
props: {
|
|
31
|
+
eyebrow: "Our Mission",
|
|
32
|
+
headline: "Simplicity Without Sacrifice",
|
|
33
|
+
body: `
|
|
34
|
+
<p>Static Kit was born from frustration with modern web development complexity. We wanted a tool that:</p>
|
|
35
|
+
<ul>
|
|
36
|
+
<li>Produces fast, accessible websites by default</li>
|
|
37
|
+
<li>Doesn't require a JavaScript framework for content sites</li>
|
|
38
|
+
<li>Makes content management intuitive for developers and content editors</li>
|
|
39
|
+
<li>Stays out of your way while providing powerful abstractions</li>
|
|
40
|
+
</ul>
|
|
41
|
+
<p>The result is a static site generator that embraces HTML as the output format, TypeScript for type safety, and a simple block-based architecture that scales from landing pages to large marketing sites.</p>
|
|
42
|
+
`,
|
|
43
|
+
},
|
|
44
|
+
layout: {
|
|
45
|
+
tone: "surface",
|
|
46
|
+
contentAlign: "left",
|
|
47
|
+
contentWidth: "narrow",
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
id: "features-principles",
|
|
52
|
+
type: "featureGrid",
|
|
53
|
+
props: {
|
|
54
|
+
headline: "Core Principles",
|
|
55
|
+
columns: "2",
|
|
56
|
+
features: [
|
|
57
|
+
{
|
|
58
|
+
icon: "📄",
|
|
59
|
+
title: "HTML First",
|
|
60
|
+
description:
|
|
61
|
+
"The web is built on HTML. We generate semantic, accessible markup that works everywhere.",
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
icon: "🔒",
|
|
65
|
+
title: "Type Safety",
|
|
66
|
+
description:
|
|
67
|
+
"Every block prop, every page config, every template expression is type-checked.",
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
icon: "🎯",
|
|
71
|
+
title: "Zero Runtime",
|
|
72
|
+
description:
|
|
73
|
+
"No framework JavaScript shipped to users. Add interactivity only where you need it.",
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
icon: "🔌",
|
|
77
|
+
title: "CMS Agnostic",
|
|
78
|
+
description:
|
|
79
|
+
"Your content schemas work with any headless CMS. We don't lock you in.",
|
|
80
|
+
},
|
|
81
|
+
],
|
|
82
|
+
},
|
|
83
|
+
layout: {
|
|
84
|
+
tone: "raised",
|
|
85
|
+
contentAlign: "center",
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
],
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>JAP</title>
|
|
7
|
+
<link rel="stylesheet" href="public/css/styles.css" />
|
|
8
|
+
</head>
|
|
9
|
+
<body>
|
|
10
|
+
<header class="site-header">
|
|
11
|
+
<nav class="container">
|
|
12
|
+
<a href="/" class="site-header__logo">
|
|
13
|
+
<svg width="24" height="24">
|
|
14
|
+
<use href="public/sprite.svg#magic-wand"></use>
|
|
15
|
+
</svg>
|
|
16
|
+
Static Kit
|
|
17
|
+
</a>
|
|
18
|
+
<div class="site-header__nav">
|
|
19
|
+
<a href="/">Home</a>
|
|
20
|
+
<a href="/about">About</a>
|
|
21
|
+
<a href="/blog">Blog</a>
|
|
22
|
+
</div>
|
|
23
|
+
</nav>
|
|
24
|
+
</header>
|
|
25
|
+
|
|
26
|
+
<main data-region="main">
|
|
27
|
+
<!-- Blocks render here -->
|
|
28
|
+
</main>
|
|
29
|
+
|
|
30
|
+
<footer class="site-footer">
|
|
31
|
+
<div class="container">
|
|
32
|
+
<p>© 2024 Static Kit. Built with static-block-kit.</p>
|
|
33
|
+
</div>
|
|
34
|
+
</footer>
|
|
35
|
+
|
|
36
|
+
<script src="public/js/index.js"></script>
|
|
37
|
+
</body>
|
|
38
|
+
</html>
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import type { PageConfig } from "@vojtaholik/static-kit-core";
|
|
2
|
+
|
|
3
|
+
export const indexPage: PageConfig = {
|
|
4
|
+
id: "home",
|
|
5
|
+
path: "/",
|
|
6
|
+
title: "JAP",
|
|
7
|
+
template: "base.html",
|
|
8
|
+
density: "comfortable",
|
|
9
|
+
regions: {
|
|
10
|
+
main: {
|
|
11
|
+
blocks: [
|
|
12
|
+
{
|
|
13
|
+
id: "hero-1",
|
|
14
|
+
type: "hero",
|
|
15
|
+
props: {
|
|
16
|
+
eyebrow: "Introducing Static Kit",
|
|
17
|
+
headline: "Build Beautiful Static Sites",
|
|
18
|
+
subheadline:
|
|
19
|
+
"A modern static site generator with block-based content management and a Vue-like template DSL.",
|
|
20
|
+
primaryCta: {
|
|
21
|
+
href: "/docs/getting-started",
|
|
22
|
+
label: "Get Started",
|
|
23
|
+
},
|
|
24
|
+
secondaryCta: {
|
|
25
|
+
href: "/about",
|
|
26
|
+
label: "Learn More",
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
layout: {
|
|
30
|
+
tone: "accent",
|
|
31
|
+
contentAlign: "center",
|
|
32
|
+
contentWidth: "narrow",
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
id: "features-1",
|
|
37
|
+
type: "featureGrid",
|
|
38
|
+
props: {
|
|
39
|
+
headline: "Why Static Kit?",
|
|
40
|
+
subheadline:
|
|
41
|
+
"Everything you need to build fast, maintainable static sites.",
|
|
42
|
+
columns: "3",
|
|
43
|
+
features: [
|
|
44
|
+
{
|
|
45
|
+
icon: "⚡",
|
|
46
|
+
title: "Lightning Fast",
|
|
47
|
+
description:
|
|
48
|
+
"Pre-rendered HTML with zero JavaScript by default. Your pages load instantly.",
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
icon: "🧱",
|
|
52
|
+
title: "Block-Based",
|
|
53
|
+
description:
|
|
54
|
+
"Compose pages from reusable blocks with type-safe props and CMS-ready schemas.",
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
icon: "🎨",
|
|
58
|
+
title: "Design System Ready",
|
|
59
|
+
description:
|
|
60
|
+
"Built-in layout primitives and design tokens. Customize everything with CSS.",
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
icon: "📝",
|
|
64
|
+
title: "CMS Compatible",
|
|
65
|
+
description:
|
|
66
|
+
"Export your content schemas for use with any headless CMS.",
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
icon: "🔧",
|
|
70
|
+
title: "Developer Experience",
|
|
71
|
+
description:
|
|
72
|
+
"Hot reload, TypeScript everywhere, and a simple mental model.",
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
icon: "🚀",
|
|
76
|
+
title: "Deploy Anywhere",
|
|
77
|
+
description:
|
|
78
|
+
"Output is plain HTML/CSS/JS. Deploy to any static host.",
|
|
79
|
+
},
|
|
80
|
+
],
|
|
81
|
+
},
|
|
82
|
+
layout: {
|
|
83
|
+
tone: "surface",
|
|
84
|
+
contentAlign: "center",
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
id: "cta-1",
|
|
89
|
+
type: "textSection",
|
|
90
|
+
props: {
|
|
91
|
+
headline: "Ready to build?",
|
|
92
|
+
body: "<p>Get started with Static Kit in minutes. Install the CLI, create a new project, and start building beautiful static sites.</p>",
|
|
93
|
+
cta: {
|
|
94
|
+
href: "/docs/getting-started",
|
|
95
|
+
label: "Read the Docs",
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
layout: {
|
|
99
|
+
tone: "raised",
|
|
100
|
+
contentAlign: "center",
|
|
101
|
+
contentWidth: "narrow",
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
],
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { PageConfig } from "@vojtaholik/static-kit-core";
|
|
2
|
+
import { indexPage } from "./index.page.ts";
|
|
3
|
+
import { aboutPage } from "./about.page.ts";
|
|
4
|
+
|
|
5
|
+
// All pages in the site
|
|
6
|
+
export const pages: PageConfig[] = [indexPage, aboutPage];
|
|
7
|
+
|
|
8
|
+
// Get page by path
|
|
9
|
+
export function getPageByPath(path: string): PageConfig | undefined {
|
|
10
|
+
return pages.find((p) => p.path === path);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// Get page by id
|
|
14
|
+
export function getPageById(id: string): PageConfig | undefined {
|
|
15
|
+
return pages.find((p) => p.id === id);
|
|
16
|
+
}
|