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.
Files changed (35) hide show
  1. package/bin/index.js +7 -5
  2. package/package.json +1 -1
  3. package/template/README.md +9 -68
  4. package/template/_gitignore +0 -2
  5. package/template/index.html +4 -204
  6. package/template/package.json +2 -12
  7. package/template/public/components/hero.html +12 -64
  8. package/template/src/main.js +2 -61
  9. package/template/src/style.css +32 -0
  10. package/template-prerender/README.md +71 -8
  11. package/template-prerender/_gitignore +2 -0
  12. package/template-prerender/index.html +206 -5
  13. package/template-prerender/package.json +12 -3
  14. package/template-prerender/public/components/hero.html +71 -10
  15. package/template-prerender/spark.config.js +68 -5
  16. package/template-prerender/src/main.js +61 -2
  17. package/template-ssr/components/nav.html +6 -5
  18. package/template-ssr/pages/_layout.html +1 -1
  19. package/template-ssr/public/style.css +113 -54
  20. package/template-ssr/spark.json +1 -1
  21. package/template/spark.config.js +0 -72
  22. package/template-prerender/src/style.css +0 -3
  23. /package/{template → template-prerender}/public/components/about.html +0 -0
  24. /package/{template → template-prerender}/public/components/demo-await.html +0 -0
  25. /package/{template → template-prerender}/public/components/demo-image.html +0 -0
  26. /package/{template → template-prerender}/public/components/demo-persist.html +0 -0
  27. /package/{template → template-prerender}/public/components/demo-props.html +0 -0
  28. /package/{template → template-prerender}/public/components/demo-todo.html +0 -0
  29. /package/{template → template-prerender}/public/components/feature-card.html +0 -0
  30. /package/{template → template-prerender}/public/components/footer.html +0 -0
  31. /package/{template → template-prerender}/public/components/home.html +0 -0
  32. /package/{template → template-prerender}/public/components/nav.html +0 -0
  33. /package/{template → template-prerender}/public/icon.png +0 -0
  34. /package/{template → template-prerender}/public/lib/format.js +0 -0
  35. /package/{template → template-prerender}/public/sample.jpg +0 -0
@@ -1,42 +1,64 @@
1
- /* One stylesheet for the whole blog. Fonts come from spark.json ("fonts"
2
- spark-html-font injects @font-face + the --font-inter stack); theming is
3
- the data-theme attribute spark-html-theme maintains. */
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: #fdfcf9;
7
- --panel: #ffffff;
8
- --text: #1c1917;
9
- --muted: #78716c;
10
- --line: #e7e5e4;
11
- --accent: #b45309;
12
- --spark: #f59e0b;
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="dark"] {
16
- --bg: #131110;
17
- --panel: #1c1917;
18
- --text: #e7e5e4;
19
- --muted: #a8a29e;
20
- --line: #292524;
21
- --accent: #fbbf24;
22
- --spark: #f59e0b;
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
- * { box-sizing: border-box; }
37
+ *, *::before, *::after { box-sizing: border-box; }
26
38
 
27
39
  body {
28
40
  margin: 0 auto;
29
- max-width: 680px;
41
+ max-width: 720px;
30
42
  padding: 0 1.25rem 4rem;
31
- font-family: var(--font-inter, system-ui, sans-serif);
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(--accent); text-decoration: none; }
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: 1.25rem 0;
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 .brand { font-weight: 700; color: var(--text); }
50
- .nav .links { display: flex; align-items: center; gap: 1rem; }
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(--panel);
61
- border: 1px solid var(--line);
62
- border-radius: 10px;
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 h2 { margin: 0 0 0.35rem; font-size: 1.15rem; }
67
- .card p { margin: 0 0 0.35rem; color: var(--text); }
68
- .meta { color: var(--muted); font-size: 0.85rem; }
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 .body { white-space: pre-line; margin-top: 1.5rem; }
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.72rem;
119
+ font-size: 0.7rem;
76
120
  font-weight: 700;
77
- padding: 0.1rem 0.5rem;
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: #1c1917; }
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(--panel);
88
- border: 1px solid var(--line);
89
- border-radius: 10px;
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: #dc2626; }
143
+ .error { color: var(--danger); }
99
144
 
100
- input, textarea, button {
145
+ /* ── forms & buttons ── */
146
+ input, textarea {
101
147
  font: inherit;
102
- color: inherit;
148
+ color: var(--text);
103
149
  background: var(--bg);
104
- border: 1px solid var(--line);
150
+ border: 1px solid var(--border-strong);
105
151
  border-radius: 8px;
106
- padding: 0.45rem 0.7rem;
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
- button { cursor: pointer; background: var(--panel); }
113
- button:hover { border-color: var(--accent); }
114
- button:disabled { opacity: 0.5; cursor: default; }
115
- button.danger:hover { border-color: #dc2626; color: #dc2626; }
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; }
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "db": "sqlite://./dev.db",
3
3
  "auth": { "table": "users", "identity": "email" },
4
- "fonts": [{ "family": "Inter", "google": true, "weights": [400, 700] }]
4
+ "fonts": [{ "family": "JetBrains Mono", "google": true, "weights": [400, 500, 700, 800] }]
5
5
  }
@@ -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
- };
@@ -1,3 +0,0 @@
1
- body { font-family: system-ui, sans-serif; max-width: 36rem; margin: 4rem auto; padding: 0 1.5rem; }
2
- main { text-align: center; }
3
- button { padding: 0.5rem 1rem; cursor: pointer; }