create-spark-html-app 0.11.0 → 0.12.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/bin/index.js +7 -5
- package/package.json +1 -1
- package/template/README.md +9 -68
- package/template/_gitignore +0 -2
- package/template/index.html +4 -204
- package/template/package.json +2 -12
- package/template/public/components/hero.html +12 -64
- package/template/src/main.js +2 -61
- package/template/src/style.css +32 -0
- package/template-prerender/README.md +71 -8
- package/template-prerender/_gitignore +2 -0
- package/template-prerender/index.html +206 -5
- package/template-prerender/package.json +12 -3
- package/template-prerender/public/components/hero.html +71 -10
- package/template-prerender/spark.config.js +68 -5
- package/template-prerender/src/main.js +61 -2
- package/template-ssr/components/nav.html +6 -5
- package/template-ssr/pages/_layout.html +1 -1
- package/template-ssr/public/style.css +113 -54
- package/template-ssr/spark.json +1 -1
- package/template/spark.config.js +0 -72
- package/template-prerender/src/style.css +0 -3
- /package/{template → template-prerender}/public/components/about.html +0 -0
- /package/{template → template-prerender}/public/components/demo-await.html +0 -0
- /package/{template → template-prerender}/public/components/demo-image.html +0 -0
- /package/{template → template-prerender}/public/components/demo-persist.html +0 -0
- /package/{template → template-prerender}/public/components/demo-props.html +0 -0
- /package/{template → template-prerender}/public/components/demo-todo.html +0 -0
- /package/{template → template-prerender}/public/components/feature-card.html +0 -0
- /package/{template → template-prerender}/public/components/footer.html +0 -0
- /package/{template → template-prerender}/public/components/home.html +0 -0
- /package/{template → template-prerender}/public/components/nav.html +0 -0
- /package/{template → template-prerender}/public/icon.png +0 -0
- /package/{template → template-prerender}/public/lib/format.js +0 -0
- /package/{template → template-prerender}/public/sample.jpg +0 -0
|
@@ -1,42 +1,64 @@
|
|
|
1
|
-
/* One stylesheet for the whole blog
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
/* One stylesheet for the whole blog — the same design system as the Spark
|
|
2
|
+
showcase: monospace JetBrains Mono type, a gold --spark accent, rounded
|
|
3
|
+
surfaces. Fonts come from spark.json ("fonts" → spark-html-font injects
|
|
4
|
+
@font-face + the --font-jetbrains-mono stack); theming is the data-theme
|
|
5
|
+
attribute spark-html-theme maintains (dark is the default). */
|
|
4
6
|
|
|
5
7
|
:root {
|
|
6
|
-
--bg: #
|
|
7
|
-
--
|
|
8
|
-
--
|
|
9
|
-
--
|
|
10
|
-
--
|
|
11
|
-
--
|
|
12
|
-
--
|
|
8
|
+
--bg: #000;
|
|
9
|
+
--surface: #0a0a0a;
|
|
10
|
+
--surface-2: #101014;
|
|
11
|
+
--border: #1a1a1a;
|
|
12
|
+
--border-strong: #333;
|
|
13
|
+
--text: #fff;
|
|
14
|
+
--muted: #888;
|
|
15
|
+
--muted-dim: #555;
|
|
16
|
+
--spark: #ffd24a;
|
|
17
|
+
--spark-ink: #ffd24a;
|
|
18
|
+
--danger: #ff6b6b;
|
|
19
|
+
--radius: 12px;
|
|
20
|
+
--font: var(--font-jetbrains-mono, "JetBrains Mono", ui-monospace, monospace);
|
|
13
21
|
}
|
|
14
22
|
|
|
15
|
-
[data-theme="
|
|
16
|
-
--bg: #
|
|
17
|
-
--
|
|
18
|
-
--
|
|
19
|
-
--
|
|
20
|
-
--
|
|
21
|
-
--
|
|
22
|
-
--
|
|
23
|
+
[data-theme="light"] {
|
|
24
|
+
--bg: #fff;
|
|
25
|
+
--surface: #fafafa;
|
|
26
|
+
--surface-2: #f4f4f5;
|
|
27
|
+
--border: #ededed;
|
|
28
|
+
--border-strong: #d4d4d4;
|
|
29
|
+
--text: #1a1a1a;
|
|
30
|
+
--muted: #666;
|
|
31
|
+
--muted-dim: #999;
|
|
32
|
+
--spark: #ffd24a;
|
|
33
|
+
--spark-ink: #9a6a00;
|
|
34
|
+
--danger: #d63b3b;
|
|
23
35
|
}
|
|
24
36
|
|
|
25
|
-
|
|
37
|
+
*, *::before, *::after { box-sizing: border-box; }
|
|
26
38
|
|
|
27
39
|
body {
|
|
28
40
|
margin: 0 auto;
|
|
29
|
-
max-width:
|
|
41
|
+
max-width: 720px;
|
|
30
42
|
padding: 0 1.25rem 4rem;
|
|
31
|
-
font-family: var(--font
|
|
43
|
+
font-family: var(--font);
|
|
32
44
|
line-height: 1.6;
|
|
33
45
|
background: var(--bg);
|
|
34
46
|
color: var(--text);
|
|
47
|
+
-webkit-font-smoothing: antialiased;
|
|
35
48
|
}
|
|
36
49
|
|
|
37
|
-
a { color: var(--
|
|
50
|
+
a { color: var(--spark-ink); text-decoration: none; }
|
|
38
51
|
a:hover { text-decoration: underline; }
|
|
39
|
-
h1, h2, h3 { line-height: 1.2; }
|
|
52
|
+
h1, h2, h3 { line-height: 1.2; letter-spacing: -0.02em; }
|
|
53
|
+
::selection { background: var(--spark); color: #000; }
|
|
54
|
+
[data-theme="light"] ::selection { background: #ffe9a8; color: #111; }
|
|
55
|
+
code {
|
|
56
|
+
background: var(--surface-2);
|
|
57
|
+
color: var(--spark-ink);
|
|
58
|
+
padding: 1px 6px;
|
|
59
|
+
border-radius: 4px;
|
|
60
|
+
font-size: 0.85em;
|
|
61
|
+
}
|
|
40
62
|
|
|
41
63
|
/* ── nav ── */
|
|
42
64
|
.nav {
|
|
@@ -44,73 +66,110 @@ h1, h2, h3 { line-height: 1.2; }
|
|
|
44
66
|
justify-content: space-between;
|
|
45
67
|
align-items: center;
|
|
46
68
|
gap: 1rem;
|
|
47
|
-
padding:
|
|
69
|
+
padding: 1rem 0;
|
|
70
|
+
margin-bottom: 1rem;
|
|
71
|
+
border-bottom: 1px solid var(--border);
|
|
72
|
+
}
|
|
73
|
+
.nav .brand {
|
|
74
|
+
font-weight: 700;
|
|
75
|
+
color: var(--text);
|
|
76
|
+
display: inline-flex;
|
|
77
|
+
align-items: center;
|
|
78
|
+
gap: 0.4rem;
|
|
79
|
+
}
|
|
80
|
+
.nav .links { display: flex; align-items: center; gap: 0.35rem; }
|
|
81
|
+
.nav .links a {
|
|
82
|
+
color: var(--muted);
|
|
83
|
+
padding: 0.35rem 0.6rem;
|
|
84
|
+
border-radius: 8px;
|
|
85
|
+
font-size: 0.9rem;
|
|
86
|
+
transition: color 0.12s, background 0.12s;
|
|
48
87
|
}
|
|
49
|
-
.nav .
|
|
50
|
-
.nav .links {
|
|
51
|
-
.nav .links a.on { color: var(--text); font-weight: 700; }
|
|
88
|
+
.nav .links a:hover { color: var(--text); background: var(--surface-2); text-decoration: none; }
|
|
89
|
+
.nav .links a.on { color: var(--spark-ink); background: var(--surface-2); font-weight: 700; }
|
|
52
90
|
|
|
53
91
|
/* ── home ── */
|
|
54
92
|
.hero { display: flex; gap: 1.25rem; align-items: center; margin: 2rem 0 2.5rem; }
|
|
55
|
-
.hero h1 { margin: 0 0 0.25rem; }
|
|
56
|
-
.avatar { border-radius: 50%; }
|
|
93
|
+
.hero h1 { margin: 0 0 0.25rem; font-size: clamp(1.6rem, 5vw, 2.2rem); }
|
|
94
|
+
.avatar { border-radius: 50%; border: 1px solid var(--border-strong); }
|
|
57
95
|
.lede { color: var(--muted); margin: 0; }
|
|
58
96
|
|
|
59
97
|
.card {
|
|
60
|
-
background: var(--
|
|
61
|
-
border: 1px solid var(--
|
|
62
|
-
border-radius:
|
|
98
|
+
background: var(--surface);
|
|
99
|
+
border: 1px solid var(--border);
|
|
100
|
+
border-radius: var(--radius);
|
|
63
101
|
padding: 1rem 1.25rem;
|
|
64
102
|
margin: 0 0 1rem;
|
|
103
|
+
transition: border-color 0.12s;
|
|
65
104
|
}
|
|
66
|
-
.card
|
|
67
|
-
.card
|
|
68
|
-
.
|
|
105
|
+
.card:hover { border-color: var(--border-strong); }
|
|
106
|
+
.card h2 { margin: 0 0 0.35rem; font-size: 1.1rem; }
|
|
107
|
+
.card h2 a { color: var(--text); }
|
|
108
|
+
.card h2 a:hover { color: var(--spark-ink); text-decoration: none; }
|
|
109
|
+
.card p { margin: 0 0 0.35rem; color: var(--muted); }
|
|
110
|
+
.meta { color: var(--muted-dim); font-size: 0.8rem; }
|
|
69
111
|
.empty { color: var(--muted); }
|
|
70
112
|
|
|
71
113
|
/* ── post page ── */
|
|
72
114
|
.post { margin-top: 2rem; }
|
|
73
|
-
.post
|
|
115
|
+
.post h1 { font-size: clamp(1.8rem, 6vw, 2.4rem); font-weight: 800; }
|
|
116
|
+
.post .lede { margin: 0.75rem 0; }
|
|
117
|
+
.post .body { white-space: pre-line; margin-top: 1.5rem; color: var(--text); }
|
|
74
118
|
.pill {
|
|
75
|
-
font-size: 0.
|
|
119
|
+
font-size: 0.7rem;
|
|
76
120
|
font-weight: 700;
|
|
77
|
-
padding: 0.1rem 0.
|
|
121
|
+
padding: 0.1rem 0.55rem;
|
|
78
122
|
border-radius: 999px;
|
|
79
123
|
vertical-align: middle;
|
|
80
124
|
}
|
|
81
|
-
.pill.draft { background: var(--spark); color: #
|
|
125
|
+
.pill.draft { background: var(--spark); color: #000; }
|
|
82
126
|
.pill.live { background: #16a34a; color: #fff; }
|
|
83
127
|
|
|
84
128
|
/* ── admin ── */
|
|
85
129
|
.admin-head { display: flex; justify-content: space-between; align-items: center; }
|
|
86
130
|
.panel {
|
|
87
|
-
background: var(--
|
|
88
|
-
border: 1px solid var(--
|
|
89
|
-
border-radius:
|
|
131
|
+
background: var(--surface);
|
|
132
|
+
border: 1px solid var(--border);
|
|
133
|
+
border-radius: var(--radius);
|
|
90
134
|
padding: 1.25rem;
|
|
91
135
|
margin: 0 0 1.25rem;
|
|
92
136
|
}
|
|
93
|
-
.panel h2 { margin-top: 0; }
|
|
137
|
+
.panel h2 { margin-top: 0; font-size: 1.15rem; }
|
|
138
|
+
.panel h3 { margin: 1.25rem 0 0.5rem; font-size: 0.95rem; color: var(--muted); }
|
|
94
139
|
.row { display: flex; align-items: center; gap: 0.6rem; margin: 0.4rem 0; }
|
|
95
140
|
.grow { flex: 1; }
|
|
96
|
-
.done { text-decoration: line-through; color: var(--muted); }
|
|
141
|
+
.done { text-decoration: line-through; color: var(--muted-dim); }
|
|
97
142
|
.hint { color: var(--muted); font-size: 0.85rem; }
|
|
98
|
-
.error { color:
|
|
143
|
+
.error { color: var(--danger); }
|
|
99
144
|
|
|
100
|
-
|
|
145
|
+
/* ── forms & buttons ── */
|
|
146
|
+
input, textarea {
|
|
101
147
|
font: inherit;
|
|
102
|
-
color:
|
|
148
|
+
color: var(--text);
|
|
103
149
|
background: var(--bg);
|
|
104
|
-
border: 1px solid var(--
|
|
150
|
+
border: 1px solid var(--border-strong);
|
|
105
151
|
border-radius: 8px;
|
|
106
|
-
padding: 0.
|
|
152
|
+
padding: 0.5rem 0.7rem;
|
|
107
153
|
}
|
|
154
|
+
input:focus, textarea:focus { outline: none; border-color: var(--spark); }
|
|
108
155
|
.login { max-width: 380px; margin: 3rem auto; display: grid; gap: 0.75rem; }
|
|
109
|
-
.login label { display: grid; gap: 0.25rem; font-size: 0.9rem; }
|
|
156
|
+
.login label { display: grid; gap: 0.25rem; font-size: 0.9rem; color: var(--muted); }
|
|
110
157
|
.panel input, .panel textarea { width: 100%; margin: 0.25rem 0; }
|
|
111
158
|
.row input, .row button { width: auto; margin: 0; }
|
|
112
|
-
|
|
113
|
-
button
|
|
114
|
-
|
|
115
|
-
|
|
159
|
+
|
|
160
|
+
button {
|
|
161
|
+
font: inherit;
|
|
162
|
+
cursor: pointer;
|
|
163
|
+
color: var(--text);
|
|
164
|
+
background: var(--surface-2);
|
|
165
|
+
border: 1px solid var(--border-strong);
|
|
166
|
+
border-radius: 8px;
|
|
167
|
+
padding: 0.5rem 0.8rem;
|
|
168
|
+
transition: border-color 0.12s, color 0.12s, transform 0.08s;
|
|
169
|
+
}
|
|
170
|
+
button:hover:not(:disabled) { border-color: var(--spark); color: var(--spark-ink); }
|
|
171
|
+
button:active:not(:disabled) { transform: scale(0.97); }
|
|
172
|
+
button:disabled { opacity: 0.4; cursor: default; }
|
|
173
|
+
button.danger:hover:not(:disabled) { border-color: var(--danger); color: var(--danger); }
|
|
116
174
|
button.ghost, button.toggle { border: none; background: none; padding: 0.2rem; }
|
|
175
|
+
button.ghost:hover:not(:disabled), button.toggle:hover:not(:disabled) { color: var(--spark-ink); transform: none; }
|
package/template-ssr/spark.json
CHANGED
package/template/spark.config.js
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import prerender from 'spark-prerender/bun';
|
|
2
|
-
// @spark:theme
|
|
3
|
-
import theme from 'spark-html-theme/bun';
|
|
4
|
-
// @spark:end
|
|
5
|
-
// @spark:font
|
|
6
|
-
import font from 'spark-html-font/bun';
|
|
7
|
-
// @spark:end
|
|
8
|
-
// @spark:image
|
|
9
|
-
import image from 'spark-html-image/bun';
|
|
10
|
-
// @spark:end
|
|
11
|
-
// @spark:pwa
|
|
12
|
-
import manifest from 'spark-html-manifest/bun';
|
|
13
|
-
// @spark:end
|
|
14
|
-
// @spark:sri
|
|
15
|
-
import sri from 'spark-html-sri/bun';
|
|
16
|
-
// @spark:end
|
|
17
|
-
|
|
18
|
-
// Spark needs no build step — spark-html-bun is just a fast dev server and a
|
|
19
|
-
// bundler for your app shell. `spark dev` serves component fragments raw and
|
|
20
|
-
// hot-reloads only the edited component; components live in public/ so they
|
|
21
|
-
// ship verbatim to the production build too.
|
|
22
|
-
//
|
|
23
|
-
// The `pipeline` runs in order after `spark build` copies public/ and bundles
|
|
24
|
-
// the entry. Order matters: prerender() first (it writes one HTML file per
|
|
25
|
-
// route), then the steps that rewrite those pages — sri() must be last so it
|
|
26
|
-
// hashes the final bytes.
|
|
27
|
-
//
|
|
28
|
-
// `prerender()` makes `bun run build` SEO-friendly: it runs your app at build
|
|
29
|
-
// time and writes fully-rendered HTML into dist/ (crawlers and AI tools read
|
|
30
|
-
// real content; the browser still hydrates over it), plus sitemap.xml +
|
|
31
|
-
// robots.txt. Remove it if you don't need SEO.
|
|
32
|
-
export default {
|
|
33
|
-
pipeline: [
|
|
34
|
-
prerender({ pages: ['index.html'] }),
|
|
35
|
-
// @spark:theme
|
|
36
|
-
// Bakes the tiny no-flash script into each page (dev too) so the saved /
|
|
37
|
-
// OS theme is on <html> before first paint — no wrong-theme flash on load.
|
|
38
|
-
theme(),
|
|
39
|
-
// @spark:end
|
|
40
|
-
// @spark:font
|
|
41
|
-
// Preconnect + the Google stylesheet + a size-adjusted local fallback
|
|
42
|
-
// face, baked into each page (dev too) — the font swap never moves or
|
|
43
|
-
// visibly reflows the page.
|
|
44
|
-
font({
|
|
45
|
-
fallback: ['ui-monospace', 'monospace'],
|
|
46
|
-
fonts: [{ family: 'JetBrains Mono', google: true, weights: [300, 400, 500, 600, 700, 800] }],
|
|
47
|
-
}),
|
|
48
|
-
// @spark:end
|
|
49
|
-
// @spark:image
|
|
50
|
-
// Every <img> in pages and components: converted to webp/avif at multiple
|
|
51
|
-
// widths, srcset + width/height added (no layout shift), loading="lazy".
|
|
52
|
-
// Zero config.
|
|
53
|
-
image(),
|
|
54
|
-
// @spark:end
|
|
55
|
-
// @spark:pwa
|
|
56
|
-
// One config → manifest.webmanifest + resized icons + <head> tags + an
|
|
57
|
-
// offline app-shell service worker (registered automatically).
|
|
58
|
-
manifest({
|
|
59
|
-
name: 'Spark App',
|
|
60
|
-
themeColor: '#ffd24a',
|
|
61
|
-
icon: 'public/icon.png',
|
|
62
|
-
offline: true,
|
|
63
|
-
}),
|
|
64
|
-
// @spark:end
|
|
65
|
-
// @spark:sri
|
|
66
|
-
// Hashes every built asset + component, stamps integrity/crossorigin onto
|
|
67
|
-
// script/link tags, and bakes the verify manifest into each page. Keep it
|
|
68
|
-
// LAST so it sees the final pages.
|
|
69
|
-
sri(),
|
|
70
|
-
// @spark:end
|
|
71
|
-
],
|
|
72
|
-
};
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|