@vojtaholik/create-static-kit 1.0.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/create-static-kit.js +3 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +365 -0
- package/package.json +48 -0
- package/templates/default/public/favicon.ico +1 -0
- package/templates/default/src/components/button.html +1 -0
- package/templates/default/src/components/feature-card.html +8 -0
- package/templates/default/src/components/footer.html +5 -0
- package/templates/default/src/components/navigation.html +11 -0
- package/templates/default/src/icons/ui/star.svg +3 -0
- package/templates/default/src/js/index.ts +28 -0
- package/templates/default/src/pages/about.html +24 -0
- package/templates/default/src/pages/index.html +23 -0
- package/templates/default/src/styles/main.scss +210 -0
- package/templates/default/tsconfig.json +19 -0
- package/templates/minimal/public/favicon.ico +1 -0
- package/templates/minimal/src/components/footer.html +3 -0
- package/templates/minimal/src/components/header.html +6 -0
- package/templates/minimal/src/js/index.ts +9 -0
- package/templates/minimal/src/pages/index.html +15 -0
- package/templates/minimal/src/styles/main.scss +77 -0
- package/templates/minimal/tsconfig.json +19 -0
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from "fs/promises";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import { fileURLToPath } from "url";
|
|
5
|
+
import prompts from "prompts";
|
|
6
|
+
import { cyan, green, red, bold } from "kleur/colors";
|
|
7
|
+
import fg from "fast-glob";
|
|
8
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
9
|
+
const TEMPLATES = {
|
|
10
|
+
minimal: {
|
|
11
|
+
name: "Minimal",
|
|
12
|
+
description: "Just the basics - perfect starting point",
|
|
13
|
+
features: ["Basic HTML/SCSS structure", "Component system", "Build pipeline"]
|
|
14
|
+
},
|
|
15
|
+
default: {
|
|
16
|
+
name: "Default",
|
|
17
|
+
description: "Starter with examples and components",
|
|
18
|
+
features: ["Multiple page examples", "Component library", "SVG sprite system", "Basic styling"]
|
|
19
|
+
},
|
|
20
|
+
styled: {
|
|
21
|
+
name: "Styled",
|
|
22
|
+
description: "Pre-styled with design system",
|
|
23
|
+
features: ["Modern CSS reset", "Design tokens", "Typography scale", "Component showcase"]
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
async function main() {
|
|
27
|
+
console.log();
|
|
28
|
+
console.log(`${cyan("create-static-kit")} ${green("v1.0.0")}`);
|
|
29
|
+
console.log();
|
|
30
|
+
const args = process.argv.slice(2);
|
|
31
|
+
let projectName = args[0];
|
|
32
|
+
let template = args.find(arg => arg.startsWith("--template="))?.split("=")[1];
|
|
33
|
+
const interactive = args.includes("--interactive") || !projectName || !template;
|
|
34
|
+
if (interactive) {
|
|
35
|
+
const response = await prompts([
|
|
36
|
+
{
|
|
37
|
+
type: "text",
|
|
38
|
+
name: "projectName",
|
|
39
|
+
message: "Project name:",
|
|
40
|
+
initial: projectName || "my-static-kit-site",
|
|
41
|
+
validate: (value) => {
|
|
42
|
+
if (!value.trim())
|
|
43
|
+
return "Project name is required";
|
|
44
|
+
if (!/^[a-zA-Z0-9-_]+$/.test(value))
|
|
45
|
+
return "Project name can only contain letters, numbers, hyphens, and underscores";
|
|
46
|
+
return true;
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
type: "select",
|
|
51
|
+
name: "template",
|
|
52
|
+
message: "Choose a template:",
|
|
53
|
+
choices: Object.entries(TEMPLATES).map(([key, config]) => ({
|
|
54
|
+
title: `${config.name} - ${config.description}`,
|
|
55
|
+
description: config.features.join(" • "),
|
|
56
|
+
value: key
|
|
57
|
+
})),
|
|
58
|
+
initial: 0
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
type: "confirm",
|
|
62
|
+
name: "cssReset",
|
|
63
|
+
message: "Include CSS reset?",
|
|
64
|
+
initial: true
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
type: "confirm",
|
|
68
|
+
name: "designTokens",
|
|
69
|
+
message: "Include design tokens?",
|
|
70
|
+
initial: false
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
type: "confirm",
|
|
74
|
+
name: "initGit",
|
|
75
|
+
message: "Initialize git repository?",
|
|
76
|
+
initial: true
|
|
77
|
+
}
|
|
78
|
+
]);
|
|
79
|
+
if (!response.projectName) {
|
|
80
|
+
console.log(red("✖") + " Operation cancelled");
|
|
81
|
+
process.exit(1);
|
|
82
|
+
}
|
|
83
|
+
const options = {
|
|
84
|
+
projectName: response.projectName,
|
|
85
|
+
template: response.template,
|
|
86
|
+
cssReset: response.cssReset,
|
|
87
|
+
designTokens: response.designTokens,
|
|
88
|
+
initGit: response.initGit
|
|
89
|
+
};
|
|
90
|
+
await createProject(options);
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
// Non-interactive mode
|
|
94
|
+
const options = {
|
|
95
|
+
projectName,
|
|
96
|
+
template: template || "default",
|
|
97
|
+
cssReset: true,
|
|
98
|
+
designTokens: false,
|
|
99
|
+
initGit: true
|
|
100
|
+
};
|
|
101
|
+
await createProject(options);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
async function createProject(options) {
|
|
105
|
+
const { projectName, template, cssReset, designTokens, initGit } = options;
|
|
106
|
+
console.log();
|
|
107
|
+
console.log(`${cyan("✨")} Creating ${bold(projectName)}...`);
|
|
108
|
+
console.log();
|
|
109
|
+
// Check if directory exists
|
|
110
|
+
const projectPath = path.resolve(projectName);
|
|
111
|
+
try {
|
|
112
|
+
await fs.access(projectPath);
|
|
113
|
+
console.log(red("✖") + ` Directory ${projectName} already exists`);
|
|
114
|
+
process.exit(1);
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
// Directory doesn't exist, which is what we want
|
|
118
|
+
}
|
|
119
|
+
try {
|
|
120
|
+
// Create project directory
|
|
121
|
+
await fs.mkdir(projectPath, { recursive: true });
|
|
122
|
+
// Copy template files
|
|
123
|
+
await copyTemplate(template, projectPath);
|
|
124
|
+
// Generate package.json
|
|
125
|
+
await generatePackageJson(projectName, projectPath);
|
|
126
|
+
// Generate vite.config.ts
|
|
127
|
+
await generateViteConfig(projectPath);
|
|
128
|
+
// Generate static-kit.config.json
|
|
129
|
+
await generateStaticKitConfig(projectPath);
|
|
130
|
+
// Conditionally add features
|
|
131
|
+
if (cssReset) {
|
|
132
|
+
await addCssReset(projectPath);
|
|
133
|
+
}
|
|
134
|
+
if (designTokens) {
|
|
135
|
+
await addDesignTokens(projectPath);
|
|
136
|
+
}
|
|
137
|
+
// Initialize git
|
|
138
|
+
if (initGit) {
|
|
139
|
+
await initializeGit(projectPath);
|
|
140
|
+
}
|
|
141
|
+
console.log();
|
|
142
|
+
console.log(`${green("✅")} Successfully created ${bold(projectName)}`);
|
|
143
|
+
console.log();
|
|
144
|
+
console.log("Next steps:");
|
|
145
|
+
console.log(` ${cyan("cd")} ${projectName}`);
|
|
146
|
+
console.log(` ${cyan("npm install")} or ${cyan("pnpm install")}`);
|
|
147
|
+
console.log(` ${cyan("npm run dev")} or ${cyan("pnpm dev")}`);
|
|
148
|
+
console.log();
|
|
149
|
+
console.log("Happy building! 🚀");
|
|
150
|
+
console.log();
|
|
151
|
+
}
|
|
152
|
+
catch (error) {
|
|
153
|
+
console.log();
|
|
154
|
+
console.log(red("✖") + " Failed to create project:");
|
|
155
|
+
console.log(red(String(error)));
|
|
156
|
+
process.exit(1);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
async function copyTemplate(templateName, projectPath) {
|
|
160
|
+
const templatesDir = path.join(__dirname, "..", "templates");
|
|
161
|
+
const templatePath = path.join(templatesDir, templateName);
|
|
162
|
+
try {
|
|
163
|
+
// Check if template exists
|
|
164
|
+
await fs.access(templatePath);
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
console.log(red("✖") + ` Template "${templateName}" not found`);
|
|
168
|
+
process.exit(1);
|
|
169
|
+
}
|
|
170
|
+
// Copy all files from template
|
|
171
|
+
const files = await fg("**/*", {
|
|
172
|
+
cwd: templatePath,
|
|
173
|
+
onlyFiles: true,
|
|
174
|
+
dot: true
|
|
175
|
+
});
|
|
176
|
+
for (const file of files) {
|
|
177
|
+
const srcPath = path.join(templatePath, file);
|
|
178
|
+
const destPath = path.join(projectPath, file);
|
|
179
|
+
// Ensure destination directory exists
|
|
180
|
+
await fs.mkdir(path.dirname(destPath), { recursive: true });
|
|
181
|
+
await fs.copyFile(srcPath, destPath);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
async function generatePackageJson(projectName, projectPath) {
|
|
185
|
+
const packageJson = {
|
|
186
|
+
name: projectName,
|
|
187
|
+
private: true,
|
|
188
|
+
version: "0.0.0",
|
|
189
|
+
type: "module",
|
|
190
|
+
scripts: {
|
|
191
|
+
dev: "vite",
|
|
192
|
+
build: "tsc && vite build",
|
|
193
|
+
preview: "vite preview"
|
|
194
|
+
},
|
|
195
|
+
devDependencies: {
|
|
196
|
+
"@vojtaholik/static-kit-core": "^1.0.0",
|
|
197
|
+
"@types/node": "^24.2.1",
|
|
198
|
+
autoprefixer: "^10.4.21",
|
|
199
|
+
postcss: "^8.5.6",
|
|
200
|
+
"sass-embedded": "^1.90.0",
|
|
201
|
+
typescript: "~5.9.2",
|
|
202
|
+
vite: "^7.1.1"
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
await fs.writeFile(path.join(projectPath, "package.json"), JSON.stringify(packageJson, null, 2));
|
|
206
|
+
}
|
|
207
|
+
async function generateViteConfig(projectPath) {
|
|
208
|
+
const viteConfig = `import { defineConfig } from "vite";
|
|
209
|
+
import { createStaticKitConfig } from "@vojtaholik/static-kit-core/vite";
|
|
210
|
+
|
|
211
|
+
export default defineConfig(async (env) => {
|
|
212
|
+
const staticKitConfig = await createStaticKitConfig();
|
|
213
|
+
return staticKitConfig;
|
|
214
|
+
});`;
|
|
215
|
+
await fs.writeFile(path.join(projectPath, "vite.config.ts"), viteConfig);
|
|
216
|
+
}
|
|
217
|
+
async function generateStaticKitConfig(projectPath) {
|
|
218
|
+
const config = {
|
|
219
|
+
build: {
|
|
220
|
+
base: "public/",
|
|
221
|
+
output: "dist"
|
|
222
|
+
},
|
|
223
|
+
templates: {
|
|
224
|
+
language: "en"
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
await fs.writeFile(path.join(projectPath, "static-kit.config.json"), JSON.stringify(config, null, 2));
|
|
228
|
+
}
|
|
229
|
+
async function addCssReset(projectPath) {
|
|
230
|
+
const resetCss = `/* Modern CSS Reset */
|
|
231
|
+
*, *::before, *::after {
|
|
232
|
+
box-sizing: border-box;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
* {
|
|
236
|
+
margin: 0;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
body {
|
|
240
|
+
line-height: 1.5;
|
|
241
|
+
-webkit-font-smoothing: antialiased;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
img, picture, video, canvas, svg {
|
|
245
|
+
display: block;
|
|
246
|
+
max-width: 100%;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
input, button, textarea, select {
|
|
250
|
+
font: inherit;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
p, h1, h2, h3, h4, h5, h6 {
|
|
254
|
+
overflow-wrap: break-word;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
#root, #__next {
|
|
258
|
+
isolation: isolate;
|
|
259
|
+
}`;
|
|
260
|
+
await fs.writeFile(path.join(projectPath, "src", "styles", "_reset.scss"), resetCss);
|
|
261
|
+
// Add import to main.scss
|
|
262
|
+
const mainScssPath = path.join(projectPath, "src", "styles", "main.scss");
|
|
263
|
+
try {
|
|
264
|
+
const mainScss = await fs.readFile(mainScssPath, "utf-8");
|
|
265
|
+
const updatedScss = `@import "reset";\n\n${mainScss}`;
|
|
266
|
+
await fs.writeFile(mainScssPath, updatedScss);
|
|
267
|
+
}
|
|
268
|
+
catch {
|
|
269
|
+
// main.scss doesn't exist or can't be read
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
async function addDesignTokens(projectPath) {
|
|
273
|
+
const tokensScss = `:root {
|
|
274
|
+
/* Colors */
|
|
275
|
+
--color-primary: #0066cc;
|
|
276
|
+
--color-primary-dark: #0052a3;
|
|
277
|
+
--color-secondary: #6b7280;
|
|
278
|
+
--color-accent: #f59e0b;
|
|
279
|
+
|
|
280
|
+
--color-text: #1f2937;
|
|
281
|
+
--color-text-muted: #6b7280;
|
|
282
|
+
--color-background: #ffffff;
|
|
283
|
+
--color-surface: #f9fafb;
|
|
284
|
+
--color-border: #e5e7eb;
|
|
285
|
+
|
|
286
|
+
/* Typography */
|
|
287
|
+
--font-size-xs: 0.75rem;
|
|
288
|
+
--font-size-sm: 0.875rem;
|
|
289
|
+
--font-size-base: 1rem;
|
|
290
|
+
--font-size-lg: 1.125rem;
|
|
291
|
+
--font-size-xl: 1.25rem;
|
|
292
|
+
--font-size-2xl: 1.5rem;
|
|
293
|
+
--font-size-3xl: 1.875rem;
|
|
294
|
+
--font-size-4xl: 2.25rem;
|
|
295
|
+
|
|
296
|
+
--font-weight-normal: 400;
|
|
297
|
+
--font-weight-medium: 500;
|
|
298
|
+
--font-weight-semibold: 600;
|
|
299
|
+
--font-weight-bold: 700;
|
|
300
|
+
|
|
301
|
+
--line-height-tight: 1.25;
|
|
302
|
+
--line-height-normal: 1.5;
|
|
303
|
+
--line-height-relaxed: 1.75;
|
|
304
|
+
|
|
305
|
+
/* Spacing */
|
|
306
|
+
--space-xs: 0.25rem;
|
|
307
|
+
--space-sm: 0.5rem;
|
|
308
|
+
--space-md: 1rem;
|
|
309
|
+
--space-lg: 1.5rem;
|
|
310
|
+
--space-xl: 2rem;
|
|
311
|
+
--space-2xl: 3rem;
|
|
312
|
+
--space-3xl: 4rem;
|
|
313
|
+
|
|
314
|
+
/* Borders */
|
|
315
|
+
--border-radius-sm: 0.25rem;
|
|
316
|
+
--border-radius-md: 0.375rem;
|
|
317
|
+
--border-radius-lg: 0.5rem;
|
|
318
|
+
--border-radius-xl: 0.75rem;
|
|
319
|
+
|
|
320
|
+
/* Shadows */
|
|
321
|
+
--shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
|
|
322
|
+
--shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
|
|
323
|
+
--shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
|
|
324
|
+
}`;
|
|
325
|
+
await fs.writeFile(path.join(projectPath, "src", "styles", "_tokens.scss"), tokensScss);
|
|
326
|
+
// Add import to main.scss
|
|
327
|
+
const mainScssPath = path.join(projectPath, "src", "styles", "main.scss");
|
|
328
|
+
try {
|
|
329
|
+
const mainScss = await fs.readFile(mainScssPath, "utf-8");
|
|
330
|
+
const updatedScss = `@import "tokens";\n\n${mainScss}`;
|
|
331
|
+
await fs.writeFile(mainScssPath, updatedScss);
|
|
332
|
+
}
|
|
333
|
+
catch {
|
|
334
|
+
// main.scss doesn't exist or can't be read
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
async function initializeGit(projectPath) {
|
|
338
|
+
const gitignore = `# Dependencies
|
|
339
|
+
node_modules/
|
|
340
|
+
.pnpm-debug.log*
|
|
341
|
+
|
|
342
|
+
# Build output
|
|
343
|
+
dist/
|
|
344
|
+
|
|
345
|
+
# Local config
|
|
346
|
+
static-kit.local.json
|
|
347
|
+
|
|
348
|
+
# OS
|
|
349
|
+
.DS_Store
|
|
350
|
+
Thumbs.db
|
|
351
|
+
|
|
352
|
+
# IDE
|
|
353
|
+
.vscode/
|
|
354
|
+
.idea/
|
|
355
|
+
*.swp
|
|
356
|
+
*.swo
|
|
357
|
+
|
|
358
|
+
# Logs
|
|
359
|
+
*.log
|
|
360
|
+
npm-debug.log*
|
|
361
|
+
yarn-debug.log*
|
|
362
|
+
yarn-error.log*`;
|
|
363
|
+
await fs.writeFile(path.join(projectPath, ".gitignore"), gitignore);
|
|
364
|
+
}
|
|
365
|
+
main().catch(console.error);
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@vojtaholik/create-static-kit",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "CLI tool to create new Static Kit projects",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"create-static-kit": "./bin/create-static-kit.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"bin/",
|
|
11
|
+
"dist/",
|
|
12
|
+
"templates/"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "tsc",
|
|
16
|
+
"dev": "tsc --watch",
|
|
17
|
+
"clean": "rm -rf dist"
|
|
18
|
+
},
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"@vojtaholik/static-kit-core": "^1.0.0",
|
|
21
|
+
"prompts": "^2.4.2",
|
|
22
|
+
"kleur": "^4.1.5",
|
|
23
|
+
"fast-glob": "^3.3.3"
|
|
24
|
+
},
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"@types/node": "^24.2.1",
|
|
27
|
+
"@types/prompts": "^2.4.9",
|
|
28
|
+
"typescript": "~5.9.2"
|
|
29
|
+
},
|
|
30
|
+
"keywords": [
|
|
31
|
+
"create",
|
|
32
|
+
"static-kit",
|
|
33
|
+
"cli",
|
|
34
|
+
"scaffold",
|
|
35
|
+
"template"
|
|
36
|
+
],
|
|
37
|
+
"author": "Vojta Holik <vojta@hey.com>",
|
|
38
|
+
"license": "MIT",
|
|
39
|
+
"repository": {
|
|
40
|
+
"type": "git",
|
|
41
|
+
"url": "https://github.com/vojtaholik/static-kit.git",
|
|
42
|
+
"directory": "packages/create-static-kit"
|
|
43
|
+
},
|
|
44
|
+
"homepage": "https://github.com/vojtaholik/static-kit#readme",
|
|
45
|
+
"bugs": {
|
|
46
|
+
"url": "https://github.com/vojtaholik/static-kit/issues"
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Empty favicon placeholder
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<a href="/about" class="button button--primary">Get Started</a>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
<div class="feature-card">
|
|
2
|
+
<div class="feature-card__icon">
|
|
3
|
+
<!-- SVG icon would go here -->
|
|
4
|
+
<div class="feature-placeholder">🚀</div>
|
|
5
|
+
</div>
|
|
6
|
+
<h3>Fast & Modern</h3>
|
|
7
|
+
<p>Built with Vite for lightning-fast development and optimized production builds.</p>
|
|
8
|
+
</div>
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
2
|
+
<path d="M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
3
|
+
</svg>
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// Main JavaScript entry point
|
|
2
|
+
console.log("Static Kit is ready! 🚀");
|
|
3
|
+
|
|
4
|
+
// Example: Add smooth scrolling for anchor links
|
|
5
|
+
document.addEventListener("DOMContentLoaded", () => {
|
|
6
|
+
// Add click handlers for navigation links
|
|
7
|
+
const navLinks = document.querySelectorAll('.nav-links a');
|
|
8
|
+
|
|
9
|
+
navLinks.forEach(link => {
|
|
10
|
+
link.addEventListener('click', () => {
|
|
11
|
+
console.log(`Navigating to: ${link.getAttribute('href')}`);
|
|
12
|
+
});
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
// Example: Add some interactivity to feature cards
|
|
16
|
+
const featureCards = document.querySelectorAll('.feature-card');
|
|
17
|
+
|
|
18
|
+
featureCards.forEach(card => {
|
|
19
|
+
const htmlCard = card as HTMLElement;
|
|
20
|
+
htmlCard.addEventListener('mouseenter', () => {
|
|
21
|
+
htmlCard.style.transform = 'translateY(-4px)';
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
htmlCard.addEventListener('mouseleave', () => {
|
|
25
|
+
htmlCard.style.transform = 'translateY(0)';
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<!-- @import: @components/navigation.html -->
|
|
2
|
+
|
|
3
|
+
<main class="container">
|
|
4
|
+
<h1>About Static Kit</h1>
|
|
5
|
+
|
|
6
|
+
<section>
|
|
7
|
+
<p>Static Kit is a modern static site generator that combines the simplicity of HTML with the power of modern build tools.</p>
|
|
8
|
+
|
|
9
|
+
<h2>Why Static Kit?</h2>
|
|
10
|
+
<ul>
|
|
11
|
+
<li>Zero configuration - just start building</li>
|
|
12
|
+
<li>Component-driven development</li>
|
|
13
|
+
<li>Modern developer experience</li>
|
|
14
|
+
<li>Deployable anywhere</li>
|
|
15
|
+
</ul>
|
|
16
|
+
</section>
|
|
17
|
+
|
|
18
|
+
<section>
|
|
19
|
+
<h2>Built With</h2>
|
|
20
|
+
<p>Static Kit uses Vite, TypeScript, and SCSS under the hood to provide a fast and modern development experience.</p>
|
|
21
|
+
</section>
|
|
22
|
+
</main>
|
|
23
|
+
|
|
24
|
+
<!-- @import: @components/footer.html -->
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
<!-- @import: @components/navigation.html -->
|
|
2
|
+
|
|
3
|
+
<section class="hero">
|
|
4
|
+
<div class="hero-content">
|
|
5
|
+
<h1>Welcome to Static Kit</h1>
|
|
6
|
+
<p>A simple, no-bullshit static site framework with TypeScript, SCSS, and HTML imports.</p>
|
|
7
|
+
|
|
8
|
+
<!-- @import: @components/button.html -->
|
|
9
|
+
</div>
|
|
10
|
+
</section>
|
|
11
|
+
|
|
12
|
+
<section class="features">
|
|
13
|
+
<div class="container">
|
|
14
|
+
<h2>Features</h2>
|
|
15
|
+
<div class="feature-grid">
|
|
16
|
+
<!-- @import: @components/feature-card.html -->
|
|
17
|
+
<!-- @import: @components/feature-card.html -->
|
|
18
|
+
<!-- @import: @components/feature-card.html -->
|
|
19
|
+
</div>
|
|
20
|
+
</div>
|
|
21
|
+
</section>
|
|
22
|
+
|
|
23
|
+
<!-- @import: @components/footer.html -->
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
// Modern CSS Reset
|
|
2
|
+
*, *::before, *::after {
|
|
3
|
+
box-sizing: border-box;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
* {
|
|
7
|
+
margin: 0;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
body {
|
|
11
|
+
line-height: 1.5;
|
|
12
|
+
-webkit-font-smoothing: antialiased;
|
|
13
|
+
font-family: system-ui, sans-serif;
|
|
14
|
+
color: #1f2937;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
img, picture, video, canvas, svg {
|
|
18
|
+
display: block;
|
|
19
|
+
max-width: 100%;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Utilities
|
|
23
|
+
.container {
|
|
24
|
+
max-width: 1200px;
|
|
25
|
+
margin: 0 auto;
|
|
26
|
+
padding: 0 1rem;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Header & Navigation
|
|
30
|
+
.header {
|
|
31
|
+
background: #ffffff;
|
|
32
|
+
border-bottom: 1px solid #e5e7eb;
|
|
33
|
+
position: sticky;
|
|
34
|
+
top: 0;
|
|
35
|
+
z-index: 100;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.nav {
|
|
39
|
+
display: flex;
|
|
40
|
+
justify-content: space-between;
|
|
41
|
+
align-items: center;
|
|
42
|
+
padding: 1rem;
|
|
43
|
+
max-width: 1200px;
|
|
44
|
+
margin: 0 auto;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.nav-brand a {
|
|
48
|
+
font-weight: 700;
|
|
49
|
+
font-size: 1.25rem;
|
|
50
|
+
text-decoration: none;
|
|
51
|
+
color: #0066cc;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.nav-links {
|
|
55
|
+
display: flex;
|
|
56
|
+
gap: 2rem;
|
|
57
|
+
|
|
58
|
+
a {
|
|
59
|
+
text-decoration: none;
|
|
60
|
+
color: #6b7280;
|
|
61
|
+
font-weight: 500;
|
|
62
|
+
transition: color 0.2s;
|
|
63
|
+
|
|
64
|
+
&:hover {
|
|
65
|
+
color: #0066cc;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Hero Section
|
|
71
|
+
.hero {
|
|
72
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
73
|
+
color: white;
|
|
74
|
+
padding: 4rem 1rem;
|
|
75
|
+
text-align: center;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.hero-content {
|
|
79
|
+
max-width: 600px;
|
|
80
|
+
margin: 0 auto;
|
|
81
|
+
|
|
82
|
+
h1 {
|
|
83
|
+
font-size: 3rem;
|
|
84
|
+
font-weight: 700;
|
|
85
|
+
margin-bottom: 1rem;
|
|
86
|
+
line-height: 1.2;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
p {
|
|
90
|
+
font-size: 1.25rem;
|
|
91
|
+
margin-bottom: 2rem;
|
|
92
|
+
opacity: 0.9;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Button Component
|
|
97
|
+
.button {
|
|
98
|
+
display: inline-block;
|
|
99
|
+
padding: 0.75rem 2rem;
|
|
100
|
+
font-weight: 600;
|
|
101
|
+
text-decoration: none;
|
|
102
|
+
border-radius: 0.5rem;
|
|
103
|
+
transition: all 0.2s;
|
|
104
|
+
cursor: pointer;
|
|
105
|
+
border: none;
|
|
106
|
+
|
|
107
|
+
&--primary {
|
|
108
|
+
background: #ffffff;
|
|
109
|
+
color: #0066cc;
|
|
110
|
+
|
|
111
|
+
&:hover {
|
|
112
|
+
background: #f8f9fa;
|
|
113
|
+
transform: translateY(-1px);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Features Section
|
|
119
|
+
.features {
|
|
120
|
+
padding: 4rem 1rem;
|
|
121
|
+
background: #f9fafb;
|
|
122
|
+
|
|
123
|
+
h2 {
|
|
124
|
+
text-align: center;
|
|
125
|
+
font-size: 2.5rem;
|
|
126
|
+
margin-bottom: 3rem;
|
|
127
|
+
color: #1f2937;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.feature-grid {
|
|
132
|
+
display: grid;
|
|
133
|
+
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
|
134
|
+
gap: 2rem;
|
|
135
|
+
max-width: 1000px;
|
|
136
|
+
margin: 0 auto;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
.feature-card {
|
|
140
|
+
background: white;
|
|
141
|
+
padding: 2rem;
|
|
142
|
+
border-radius: 0.75rem;
|
|
143
|
+
box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1);
|
|
144
|
+
text-align: center;
|
|
145
|
+
|
|
146
|
+
&__icon {
|
|
147
|
+
margin-bottom: 1rem;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.feature-placeholder {
|
|
151
|
+
font-size: 3rem;
|
|
152
|
+
margin-bottom: 1rem;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
h3 {
|
|
156
|
+
font-size: 1.25rem;
|
|
157
|
+
font-weight: 600;
|
|
158
|
+
margin-bottom: 1rem;
|
|
159
|
+
color: #1f2937;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
p {
|
|
163
|
+
color: #6b7280;
|
|
164
|
+
line-height: 1.6;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Main Content
|
|
169
|
+
main {
|
|
170
|
+
padding: 3rem 1rem;
|
|
171
|
+
|
|
172
|
+
h1 {
|
|
173
|
+
font-size: 2.5rem;
|
|
174
|
+
margin-bottom: 2rem;
|
|
175
|
+
color: #1f2937;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
h2 {
|
|
179
|
+
font-size: 1.875rem;
|
|
180
|
+
margin: 2rem 0 1rem;
|
|
181
|
+
color: #374151;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
section {
|
|
185
|
+
margin-bottom: 2rem;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
ul {
|
|
189
|
+
padding-left: 1.5rem;
|
|
190
|
+
|
|
191
|
+
li {
|
|
192
|
+
margin-bottom: 0.5rem;
|
|
193
|
+
color: #4b5563;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
p {
|
|
198
|
+
margin-bottom: 1rem;
|
|
199
|
+
color: #4b5563;
|
|
200
|
+
line-height: 1.7;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Footer
|
|
205
|
+
.footer {
|
|
206
|
+
background: #1f2937;
|
|
207
|
+
color: #9ca3af;
|
|
208
|
+
padding: 2rem 1rem;
|
|
209
|
+
text-align: center;
|
|
210
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"useDefineForClassFields": true,
|
|
5
|
+
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
|
6
|
+
"module": "ESNext",
|
|
7
|
+
"skipLibCheck": true,
|
|
8
|
+
"moduleResolution": "bundler",
|
|
9
|
+
"allowImportingTsExtensions": true,
|
|
10
|
+
"resolveJsonModule": true,
|
|
11
|
+
"isolatedModules": true,
|
|
12
|
+
"noEmit": true,
|
|
13
|
+
"strict": true,
|
|
14
|
+
"noUnusedLocals": true,
|
|
15
|
+
"noUnusedParameters": true,
|
|
16
|
+
"noFallthroughCasesInSwitch": true
|
|
17
|
+
},
|
|
18
|
+
"include": ["src"]
|
|
19
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Empty favicon placeholder
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// Main JavaScript entry point
|
|
2
|
+
// This file is automatically included in every page
|
|
3
|
+
|
|
4
|
+
console.log("Static Kit is ready! 🚀");
|
|
5
|
+
|
|
6
|
+
// Example: Add some interactivity
|
|
7
|
+
document.addEventListener("DOMContentLoaded", () => {
|
|
8
|
+
console.log("DOM loaded and ready");
|
|
9
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<!-- @import: @components/header.html -->
|
|
2
|
+
|
|
3
|
+
<main>
|
|
4
|
+
<h1>Welcome to Static Kit</h1>
|
|
5
|
+
<p>A simple, no-bullshit static site framework.</p>
|
|
6
|
+
|
|
7
|
+
<section>
|
|
8
|
+
<h2>Getting Started</h2>
|
|
9
|
+
<p>Edit this file at <code>src/pages/index.html</code> to get started.</p>
|
|
10
|
+
<p>Create new components in <code>src/components/</code> and import them with:</p>
|
|
11
|
+
<pre><code><!-- @import: @components/your-component.html --></code></pre>
|
|
12
|
+
</section>
|
|
13
|
+
</main>
|
|
14
|
+
|
|
15
|
+
<!-- @import: @components/footer.html -->
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
body {
|
|
2
|
+
font-family: system-ui, sans-serif;
|
|
3
|
+
line-height: 1.6;
|
|
4
|
+
margin: 0;
|
|
5
|
+
padding: 0;
|
|
6
|
+
color: #333;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
header {
|
|
10
|
+
background: #f8f9fa;
|
|
11
|
+
padding: 1rem;
|
|
12
|
+
border-bottom: 1px solid #e5e7eb;
|
|
13
|
+
|
|
14
|
+
nav {
|
|
15
|
+
display: flex;
|
|
16
|
+
gap: 1rem;
|
|
17
|
+
|
|
18
|
+
a {
|
|
19
|
+
text-decoration: none;
|
|
20
|
+
color: #0066cc;
|
|
21
|
+
|
|
22
|
+
&:hover {
|
|
23
|
+
text-decoration: underline;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
main {
|
|
30
|
+
max-width: 800px;
|
|
31
|
+
margin: 0 auto;
|
|
32
|
+
padding: 2rem 1rem;
|
|
33
|
+
|
|
34
|
+
h1 {
|
|
35
|
+
color: #1f2937;
|
|
36
|
+
margin-bottom: 0.5rem;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
section {
|
|
40
|
+
margin-top: 2rem;
|
|
41
|
+
|
|
42
|
+
h2 {
|
|
43
|
+
color: #374151;
|
|
44
|
+
margin-bottom: 1rem;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
code {
|
|
49
|
+
background: #f3f4f6;
|
|
50
|
+
padding: 0.2rem 0.4rem;
|
|
51
|
+
border-radius: 0.25rem;
|
|
52
|
+
font-size: 0.875rem;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
pre {
|
|
56
|
+
background: #1f2937;
|
|
57
|
+
color: #f9fafb;
|
|
58
|
+
padding: 1rem;
|
|
59
|
+
border-radius: 0.5rem;
|
|
60
|
+
overflow-x: auto;
|
|
61
|
+
|
|
62
|
+
code {
|
|
63
|
+
background: none;
|
|
64
|
+
padding: 0;
|
|
65
|
+
color: inherit;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
footer {
|
|
71
|
+
background: #f8f9fa;
|
|
72
|
+
text-align: center;
|
|
73
|
+
padding: 2rem 1rem;
|
|
74
|
+
margin-top: 3rem;
|
|
75
|
+
border-top: 1px solid #e5e7eb;
|
|
76
|
+
color: #6b7280;
|
|
77
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"useDefineForClassFields": true,
|
|
5
|
+
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
|
6
|
+
"module": "ESNext",
|
|
7
|
+
"skipLibCheck": true,
|
|
8
|
+
"moduleResolution": "bundler",
|
|
9
|
+
"allowImportingTsExtensions": true,
|
|
10
|
+
"resolveJsonModule": true,
|
|
11
|
+
"isolatedModules": true,
|
|
12
|
+
"noEmit": true,
|
|
13
|
+
"strict": true,
|
|
14
|
+
"noUnusedLocals": true,
|
|
15
|
+
"noUnusedParameters": true,
|
|
16
|
+
"noFallthroughCasesInSwitch": true
|
|
17
|
+
},
|
|
18
|
+
"include": ["src"]
|
|
19
|
+
}
|