create-zoijs 0.1.3 → 0.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/CHANGELOG.md +127 -74
- package/LICENSE +21 -21
- package/README.md +98 -97
- package/bin/create-zoijs.js +197 -169
- package/core-cdn.json +36 -0
- package/package.json +44 -43
- package/templates/app/README.md +68 -48
- package/templates/app/_gitignore +1 -1
- package/templates/app/_vscode/extensions.json +7 -0
- package/templates/app/dev-server.mjs +124 -74
- package/templates/app/index.html +24 -22
- package/templates/app/jsconfig.json +16 -0
- package/templates/app/package.json +12 -12
- package/templates/app/src/app.js +98 -98
- package/templates/app/src/components/Header.js +16 -16
- package/templates/app/src/components/StatCard.js +13 -13
- package/templates/app/src/components/TaskItem.js +18 -18
- package/templates/app/src/style.css +241 -241
- package/templates/basic/README.md +50 -30
- package/templates/basic/_gitignore +1 -1
- package/templates/basic/_vscode/extensions.json +7 -0
- package/templates/basic/dev-server.mjs +124 -74
- package/templates/basic/index.html +24 -22
- package/templates/basic/jsconfig.json +16 -0
- package/templates/basic/package.json +12 -12
- package/templates/basic/src/app.js +18 -18
- package/templates/basic/src/style.css +33 -33
- package/templates/library/_vscode/extensions.json +7 -0
- package/templates/library/package.json +2 -2
- package/templates/minimal/README.md +29 -8
- package/templates/minimal/dev-server.mjs +124 -0
- package/templates/minimal/index.html +5 -3
- package/templates/minimal/package.json +9 -0
- package/templates/typescript/README.md +20 -0
- package/templates/typescript/_gitignore +1 -1
- package/templates/typescript/_vscode/extensions.json +7 -0
- package/templates/typescript/dev-server.mjs +124 -74
- package/templates/typescript/index.html +24 -22
- package/templates/typescript/package.json +1 -1
- package/templates/typescript/src/style.css +33 -33
|
@@ -1,241 +1,241 @@
|
|
|
1
|
-
/* A small, polished dashboard theme — plain CSS, no framework.
|
|
2
|
-
Adapts to light/dark automatically and stays readable on mobile. */
|
|
3
|
-
|
|
4
|
-
:root {
|
|
5
|
-
color-scheme: light dark;
|
|
6
|
-
--bg: #f6f7fb;
|
|
7
|
-
--panel: #ffffff;
|
|
8
|
-
--text: #1e2230;
|
|
9
|
-
--muted: #6b7280;
|
|
10
|
-
--border: #e6e8ef;
|
|
11
|
-
--accent: #6366f1;
|
|
12
|
-
--accent-2: #8b5cf6;
|
|
13
|
-
--radius: 14px;
|
|
14
|
-
--shadow: 0 1px 2px rgba(20, 22, 40, 0.04), 0 8px 24px rgba(20, 22, 40, 0.06);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
@media (prefers-color-scheme: dark) {
|
|
18
|
-
:root {
|
|
19
|
-
--bg: #0e1016;
|
|
20
|
-
--panel: #171a22;
|
|
21
|
-
--text: #e7e9f0;
|
|
22
|
-
--muted: #9aa1b1;
|
|
23
|
-
--border: #262a36;
|
|
24
|
-
--shadow: 0 1px 2px rgba(0, 0, 0, 0.3), 0 10px 30px rgba(0, 0, 0, 0.35);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
* {
|
|
29
|
-
box-sizing: border-box;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
body {
|
|
33
|
-
margin: 0;
|
|
34
|
-
min-height: 100vh;
|
|
35
|
-
font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
|
|
36
|
-
line-height: 1.5;
|
|
37
|
-
color: var(--text);
|
|
38
|
-
background:
|
|
39
|
-
radial-gradient(1200px 500px at 50% -200px, rgba(99, 102, 241, 0.18), transparent 70%),
|
|
40
|
-
var(--bg);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
.app {
|
|
44
|
-
width: min(56rem, 92vw);
|
|
45
|
-
margin: 0 auto;
|
|
46
|
-
padding: clamp(1.5rem, 4vw, 3rem) 0 3rem;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/* --- hero ------------------------------------------------------------------ */
|
|
50
|
-
.hero {
|
|
51
|
-
text-align: center;
|
|
52
|
-
margin-bottom: 1.75rem;
|
|
53
|
-
}
|
|
54
|
-
.badge {
|
|
55
|
-
display: inline-block;
|
|
56
|
-
font-size: 0.72rem;
|
|
57
|
-
font-weight: 600;
|
|
58
|
-
letter-spacing: 0.04em;
|
|
59
|
-
text-transform: uppercase;
|
|
60
|
-
color: #fff;
|
|
61
|
-
background: linear-gradient(135deg, var(--accent), var(--accent-2));
|
|
62
|
-
padding: 0.3rem 0.7rem;
|
|
63
|
-
border-radius: 999px;
|
|
64
|
-
}
|
|
65
|
-
.hero h1 {
|
|
66
|
-
margin: 0.7rem 0 0.25rem;
|
|
67
|
-
font-size: clamp(1.8rem, 5vw, 2.6rem);
|
|
68
|
-
letter-spacing: -0.02em;
|
|
69
|
-
}
|
|
70
|
-
.tagline {
|
|
71
|
-
margin: 0 auto;
|
|
72
|
-
max-width: 34rem;
|
|
73
|
-
color: var(--muted);
|
|
74
|
-
}
|
|
75
|
-
.summary {
|
|
76
|
-
margin: 0.6rem 0 0;
|
|
77
|
-
color: var(--muted);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/* --- cards & stats --------------------------------------------------------- */
|
|
81
|
-
.card {
|
|
82
|
-
background: var(--panel);
|
|
83
|
-
border: 1px solid var(--border);
|
|
84
|
-
border-radius: var(--radius);
|
|
85
|
-
box-shadow: var(--shadow);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
.stats {
|
|
89
|
-
display: grid;
|
|
90
|
-
grid-template-columns: repeat(auto-fit, minmax(8.5rem, 1fr));
|
|
91
|
-
gap: 0.9rem;
|
|
92
|
-
margin-bottom: 1.25rem;
|
|
93
|
-
}
|
|
94
|
-
.stat {
|
|
95
|
-
padding: 1rem 1.1rem;
|
|
96
|
-
border-left: 3px solid var(--accent);
|
|
97
|
-
}
|
|
98
|
-
.stat-indigo { border-left-color: #6366f1; }
|
|
99
|
-
.stat-green { border-left-color: #10b981; }
|
|
100
|
-
.stat-amber { border-left-color: #f59e0b; }
|
|
101
|
-
.stat-slate { border-left-color: #64748b; }
|
|
102
|
-
.stat-value {
|
|
103
|
-
font-size: 1.7rem;
|
|
104
|
-
font-weight: 700;
|
|
105
|
-
text-transform: capitalize;
|
|
106
|
-
}
|
|
107
|
-
.stat-label {
|
|
108
|
-
font-size: 0.85rem;
|
|
109
|
-
color: var(--muted);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/* --- task panel ------------------------------------------------------------ */
|
|
113
|
-
.panel {
|
|
114
|
-
background: var(--panel);
|
|
115
|
-
border: 1px solid var(--border);
|
|
116
|
-
border-radius: var(--radius);
|
|
117
|
-
box-shadow: var(--shadow);
|
|
118
|
-
padding: 1.25rem;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
.add {
|
|
122
|
-
display: flex;
|
|
123
|
-
gap: 0.5rem;
|
|
124
|
-
margin-bottom: 0.9rem;
|
|
125
|
-
}
|
|
126
|
-
.add input {
|
|
127
|
-
flex: 1;
|
|
128
|
-
font: inherit;
|
|
129
|
-
padding: 0.6rem 0.8rem;
|
|
130
|
-
color: var(--text);
|
|
131
|
-
background: transparent;
|
|
132
|
-
border: 1px solid var(--border);
|
|
133
|
-
border-radius: 10px;
|
|
134
|
-
}
|
|
135
|
-
.add input:focus-visible {
|
|
136
|
-
outline: 2px solid var(--accent);
|
|
137
|
-
outline-offset: 1px;
|
|
138
|
-
}
|
|
139
|
-
button {
|
|
140
|
-
font: inherit;
|
|
141
|
-
cursor: pointer;
|
|
142
|
-
border-radius: 10px;
|
|
143
|
-
border: 1px solid transparent;
|
|
144
|
-
}
|
|
145
|
-
.add button {
|
|
146
|
-
padding: 0.6rem 1.1rem;
|
|
147
|
-
color: #fff;
|
|
148
|
-
background: linear-gradient(135deg, var(--accent), var(--accent-2));
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
.filters {
|
|
152
|
-
display: flex;
|
|
153
|
-
gap: 0.4rem;
|
|
154
|
-
margin-bottom: 0.9rem;
|
|
155
|
-
}
|
|
156
|
-
.chip {
|
|
157
|
-
padding: 0.35rem 0.85rem;
|
|
158
|
-
color: var(--muted);
|
|
159
|
-
background: transparent;
|
|
160
|
-
border: 1px solid var(--border);
|
|
161
|
-
}
|
|
162
|
-
.chip-on {
|
|
163
|
-
color: var(--text);
|
|
164
|
-
border-color: var(--accent);
|
|
165
|
-
background: color-mix(in srgb, var(--accent) 12%, transparent);
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
.tasks {
|
|
169
|
-
list-style: none;
|
|
170
|
-
margin: 0;
|
|
171
|
-
padding: 0;
|
|
172
|
-
display: grid;
|
|
173
|
-
gap: 0.45rem;
|
|
174
|
-
}
|
|
175
|
-
.task {
|
|
176
|
-
display: flex;
|
|
177
|
-
align-items: center;
|
|
178
|
-
justify-content: space-between;
|
|
179
|
-
gap: 0.6rem;
|
|
180
|
-
padding: 0.6rem 0.75rem;
|
|
181
|
-
border: 1px solid var(--border);
|
|
182
|
-
border-radius: 10px;
|
|
183
|
-
}
|
|
184
|
-
.task label {
|
|
185
|
-
display: flex;
|
|
186
|
-
align-items: center;
|
|
187
|
-
gap: 0.6rem;
|
|
188
|
-
cursor: pointer;
|
|
189
|
-
}
|
|
190
|
-
.task input[type="checkbox"] {
|
|
191
|
-
width: 1.1rem;
|
|
192
|
-
height: 1.1rem;
|
|
193
|
-
accent-color: var(--accent);
|
|
194
|
-
}
|
|
195
|
-
.task.done span {
|
|
196
|
-
text-decoration: line-through;
|
|
197
|
-
color: var(--muted);
|
|
198
|
-
}
|
|
199
|
-
.delete {
|
|
200
|
-
border: none;
|
|
201
|
-
background: transparent;
|
|
202
|
-
color: var(--muted);
|
|
203
|
-
padding: 0.2rem 0.5rem;
|
|
204
|
-
font-size: 1rem;
|
|
205
|
-
}
|
|
206
|
-
.delete:hover {
|
|
207
|
-
color: #ef4444;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
.empty {
|
|
211
|
-
text-align: center;
|
|
212
|
-
color: var(--muted);
|
|
213
|
-
padding: 1.5rem 0 0.5rem;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
/* --- dev hint -------------------------------------------------------------- */
|
|
217
|
-
.hint {
|
|
218
|
-
text-align: center;
|
|
219
|
-
color: var(--muted);
|
|
220
|
-
font-size: 0.9rem;
|
|
221
|
-
margin-top: 1.5rem;
|
|
222
|
-
}
|
|
223
|
-
.hint p {
|
|
224
|
-
margin: 0.2rem 0;
|
|
225
|
-
}
|
|
226
|
-
code {
|
|
227
|
-
font-family: ui-monospace, "SF Mono", Menlo, monospace;
|
|
228
|
-
font-size: 0.85em;
|
|
229
|
-
padding: 0.1rem 0.35rem;
|
|
230
|
-
border-radius: 6px;
|
|
231
|
-
background: color-mix(in srgb, var(--accent) 12%, transparent);
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
@media (max-width: 30rem) {
|
|
235
|
-
.add {
|
|
236
|
-
flex-direction: column;
|
|
237
|
-
}
|
|
238
|
-
.add button {
|
|
239
|
-
width: 100%;
|
|
240
|
-
}
|
|
241
|
-
}
|
|
1
|
+
/* A small, polished dashboard theme — plain CSS, no framework.
|
|
2
|
+
Adapts to light/dark automatically and stays readable on mobile. */
|
|
3
|
+
|
|
4
|
+
:root {
|
|
5
|
+
color-scheme: light dark;
|
|
6
|
+
--bg: #f6f7fb;
|
|
7
|
+
--panel: #ffffff;
|
|
8
|
+
--text: #1e2230;
|
|
9
|
+
--muted: #6b7280;
|
|
10
|
+
--border: #e6e8ef;
|
|
11
|
+
--accent: #6366f1;
|
|
12
|
+
--accent-2: #8b5cf6;
|
|
13
|
+
--radius: 14px;
|
|
14
|
+
--shadow: 0 1px 2px rgba(20, 22, 40, 0.04), 0 8px 24px rgba(20, 22, 40, 0.06);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
@media (prefers-color-scheme: dark) {
|
|
18
|
+
:root {
|
|
19
|
+
--bg: #0e1016;
|
|
20
|
+
--panel: #171a22;
|
|
21
|
+
--text: #e7e9f0;
|
|
22
|
+
--muted: #9aa1b1;
|
|
23
|
+
--border: #262a36;
|
|
24
|
+
--shadow: 0 1px 2px rgba(0, 0, 0, 0.3), 0 10px 30px rgba(0, 0, 0, 0.35);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
* {
|
|
29
|
+
box-sizing: border-box;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
body {
|
|
33
|
+
margin: 0;
|
|
34
|
+
min-height: 100vh;
|
|
35
|
+
font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
|
|
36
|
+
line-height: 1.5;
|
|
37
|
+
color: var(--text);
|
|
38
|
+
background:
|
|
39
|
+
radial-gradient(1200px 500px at 50% -200px, rgba(99, 102, 241, 0.18), transparent 70%),
|
|
40
|
+
var(--bg);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.app {
|
|
44
|
+
width: min(56rem, 92vw);
|
|
45
|
+
margin: 0 auto;
|
|
46
|
+
padding: clamp(1.5rem, 4vw, 3rem) 0 3rem;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/* --- hero ------------------------------------------------------------------ */
|
|
50
|
+
.hero {
|
|
51
|
+
text-align: center;
|
|
52
|
+
margin-bottom: 1.75rem;
|
|
53
|
+
}
|
|
54
|
+
.badge {
|
|
55
|
+
display: inline-block;
|
|
56
|
+
font-size: 0.72rem;
|
|
57
|
+
font-weight: 600;
|
|
58
|
+
letter-spacing: 0.04em;
|
|
59
|
+
text-transform: uppercase;
|
|
60
|
+
color: #fff;
|
|
61
|
+
background: linear-gradient(135deg, var(--accent), var(--accent-2));
|
|
62
|
+
padding: 0.3rem 0.7rem;
|
|
63
|
+
border-radius: 999px;
|
|
64
|
+
}
|
|
65
|
+
.hero h1 {
|
|
66
|
+
margin: 0.7rem 0 0.25rem;
|
|
67
|
+
font-size: clamp(1.8rem, 5vw, 2.6rem);
|
|
68
|
+
letter-spacing: -0.02em;
|
|
69
|
+
}
|
|
70
|
+
.tagline {
|
|
71
|
+
margin: 0 auto;
|
|
72
|
+
max-width: 34rem;
|
|
73
|
+
color: var(--muted);
|
|
74
|
+
}
|
|
75
|
+
.summary {
|
|
76
|
+
margin: 0.6rem 0 0;
|
|
77
|
+
color: var(--muted);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/* --- cards & stats --------------------------------------------------------- */
|
|
81
|
+
.card {
|
|
82
|
+
background: var(--panel);
|
|
83
|
+
border: 1px solid var(--border);
|
|
84
|
+
border-radius: var(--radius);
|
|
85
|
+
box-shadow: var(--shadow);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.stats {
|
|
89
|
+
display: grid;
|
|
90
|
+
grid-template-columns: repeat(auto-fit, minmax(8.5rem, 1fr));
|
|
91
|
+
gap: 0.9rem;
|
|
92
|
+
margin-bottom: 1.25rem;
|
|
93
|
+
}
|
|
94
|
+
.stat {
|
|
95
|
+
padding: 1rem 1.1rem;
|
|
96
|
+
border-left: 3px solid var(--accent);
|
|
97
|
+
}
|
|
98
|
+
.stat-indigo { border-left-color: #6366f1; }
|
|
99
|
+
.stat-green { border-left-color: #10b981; }
|
|
100
|
+
.stat-amber { border-left-color: #f59e0b; }
|
|
101
|
+
.stat-slate { border-left-color: #64748b; }
|
|
102
|
+
.stat-value {
|
|
103
|
+
font-size: 1.7rem;
|
|
104
|
+
font-weight: 700;
|
|
105
|
+
text-transform: capitalize;
|
|
106
|
+
}
|
|
107
|
+
.stat-label {
|
|
108
|
+
font-size: 0.85rem;
|
|
109
|
+
color: var(--muted);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/* --- task panel ------------------------------------------------------------ */
|
|
113
|
+
.panel {
|
|
114
|
+
background: var(--panel);
|
|
115
|
+
border: 1px solid var(--border);
|
|
116
|
+
border-radius: var(--radius);
|
|
117
|
+
box-shadow: var(--shadow);
|
|
118
|
+
padding: 1.25rem;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.add {
|
|
122
|
+
display: flex;
|
|
123
|
+
gap: 0.5rem;
|
|
124
|
+
margin-bottom: 0.9rem;
|
|
125
|
+
}
|
|
126
|
+
.add input {
|
|
127
|
+
flex: 1;
|
|
128
|
+
font: inherit;
|
|
129
|
+
padding: 0.6rem 0.8rem;
|
|
130
|
+
color: var(--text);
|
|
131
|
+
background: transparent;
|
|
132
|
+
border: 1px solid var(--border);
|
|
133
|
+
border-radius: 10px;
|
|
134
|
+
}
|
|
135
|
+
.add input:focus-visible {
|
|
136
|
+
outline: 2px solid var(--accent);
|
|
137
|
+
outline-offset: 1px;
|
|
138
|
+
}
|
|
139
|
+
button {
|
|
140
|
+
font: inherit;
|
|
141
|
+
cursor: pointer;
|
|
142
|
+
border-radius: 10px;
|
|
143
|
+
border: 1px solid transparent;
|
|
144
|
+
}
|
|
145
|
+
.add button {
|
|
146
|
+
padding: 0.6rem 1.1rem;
|
|
147
|
+
color: #fff;
|
|
148
|
+
background: linear-gradient(135deg, var(--accent), var(--accent-2));
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
.filters {
|
|
152
|
+
display: flex;
|
|
153
|
+
gap: 0.4rem;
|
|
154
|
+
margin-bottom: 0.9rem;
|
|
155
|
+
}
|
|
156
|
+
.chip {
|
|
157
|
+
padding: 0.35rem 0.85rem;
|
|
158
|
+
color: var(--muted);
|
|
159
|
+
background: transparent;
|
|
160
|
+
border: 1px solid var(--border);
|
|
161
|
+
}
|
|
162
|
+
.chip-on {
|
|
163
|
+
color: var(--text);
|
|
164
|
+
border-color: var(--accent);
|
|
165
|
+
background: color-mix(in srgb, var(--accent) 12%, transparent);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
.tasks {
|
|
169
|
+
list-style: none;
|
|
170
|
+
margin: 0;
|
|
171
|
+
padding: 0;
|
|
172
|
+
display: grid;
|
|
173
|
+
gap: 0.45rem;
|
|
174
|
+
}
|
|
175
|
+
.task {
|
|
176
|
+
display: flex;
|
|
177
|
+
align-items: center;
|
|
178
|
+
justify-content: space-between;
|
|
179
|
+
gap: 0.6rem;
|
|
180
|
+
padding: 0.6rem 0.75rem;
|
|
181
|
+
border: 1px solid var(--border);
|
|
182
|
+
border-radius: 10px;
|
|
183
|
+
}
|
|
184
|
+
.task label {
|
|
185
|
+
display: flex;
|
|
186
|
+
align-items: center;
|
|
187
|
+
gap: 0.6rem;
|
|
188
|
+
cursor: pointer;
|
|
189
|
+
}
|
|
190
|
+
.task input[type="checkbox"] {
|
|
191
|
+
width: 1.1rem;
|
|
192
|
+
height: 1.1rem;
|
|
193
|
+
accent-color: var(--accent);
|
|
194
|
+
}
|
|
195
|
+
.task.done span {
|
|
196
|
+
text-decoration: line-through;
|
|
197
|
+
color: var(--muted);
|
|
198
|
+
}
|
|
199
|
+
.delete {
|
|
200
|
+
border: none;
|
|
201
|
+
background: transparent;
|
|
202
|
+
color: var(--muted);
|
|
203
|
+
padding: 0.2rem 0.5rem;
|
|
204
|
+
font-size: 1rem;
|
|
205
|
+
}
|
|
206
|
+
.delete:hover {
|
|
207
|
+
color: #ef4444;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
.empty {
|
|
211
|
+
text-align: center;
|
|
212
|
+
color: var(--muted);
|
|
213
|
+
padding: 1.5rem 0 0.5rem;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/* --- dev hint -------------------------------------------------------------- */
|
|
217
|
+
.hint {
|
|
218
|
+
text-align: center;
|
|
219
|
+
color: var(--muted);
|
|
220
|
+
font-size: 0.9rem;
|
|
221
|
+
margin-top: 1.5rem;
|
|
222
|
+
}
|
|
223
|
+
.hint p {
|
|
224
|
+
margin: 0.2rem 0;
|
|
225
|
+
}
|
|
226
|
+
code {
|
|
227
|
+
font-family: ui-monospace, "SF Mono", Menlo, monospace;
|
|
228
|
+
font-size: 0.85em;
|
|
229
|
+
padding: 0.1rem 0.35rem;
|
|
230
|
+
border-radius: 6px;
|
|
231
|
+
background: color-mix(in srgb, var(--accent) 12%, transparent);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
@media (max-width: 30rem) {
|
|
235
|
+
.add {
|
|
236
|
+
flex-direction: column;
|
|
237
|
+
}
|
|
238
|
+
.add button {
|
|
239
|
+
width: 100%;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
@@ -1,30 +1,50 @@
|
|
|
1
|
-
# {{APP_TITLE}}
|
|
2
|
-
|
|
3
|
-
A [Zoijs](https://zoijs.dev) app — plain HTML, CSS, and JavaScript. **No build step.**
|
|
4
|
-
|
|
5
|
-
## Develop
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
npm install
|
|
9
|
-
npm run dev
|
|
10
|
-
```
|
|
11
|
-
|
|
12
|
-
```text
|
|
13
|
-
Zoijs dev server
|
|
14
|
-
|
|
15
|
-
- Local: http://localhost:7310
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
Open the printed URL (it falls back to 7311–7313 if the port is busy).
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
1
|
+
# {{APP_TITLE}}
|
|
2
|
+
|
|
3
|
+
A [Zoijs](https://zoijs.dev) app — plain HTML, CSS, and JavaScript. **No build step.**
|
|
4
|
+
|
|
5
|
+
## Develop
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install
|
|
9
|
+
npm run dev
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
```text
|
|
13
|
+
Zoijs dev server
|
|
14
|
+
|
|
15
|
+
- Local: http://localhost:7310
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Open the printed URL (it falls back to 7311–7313 if the port is busy).
|
|
19
|
+
|
|
20
|
+
The dev server is for **development only**: it listens on `127.0.0.1` (this machine),
|
|
21
|
+
never serves dotfiles (`.env`, `.git/`, …) or anything outside the project folder, and is
|
|
22
|
+
not meant for hosting. To try the app from a phone on your network, opt in explicitly with
|
|
23
|
+
`ZOIJS_HOST=0.0.0.0 npm run dev` — while it runs, anyone on that network can read the
|
|
24
|
+
project's files.
|
|
25
|
+
|
|
26
|
+
## Deploy
|
|
27
|
+
|
|
28
|
+
This page loads the **development** entry of `@zoijs/core` (helpful warnings, devtools).
|
|
29
|
+
When you deploy, change the import map in `index.html` to the **production** entry —
|
|
30
|
+
same API, warnings and the devtools hook off:
|
|
31
|
+
|
|
32
|
+
```html
|
|
33
|
+
"@zoijs/core": "./node_modules/@zoijs/core/src/prod.js"
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Then deploy the files to a static host (not the dev server) and go through the
|
|
37
|
+
[production security checklist](https://zoijs.dev/production-security) — security headers,
|
|
38
|
+
a Content-Security-Policy with your import map's hash, CSRF, and more.
|
|
39
|
+
|
|
40
|
+
## How it works
|
|
41
|
+
|
|
42
|
+
- **`index.html`** — an import map points `@zoijs/core` at `node_modules`, then loads `src/app.js`.
|
|
43
|
+
- **`dev-server.mjs`** — a tiny zero-dependency static server (Node built-ins only) that `npm run dev` runs.
|
|
44
|
+
- **`src/app.js`** — your app: `createState` for state, `html` for markup, `mount` to render.
|
|
45
|
+
- **`src/style.css`** — plain CSS.
|
|
46
|
+
|
|
47
|
+
There's no bundler and no build step. Open the files and read them — that's the
|
|
48
|
+
whole app. Edit `src/app.js` and reload.
|
|
49
|
+
|
|
50
|
+
Learn more at [zoijs.dev](https://zoijs.dev).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
node_modules
|
|
1
|
+
node_modules
|