@core.sbs/create-core-app 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/README.md +130 -0
- package/bin/create-core-app.js +448 -0
- package/package.json +31 -0
- package/templates/default/README.md +95 -0
- package/templates/default/core-components.js +117 -0
- package/templates/default/index.html +203 -0
- package/templates/default/styles.css +355 -0
package/README.md
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# create-core-app
|
|
2
|
+
|
|
3
|
+
Scaffold a new core.js application with zero configuration.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
Install via npm:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install -g @core.sbs/create-core-app
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
### Quick Start
|
|
16
|
+
|
|
17
|
+
After installation:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
create-core-app my-app
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
The CLI will guide you through setup options:
|
|
24
|
+
- **Development server** - Install and start core-dev for hot reloading
|
|
25
|
+
- **Component generator** - Install core-gen for scaffolding components
|
|
26
|
+
- **Routing** - Enable SPA routing in your app
|
|
27
|
+
|
|
28
|
+
## Usage
|
|
29
|
+
|
|
30
|
+
### Interactive Prompts
|
|
31
|
+
|
|
32
|
+
The CLI will ask about optional tools:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
create-core-app my-app
|
|
36
|
+
? Would you like to install the development server? (Y/n)
|
|
37
|
+
? Would you like to install the component generator? (Y/n)
|
|
38
|
+
? Would you like to enable routing? (Y/n)
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Skip Auto-Start
|
|
42
|
+
|
|
43
|
+
If you don't want the dev server to start automatically:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
create-core-app my-app --no-server
|
|
47
|
+
cd my-app
|
|
48
|
+
core-dev
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Or link it globally for testing:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
cd cli/create-core-app
|
|
55
|
+
npm link
|
|
56
|
+
cd ../..
|
|
57
|
+
create-core-app my-app
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## What You Get
|
|
61
|
+
|
|
62
|
+
- Beautiful welcome page with live demos
|
|
63
|
+
- Interactive examples showing:
|
|
64
|
+
- Reactivity (counter demo)
|
|
65
|
+
- Data fetching (API integration)
|
|
66
|
+
- Routing (SPA navigation)
|
|
67
|
+
- Live framework stats
|
|
68
|
+
- Pre-configured core.js setup
|
|
69
|
+
- Starter styles
|
|
70
|
+
- Getting started guide
|
|
71
|
+
|
|
72
|
+
## Templates
|
|
73
|
+
|
|
74
|
+
### Default Template
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
create-core-app my-app
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Creates a welcome page with interactive demos and getting started guide.
|
|
81
|
+
|
|
82
|
+
### Coming Soon
|
|
83
|
+
|
|
84
|
+
- Dashboard template
|
|
85
|
+
- Blog template
|
|
86
|
+
- E-commerce template
|
|
87
|
+
|
|
88
|
+
## Features
|
|
89
|
+
|
|
90
|
+
- ✅ Zero build step - just open index.html
|
|
91
|
+
- ✅ No dependencies to install
|
|
92
|
+
- ✅ Works offline after first load
|
|
93
|
+
- ✅ Beautiful welcome page
|
|
94
|
+
- ✅ Live framework metrics
|
|
95
|
+
- ✅ Interactive demos
|
|
96
|
+
- ✅ Mobile responsive
|
|
97
|
+
|
|
98
|
+
## Next Steps
|
|
99
|
+
|
|
100
|
+
After creating your app:
|
|
101
|
+
|
|
102
|
+
1. **Install VS Code Extension** - Get 56 code snippets
|
|
103
|
+
```
|
|
104
|
+
Search for "core.js" in VS Code extensions tab and install
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
2. **Generate Components** - Use the component generator
|
|
108
|
+
```bash
|
|
109
|
+
core-gen form --validation
|
|
110
|
+
core-gen table --sortable
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
3. **Read the Docs** - Learn more about core.js
|
|
114
|
+
```
|
|
115
|
+
https://github.com/Sitezip/core.sbs
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## No Build Step Required
|
|
119
|
+
|
|
120
|
+
Unlike other frameworks, core.js apps don't need:
|
|
121
|
+
- ❌ npm install
|
|
122
|
+
- ❌ webpack/vite/rollup
|
|
123
|
+
- ❌ babel/typescript compilation
|
|
124
|
+
- ❌ build scripts
|
|
125
|
+
|
|
126
|
+
Just include the CDN script and start coding!
|
|
127
|
+
|
|
128
|
+
## License
|
|
129
|
+
|
|
130
|
+
MIT
|
|
@@ -0,0 +1,448 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const readline = require('readline');
|
|
6
|
+
const { spawn } = require('child_process');
|
|
7
|
+
|
|
8
|
+
const args = process.argv.slice(2);
|
|
9
|
+
const projectName = args[0] || 'my-core-app';
|
|
10
|
+
const template = args.find(arg => arg.startsWith('--template='))?.split('=')[1] || 'default';
|
|
11
|
+
|
|
12
|
+
// Embedded templates for standalone installation
|
|
13
|
+
const templates = {
|
|
14
|
+
default: {
|
|
15
|
+
'index.html': `<!DOCTYPE html>
|
|
16
|
+
<html lang="en">
|
|
17
|
+
<head>
|
|
18
|
+
<meta charset="UTF-8">
|
|
19
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
20
|
+
<title>core.sbs - Smoke Test</title>
|
|
21
|
+
<link rel="stylesheet" href="styles.css">
|
|
22
|
+
</head>
|
|
23
|
+
<body>
|
|
24
|
+
<div class="container">
|
|
25
|
+
<div class="logo">core.sbs</div>
|
|
26
|
+
<h1>It works!</h1>
|
|
27
|
+
<p>A lightweight, progressive JavaScript framework</p>
|
|
28
|
+
|
|
29
|
+
<div class="counter-box">
|
|
30
|
+
<div class="counter" id="counter">0</div>
|
|
31
|
+
<div class="counter-label">Live Counter</div>
|
|
32
|
+
</div>
|
|
33
|
+
|
|
34
|
+
<div class="buttons">
|
|
35
|
+
<button class="btn" onclick="increment()">+</button>
|
|
36
|
+
<button class="btn btn-secondary" onclick="decrement()">-</button>
|
|
37
|
+
<button class="btn btn-secondary" onclick="reset()">Reset</button>
|
|
38
|
+
</div>
|
|
39
|
+
</div>
|
|
40
|
+
|
|
41
|
+
<script src="https://cdn.jsdelivr.net/gh/Sitezip/core.sbs/core.js"></script>
|
|
42
|
+
<script>
|
|
43
|
+
let count = 0;
|
|
44
|
+
const counterEl = document.getElementById('counter');
|
|
45
|
+
|
|
46
|
+
function updateDisplay() {
|
|
47
|
+
counterEl.textContent = count;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function increment() {
|
|
51
|
+
count++;
|
|
52
|
+
updateDisplay();
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function decrement() {
|
|
56
|
+
count--;
|
|
57
|
+
updateDisplay();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function reset() {
|
|
61
|
+
count = 0;
|
|
62
|
+
updateDisplay();
|
|
63
|
+
}
|
|
64
|
+
</script>
|
|
65
|
+
</body>
|
|
66
|
+
</html>`,
|
|
67
|
+
'styles.css': `/* core.sbs Smoke Test Styles */
|
|
68
|
+
* {
|
|
69
|
+
margin: 0;
|
|
70
|
+
padding: 0;
|
|
71
|
+
box-sizing: border-box;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
body {
|
|
75
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
76
|
+
background: linear-gradient(135deg, #020617 0%, #0f172a 100%);
|
|
77
|
+
min-height: 100vh;
|
|
78
|
+
display: flex;
|
|
79
|
+
align-items: center;
|
|
80
|
+
justify-content: center;
|
|
81
|
+
color: white;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.container {
|
|
85
|
+
text-align: center;
|
|
86
|
+
padding: 2rem;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.logo {
|
|
90
|
+
font-size: 3rem;
|
|
91
|
+
font-weight: 800;
|
|
92
|
+
margin-bottom: 0.5rem;
|
|
93
|
+
background: linear-gradient(90deg, #10b981, #06b6d4);
|
|
94
|
+
-webkit-background-clip: text;
|
|
95
|
+
-webkit-text-fill-color: transparent;
|
|
96
|
+
background-clip: text;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
h1 {
|
|
100
|
+
font-size: 2rem;
|
|
101
|
+
margin-bottom: 0.5rem;
|
|
102
|
+
color: #10b981;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
p {
|
|
106
|
+
font-size: 1.1rem;
|
|
107
|
+
opacity: 0.7;
|
|
108
|
+
margin-bottom: 3rem;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.counter-box {
|
|
112
|
+
background: rgba(16, 185, 129, 0.1);
|
|
113
|
+
backdrop-filter: blur(10px);
|
|
114
|
+
border-radius: 20px;
|
|
115
|
+
padding: 2rem 4rem;
|
|
116
|
+
margin-bottom: 2rem;
|
|
117
|
+
border: 1px solid rgba(16, 185, 129, 0.2);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.counter {
|
|
121
|
+
font-size: 5rem;
|
|
122
|
+
font-weight: 700;
|
|
123
|
+
line-height: 1;
|
|
124
|
+
margin-bottom: 0.5rem;
|
|
125
|
+
color: #10b981;
|
|
126
|
+
text-shadow: 0 0 30px rgba(16, 185, 129, 0.5);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.counter-label {
|
|
130
|
+
font-size: 0.9rem;
|
|
131
|
+
opacity: 0.6;
|
|
132
|
+
text-transform: uppercase;
|
|
133
|
+
letter-spacing: 2px;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.buttons {
|
|
137
|
+
display: flex;
|
|
138
|
+
gap: 1rem;
|
|
139
|
+
justify-content: center;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.btn {
|
|
143
|
+
background: #10b981;
|
|
144
|
+
color: white;
|
|
145
|
+
border: none;
|
|
146
|
+
padding: 1rem 2rem;
|
|
147
|
+
border-radius: 10px;
|
|
148
|
+
font-size: 1.2rem;
|
|
149
|
+
font-weight: 600;
|
|
150
|
+
cursor: pointer;
|
|
151
|
+
transition: all 0.2s;
|
|
152
|
+
min-width: 60px;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
.btn:hover {
|
|
156
|
+
transform: translateY(-2px);
|
|
157
|
+
box-shadow: 0 10px 30px rgba(16, 185, 129, 0.3);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.btn-secondary {
|
|
161
|
+
background: rgba(6, 182, 212, 0.2);
|
|
162
|
+
color: #06b6d4;
|
|
163
|
+
border: 1px solid rgba(6, 182, 212, 0.3);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.btn-secondary:hover {
|
|
167
|
+
background: rgba(6, 182, 212, 0.3);
|
|
168
|
+
box-shadow: 0 10px 30px rgba(6, 182, 212, 0.2);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
@media (max-width: 480px) {
|
|
172
|
+
.logo { font-size: 2rem; }
|
|
173
|
+
h1 { font-size: 1.5rem; }
|
|
174
|
+
.counter { font-size: 3rem; }
|
|
175
|
+
.counter-box { padding: 1.5rem 2rem; }
|
|
176
|
+
.buttons { flex-direction: column; }
|
|
177
|
+
.btn { width: 100%; }
|
|
178
|
+
}`,
|
|
179
|
+
'core-components.js': `/**
|
|
180
|
+
* core-components.js
|
|
181
|
+
* Component loader for core.js applications
|
|
182
|
+
* No build step required - just include this script
|
|
183
|
+
*/
|
|
184
|
+
|
|
185
|
+
(function() {
|
|
186
|
+
'use strict';
|
|
187
|
+
|
|
188
|
+
// Component cache
|
|
189
|
+
const componentCache = {};
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Load a component from the components/ folder
|
|
193
|
+
* @param {string} componentName - Name of the component file (without .html extension)
|
|
194
|
+
* @returns {Promise<void>}
|
|
195
|
+
*/
|
|
196
|
+
window.loadComponent = async function(componentName) {
|
|
197
|
+
// Check cache first
|
|
198
|
+
if (componentCache[componentName]) {
|
|
199
|
+
console.log(\`✓ Component "\${componentName}" already loaded\`);
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
try {
|
|
204
|
+
const response = await fetch(\`components/\${componentName}.html\`);
|
|
205
|
+
|
|
206
|
+
if (!response.ok) {
|
|
207
|
+
throw new Error(\`Failed to load component: \${response.statusText}\`);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const html = await response.text();
|
|
211
|
+
|
|
212
|
+
// Create a temporary container to parse the HTML
|
|
213
|
+
const temp = document.createElement('div');
|
|
214
|
+
temp.innerHTML = html;
|
|
215
|
+
|
|
216
|
+
// Extract and inject templates into cr-data section
|
|
217
|
+
const templates = temp.querySelectorAll('template');
|
|
218
|
+
const crData = document.getElementById('cr-data');
|
|
219
|
+
|
|
220
|
+
if (crData && templates.length > 0) {
|
|
221
|
+
templates.forEach(template => {
|
|
222
|
+
crData.appendChild(template.cloneNode(true));
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// Extract and inject styles
|
|
227
|
+
const styles = temp.querySelectorAll('style');
|
|
228
|
+
styles.forEach(style => {
|
|
229
|
+
document.head.appendChild(style.cloneNode(true));
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
// Extract and inject scripts
|
|
233
|
+
const scripts = temp.querySelectorAll('script');
|
|
234
|
+
scripts.forEach(script => {
|
|
235
|
+
const newScript = document.createElement('script');
|
|
236
|
+
newScript.textContent = script.textContent;
|
|
237
|
+
document.head.appendChild(newScript);
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
// Mark as loaded
|
|
241
|
+
componentCache[componentName] = true;
|
|
242
|
+
console.log(\`✓ Component "\${componentName}" loaded successfully\`);
|
|
243
|
+
|
|
244
|
+
} catch (error) {
|
|
245
|
+
console.error(\`❌ Failed to load component "\${componentName}":\`, error);
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
// Auto-load components when DOM is ready
|
|
250
|
+
if (document.readyState === 'loading') {
|
|
251
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
252
|
+
console.log('🚀 core-components.js loaded');
|
|
253
|
+
});
|
|
254
|
+
} else {
|
|
255
|
+
console.log('🚀 core-components.js loaded');
|
|
256
|
+
}
|
|
257
|
+
})();`,
|
|
258
|
+
'README.md': `# Your Core.js App
|
|
259
|
+
|
|
260
|
+
Welcome to your new core.js application!
|
|
261
|
+
|
|
262
|
+
## Getting Started
|
|
263
|
+
|
|
264
|
+
1. **Open index.html in your browser**
|
|
265
|
+
- No build step required!
|
|
266
|
+
- Just double-click the file or serve it with a web server
|
|
267
|
+
|
|
268
|
+
2. **Start development (optional)**
|
|
269
|
+
\`\`\`bash
|
|
270
|
+
# If you installed the CLI tools:
|
|
271
|
+
core-dev
|
|
272
|
+
|
|
273
|
+
# Or open directly in browser
|
|
274
|
+
\`\`\`
|
|
275
|
+
|
|
276
|
+
## What's Included
|
|
277
|
+
|
|
278
|
+
- ✅ **Core.js Framework** - Modern client-side rendering
|
|
279
|
+
- ✅ **Hot Reload Ready** - Use core-dev for live updates
|
|
280
|
+
- ✅ **Component System** - Modular architecture
|
|
281
|
+
- ✅ **Responsive Design** - Mobile-friendly styles
|
|
282
|
+
|
|
283
|
+
## Learn More
|
|
284
|
+
|
|
285
|
+
- [Core.js Documentation](https://github.com/Sitezip/core.sbs)
|
|
286
|
+
- [VS Code Extension](https://github.com/Sitezip/core.sbs/releases)
|
|
287
|
+
- [Component Generator](https://github.com/Sitezip/core.sbs/tree/main/cli/core-gen)
|
|
288
|
+
|
|
289
|
+
## Next Steps
|
|
290
|
+
|
|
291
|
+
1. Edit \`index.html\` to build your app
|
|
292
|
+
2. Create components in the \`components/\` folder
|
|
293
|
+
3. Use \`core-gen\` to generate pre-built components:
|
|
294
|
+
\`\`\`bash
|
|
295
|
+
core-gen form --validation
|
|
296
|
+
core-gen table --sortable
|
|
297
|
+
\`\`\`
|
|
298
|
+
|
|
299
|
+
Happy coding! 🚀`
|
|
300
|
+
}
|
|
301
|
+
};
|
|
302
|
+
|
|
303
|
+
// Create readline interface for prompts
|
|
304
|
+
const rl = readline.createInterface({
|
|
305
|
+
input: process.stdin,
|
|
306
|
+
output: process.stdout
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
// Promisify question
|
|
310
|
+
function ask(question) {
|
|
311
|
+
return new Promise((resolve) => {
|
|
312
|
+
rl.question(question, (answer) => {
|
|
313
|
+
resolve(answer.toLowerCase().trim());
|
|
314
|
+
});
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
console.log(`
|
|
319
|
+
╔═══════════════════════════════════════╗
|
|
320
|
+
║ ║
|
|
321
|
+
║ create-core-app ║
|
|
322
|
+
║ ║
|
|
323
|
+
╚═══════════════════════════════════════╝
|
|
324
|
+
`);
|
|
325
|
+
|
|
326
|
+
async function main() {
|
|
327
|
+
console.log(`Creating a new core.js app in ${projectName}/\n`);
|
|
328
|
+
|
|
329
|
+
// Ask user preferences
|
|
330
|
+
console.log('📋 Let\'s configure your project:\n');
|
|
331
|
+
|
|
332
|
+
const installDevServer = await ask('Install dev server with hot reload? (Y/n): ');
|
|
333
|
+
const wantsDevServer = installDevServer === '' || installDevServer === 'y' || installDevServer === 'yes';
|
|
334
|
+
|
|
335
|
+
const installComponentGen = await ask('Install component generator? (Y/n): ');
|
|
336
|
+
const wantsComponentGen = installComponentGen === '' || installComponentGen === 'y' || installComponentGen === 'yes';
|
|
337
|
+
|
|
338
|
+
const enableRoutingAnswer = await ask('Enable routing? (Y/n): ');
|
|
339
|
+
const wantsRouting = enableRoutingAnswer === '' || enableRoutingAnswer === 'y' || enableRoutingAnswer === 'yes';
|
|
340
|
+
|
|
341
|
+
rl.close();
|
|
342
|
+
|
|
343
|
+
console.log('');
|
|
344
|
+
|
|
345
|
+
// Create project directory
|
|
346
|
+
const projectPath = path.join(process.cwd(), projectName);
|
|
347
|
+
|
|
348
|
+
if (fs.existsSync(projectPath)) {
|
|
349
|
+
console.error(`❌ Error: Directory "${projectName}" already exists.`);
|
|
350
|
+
process.exit(1);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
fs.mkdirSync(projectPath, { recursive: true });
|
|
354
|
+
|
|
355
|
+
// Copy template files from embedded templates
|
|
356
|
+
const templateData = templates[template];
|
|
357
|
+
|
|
358
|
+
if (!templateData) {
|
|
359
|
+
console.error(`❌ Error: Template "${template}" not found.`);
|
|
360
|
+
process.exit(1);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
console.log('📦 Creating template files...');
|
|
364
|
+
|
|
365
|
+
// Write each template file
|
|
366
|
+
Object.entries(templateData).forEach(([filename, content]) => {
|
|
367
|
+
const filePath = path.join(projectPath, filename);
|
|
368
|
+
fs.writeFileSync(filePath, content);
|
|
369
|
+
console.log(` ✓ Created ${filename}`);
|
|
370
|
+
});
|
|
371
|
+
|
|
372
|
+
// Update routing in index.html based on user choice
|
|
373
|
+
const indexPath = path.join(projectPath, 'index.html');
|
|
374
|
+
if (fs.existsSync(indexPath)) {
|
|
375
|
+
let indexContent = fs.readFileSync(indexPath, 'utf8');
|
|
376
|
+
if (!wantsRouting) {
|
|
377
|
+
indexContent = indexContent.replace('core.useRouting = true;', 'core.useRouting = false;');
|
|
378
|
+
}
|
|
379
|
+
fs.writeFileSync(indexPath, indexContent);
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
console.log(`
|
|
383
|
+
✅ Success! Created ${projectName} at ${projectPath}
|
|
384
|
+
|
|
385
|
+
Optional: Install the VS Code extension for 56 code snippets:
|
|
386
|
+
https://github.com/Sitezip/core.sbs/releases
|
|
387
|
+
`);
|
|
388
|
+
|
|
389
|
+
if (wantsComponentGen) {
|
|
390
|
+
console.log(`
|
|
391
|
+
📦 Component generator available!
|
|
392
|
+
|
|
393
|
+
Generate pre-built components:
|
|
394
|
+
core-gen form --validation --name=contact
|
|
395
|
+
core-gen table --name=users
|
|
396
|
+
core-gen modal --name=confirm
|
|
397
|
+
`);
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
if (!wantsDevServer) {
|
|
401
|
+
console.log(`
|
|
402
|
+
To start the dev server:
|
|
403
|
+
cd ${projectName}
|
|
404
|
+
core-dev
|
|
405
|
+
|
|
406
|
+
Happy coding! 🎉
|
|
407
|
+
`);
|
|
408
|
+
} else {
|
|
409
|
+
console.log(`
|
|
410
|
+
🚀 Starting dev server...
|
|
411
|
+
|
|
412
|
+
`);
|
|
413
|
+
|
|
414
|
+
// Start dev server
|
|
415
|
+
const coreDevPath = path.join(process.env.USERPROFILE || process.env.HOME, '.core-sbs', 'core-dev.js');
|
|
416
|
+
console.log('Dev server path:', coreDevPath);
|
|
417
|
+
|
|
418
|
+
const devServer = spawn('node', [coreDevPath], {
|
|
419
|
+
cwd: projectPath,
|
|
420
|
+
stdio: 'inherit',
|
|
421
|
+
shell: true
|
|
422
|
+
});
|
|
423
|
+
|
|
424
|
+
devServer.on('error', (err) => {
|
|
425
|
+
console.error(`❌ Failed to start dev server: ${err.message}`);
|
|
426
|
+
console.log(`
|
|
427
|
+
Make sure core-dev is installed:
|
|
428
|
+
curl -sSL https://raw.githubusercontent.com/Sitezip/core.sbs/main/install.sh | bash
|
|
429
|
+
|
|
430
|
+
Or start it manually:
|
|
431
|
+
cd ${projectName}
|
|
432
|
+
core-dev
|
|
433
|
+
`);
|
|
434
|
+
});
|
|
435
|
+
|
|
436
|
+
// Handle Ctrl+C
|
|
437
|
+
process.on('SIGINT', () => {
|
|
438
|
+
devServer.kill();
|
|
439
|
+
process.exit(0);
|
|
440
|
+
});
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
// Run main function
|
|
445
|
+
main().catch(err => {
|
|
446
|
+
console.error('Error:', err);
|
|
447
|
+
process.exit(1);
|
|
448
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@core.sbs/create-core-app",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Scaffold a new core.js application. Optionally include a development server, component generator, and more.",
|
|
5
|
+
"bin": {
|
|
6
|
+
"create-core-app": "./bin/create-core-app.js"
|
|
7
|
+
},
|
|
8
|
+
"keywords": [
|
|
9
|
+
"core.js",
|
|
10
|
+
"scaffold",
|
|
11
|
+
"create-app",
|
|
12
|
+
"boilerplate",
|
|
13
|
+
"development server",
|
|
14
|
+
"component generator",
|
|
15
|
+
"cli",
|
|
16
|
+
"scaffolding",
|
|
17
|
+
"create-core-app"
|
|
18
|
+
],
|
|
19
|
+
"author": "core.js team",
|
|
20
|
+
"license": "MIT",
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "https://github.com/Sitezip/core.sbs"
|
|
24
|
+
},
|
|
25
|
+
"engines": {
|
|
26
|
+
"node": ">=14.0.0"
|
|
27
|
+
},
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"@core-js/dev": "^1.0.0"
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# Welcome to Your core.js App!
|
|
2
|
+
|
|
3
|
+
Your app is ready to go. Open `index.html` in your browser to see it in action.
|
|
4
|
+
|
|
5
|
+
## What's Included
|
|
6
|
+
|
|
7
|
+
- **index.html** - Main application file with welcome page
|
|
8
|
+
- **styles.css** - Starter styles
|
|
9
|
+
- **README.md** - This file
|
|
10
|
+
|
|
11
|
+
## Getting Started
|
|
12
|
+
|
|
13
|
+
1. Open `index.html` in your browser
|
|
14
|
+
2. See the welcome page with live demos
|
|
15
|
+
3. Start editing `index.html` to build your app
|
|
16
|
+
|
|
17
|
+
## Quick Tips
|
|
18
|
+
|
|
19
|
+
### Adding a New Template
|
|
20
|
+
|
|
21
|
+
```html
|
|
22
|
+
<template name="myTemplate">
|
|
23
|
+
<div>
|
|
24
|
+
<h2>{{data:myTemplate:title}}</h2>
|
|
25
|
+
<p>{{data:myTemplate:description}}</p>
|
|
26
|
+
</div>
|
|
27
|
+
</template>
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Creating a Pocket
|
|
31
|
+
|
|
32
|
+
```html
|
|
33
|
+
<div class="core-pocket"
|
|
34
|
+
data-core-templates="myTemplate"
|
|
35
|
+
data-core-source-myTemplate="/api/data">
|
|
36
|
+
</div>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Fetching Data
|
|
40
|
+
|
|
41
|
+
```javascript
|
|
42
|
+
await core.be.getData('myData', '/api/endpoint');
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Generate Components
|
|
46
|
+
|
|
47
|
+
Use the component generator to quickly add pre-built components:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
core-gen form --validation --name=contact
|
|
51
|
+
core-gen table --name=users
|
|
52
|
+
core-gen modal --name=confirm
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Components are generated into the `components/` folder.
|
|
56
|
+
|
|
57
|
+
### Loading Components
|
|
58
|
+
|
|
59
|
+
Components are automatically loaded using `core-components.js`:
|
|
60
|
+
|
|
61
|
+
```html
|
|
62
|
+
<script src="core-components.js"></script>
|
|
63
|
+
<script>
|
|
64
|
+
// Load a single component
|
|
65
|
+
loadComponent('contact-form');
|
|
66
|
+
|
|
67
|
+
// Load multiple components
|
|
68
|
+
loadComponents(['users-table', 'confirm-modal']);
|
|
69
|
+
</script>
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
The component loader will:
|
|
73
|
+
- Inject templates into your `#cr-data` section
|
|
74
|
+
- Add styles to the page
|
|
75
|
+
- Execute component scripts
|
|
76
|
+
- Initialize core.js pockets automatically
|
|
77
|
+
|
|
78
|
+
**No build step required!** Just generate and load.
|
|
79
|
+
|
|
80
|
+
## Resources
|
|
81
|
+
|
|
82
|
+
- [Documentation](https://github.com/Sitezip/core.sbs)
|
|
83
|
+
- [VS Code Extension](https://github.com/Sitezip/core.sbs/releases)
|
|
84
|
+
- [GitHub Repository](https://github.com/Sitezip/core.sbs)
|
|
85
|
+
|
|
86
|
+
## Next Steps
|
|
87
|
+
|
|
88
|
+
1. Install the VS Code extension for 56 code snippets
|
|
89
|
+
2. Read the full documentation
|
|
90
|
+
3. Explore the interactive demos on the welcome page
|
|
91
|
+
4. Start building!
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
Built with ❤️ using core.js
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* core-components.js
|
|
3
|
+
* Component loader for core.js applications
|
|
4
|
+
* No build step required - just include this script
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
(function() {
|
|
8
|
+
'use strict';
|
|
9
|
+
|
|
10
|
+
// Component cache
|
|
11
|
+
const componentCache = {};
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Load a component from the components/ folder
|
|
15
|
+
* @param {string} componentName - Name of the component file (without .html extension)
|
|
16
|
+
* @returns {Promise<void>}
|
|
17
|
+
*/
|
|
18
|
+
window.loadComponent = async function(componentName) {
|
|
19
|
+
// Check cache first
|
|
20
|
+
if (componentCache[componentName]) {
|
|
21
|
+
console.log(`✓ Component "${componentName}" already loaded`);
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
try {
|
|
26
|
+
const response = await fetch(`components/${componentName}.html`);
|
|
27
|
+
|
|
28
|
+
if (!response.ok) {
|
|
29
|
+
throw new Error(`Failed to load component: ${response.statusText}`);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const html = await response.text();
|
|
33
|
+
|
|
34
|
+
// Create a temporary container to parse the HTML
|
|
35
|
+
const temp = document.createElement('div');
|
|
36
|
+
temp.innerHTML = html;
|
|
37
|
+
|
|
38
|
+
// Extract and inject templates into cr-data section
|
|
39
|
+
const templates = temp.querySelectorAll('template');
|
|
40
|
+
const crData = document.getElementById('cr-data');
|
|
41
|
+
|
|
42
|
+
if (crData && templates.length > 0) {
|
|
43
|
+
templates.forEach(template => {
|
|
44
|
+
crData.appendChild(template.cloneNode(true));
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Extract and inject styles
|
|
49
|
+
const styles = temp.querySelectorAll('style');
|
|
50
|
+
styles.forEach(style => {
|
|
51
|
+
document.head.appendChild(style.cloneNode(true));
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
// Extract and execute scripts
|
|
55
|
+
const scripts = temp.querySelectorAll('script');
|
|
56
|
+
scripts.forEach(script => {
|
|
57
|
+
const newScript = document.createElement('script');
|
|
58
|
+
if (script.src) {
|
|
59
|
+
newScript.src = script.src;
|
|
60
|
+
} else {
|
|
61
|
+
newScript.textContent = script.textContent;
|
|
62
|
+
}
|
|
63
|
+
document.body.appendChild(newScript);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// Inject pockets into the body (or specified container)
|
|
67
|
+
const pockets = temp.querySelectorAll('.core-pocket');
|
|
68
|
+
const componentContainer = document.getElementById('component-container') || document.body;
|
|
69
|
+
pockets.forEach(pocket => {
|
|
70
|
+
componentContainer.appendChild(pocket.cloneNode(true));
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
// Inject any other elements (buttons, etc.)
|
|
74
|
+
const otherElements = Array.from(temp.children).filter(
|
|
75
|
+
el => !el.matches('template, style, script, .core-pocket')
|
|
76
|
+
);
|
|
77
|
+
otherElements.forEach(el => {
|
|
78
|
+
componentContainer.appendChild(el.cloneNode(true));
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
// Mark as loaded
|
|
82
|
+
componentCache[componentName] = true;
|
|
83
|
+
console.log(`✓ Component "${componentName}" loaded successfully`);
|
|
84
|
+
|
|
85
|
+
// Reinitialize pockets if core.js is loaded
|
|
86
|
+
if (window.core && window.core.pk && window.core.pk.init) {
|
|
87
|
+
await core.pk.init();
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
} catch (error) {
|
|
91
|
+
console.error(`✗ Error loading component "${componentName}":`, error);
|
|
92
|
+
throw error;
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Load multiple components
|
|
98
|
+
* @param {string[]} componentNames - Array of component names
|
|
99
|
+
* @returns {Promise<void>}
|
|
100
|
+
*/
|
|
101
|
+
window.loadComponents = async function(componentNames) {
|
|
102
|
+
for (const name of componentNames) {
|
|
103
|
+
await loadComponent(name);
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Check if a component is loaded
|
|
109
|
+
* @param {string} componentName - Name of the component
|
|
110
|
+
* @returns {boolean}
|
|
111
|
+
*/
|
|
112
|
+
window.isComponentLoaded = function(componentName) {
|
|
113
|
+
return !!componentCache[componentName];
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
console.log('✓ core-components.js loaded');
|
|
117
|
+
})();
|
|
@@ -0,0 +1,203 @@
|
|
|
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>Welcome to core.js</title>
|
|
7
|
+
<link rel="stylesheet" href="styles.css">
|
|
8
|
+
</head>
|
|
9
|
+
<body>
|
|
10
|
+
<!-- Main Container -->
|
|
11
|
+
<div id="app">
|
|
12
|
+
<!-- Welcome Pocket -->
|
|
13
|
+
<div class="core-pocket" data-core-templates="welcome"></div>
|
|
14
|
+
|
|
15
|
+
<!-- Live Stats Pocket -->
|
|
16
|
+
<div class="core-pocket" data-core-templates="stats"></div>
|
|
17
|
+
|
|
18
|
+
<!-- Demo Sections -->
|
|
19
|
+
<div class="core-pocket" data-core-templates="demos"></div>
|
|
20
|
+
</div>
|
|
21
|
+
|
|
22
|
+
<!-- Template Registry -->
|
|
23
|
+
<section id="cr-data" class="template-registry">
|
|
24
|
+
|
|
25
|
+
<!-- Welcome Template -->
|
|
26
|
+
<template name="welcome">
|
|
27
|
+
<div class="welcome-hero">
|
|
28
|
+
<div class="logo-container">
|
|
29
|
+
<svg class="logo" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg">
|
|
30
|
+
<circle cx="100" cy="100" r="90" fill="none" stroke="url(#gradient)" stroke-width="8"/>
|
|
31
|
+
<text x="100" y="115" text-anchor="middle" font-size="60" font-weight="bold" fill="url(#gradient)">C</text>
|
|
32
|
+
<defs>
|
|
33
|
+
<linearGradient id="gradient" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
34
|
+
<stop offset="0%" style="stop-color:#6366f1;stop-opacity:1" />
|
|
35
|
+
<stop offset="100%" style="stop-color:#10b981;stop-opacity:1" />
|
|
36
|
+
</linearGradient>
|
|
37
|
+
</defs>
|
|
38
|
+
</svg>
|
|
39
|
+
</div>
|
|
40
|
+
<h1 class="welcome-title">🎉 Your core.js App is Running!</h1>
|
|
41
|
+
<p class="welcome-subtitle">Everything is working perfectly. Start building something amazing.</p>
|
|
42
|
+
|
|
43
|
+
<div class="quick-links">
|
|
44
|
+
<a href="https://github.com/Sitezip/core.sbs" target="_blank" rel="noopener noreferrer" class="btn btn-primary">View Docs</a>
|
|
45
|
+
<a href="https://github.com/Sitezip/core.sbs/releases" target="_blank" rel="noopener noreferrer" class="btn btn-secondary">Get VS Code Extension</a>
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
</template>
|
|
49
|
+
|
|
50
|
+
<!-- Stats Template -->
|
|
51
|
+
<template name="stats">
|
|
52
|
+
<div class="stats-container">
|
|
53
|
+
<h2>Live Framework Stats</h2>
|
|
54
|
+
<div class="stats-grid">
|
|
55
|
+
<div class="stat-card">
|
|
56
|
+
<div class="stat-icon">📦</div>
|
|
57
|
+
<div class="stat-value" id="cacheHits">0</div>
|
|
58
|
+
<div class="stat-label">Cache Hits</div>
|
|
59
|
+
</div>
|
|
60
|
+
<div class="stat-card">
|
|
61
|
+
<div class="stat-icon">🌐</div>
|
|
62
|
+
<div class="stat-value" id="dataCalls">0</div>
|
|
63
|
+
<div class="stat-label">Data Calls</div>
|
|
64
|
+
</div>
|
|
65
|
+
<div class="stat-card">
|
|
66
|
+
<div class="stat-icon">📄</div>
|
|
67
|
+
<div class="stat-value" id="templates">0</div>
|
|
68
|
+
<div class="stat-label">Templates</div>
|
|
69
|
+
</div>
|
|
70
|
+
<div class="stat-card">
|
|
71
|
+
<div class="stat-icon">🔄</div>
|
|
72
|
+
<div class="stat-value" id="clones">0</div>
|
|
73
|
+
<div class="stat-label">Clones</div>
|
|
74
|
+
</div>
|
|
75
|
+
</div>
|
|
76
|
+
</div>
|
|
77
|
+
</template>
|
|
78
|
+
|
|
79
|
+
<!-- Demos Template -->
|
|
80
|
+
<template name="demos">
|
|
81
|
+
<div class="demos-container">
|
|
82
|
+
<h2>Interactive Demos</h2>
|
|
83
|
+
|
|
84
|
+
<!-- Counter Demo -->
|
|
85
|
+
<div class="demo-card">
|
|
86
|
+
<h3>✨ Reactivity Demo</h3>
|
|
87
|
+
<p>Click the button to see data binding in action</p>
|
|
88
|
+
<div class="counter-demo">
|
|
89
|
+
<button onclick="incrementCounter()" class="btn btn-primary">Click Me!</button>
|
|
90
|
+
<div class="counter-display">
|
|
91
|
+
<span class="counter-label">Count:</span>
|
|
92
|
+
<span class="counter-value" id="counterValue">0</span>
|
|
93
|
+
</div>
|
|
94
|
+
</div>
|
|
95
|
+
</div>
|
|
96
|
+
|
|
97
|
+
<!-- Data Fetch Demo -->
|
|
98
|
+
<div class="demo-card">
|
|
99
|
+
<h3>🌐 Data Fetching Demo</h3>
|
|
100
|
+
<p>Fetch and display data from an API</p>
|
|
101
|
+
<button onclick="fetchDemoData()" class="btn btn-secondary">Fetch Random User</button>
|
|
102
|
+
<div class="core-pocket" data-core-templates="userData" id="userDataPocket"></div>
|
|
103
|
+
</div>
|
|
104
|
+
|
|
105
|
+
<!-- Routing Demo -->
|
|
106
|
+
<div class="demo-card">
|
|
107
|
+
<h3>🧭 Routing Demo</h3>
|
|
108
|
+
<p>Navigate between views without page reload</p>
|
|
109
|
+
<div class="routing-links">
|
|
110
|
+
<a href="#/_main/welcome" class="route-link">Home</a>
|
|
111
|
+
<a href="#/_main/about" class="route-link">About</a>
|
|
112
|
+
<a href="#/_main/contact" class="route-link">Contact</a>
|
|
113
|
+
</div>
|
|
114
|
+
</div>
|
|
115
|
+
|
|
116
|
+
<!-- Getting Started -->
|
|
117
|
+
<div class="demo-card getting-started">
|
|
118
|
+
<h3>🚀 Getting Started</h3>
|
|
119
|
+
<p>Edit <code>index.html</code> to start building your app</p>
|
|
120
|
+
<ul class="checklist">
|
|
121
|
+
<li>✅ core.js loaded and running</li>
|
|
122
|
+
<li>✅ Templates rendering correctly</li>
|
|
123
|
+
<li>✅ Data binding working</li>
|
|
124
|
+
<li>✅ Routing enabled</li>
|
|
125
|
+
</ul>
|
|
126
|
+
<div class="next-steps">
|
|
127
|
+
<h4>Next Steps:</h4>
|
|
128
|
+
<ol>
|
|
129
|
+
<li>Read the <a href="https://github.com/Sitezip/core.sbs" target="_blank" rel="noopener noreferrer">documentation</a></li>
|
|
130
|
+
<li>Install the <a href="https://github.com/Sitezip/core.sbs/releases" target="_blank" rel="noopener noreferrer">VS Code extension</a></li>
|
|
131
|
+
<li>Generate components with <code>core-gen form</code></li>
|
|
132
|
+
<li>Build something awesome!</li>
|
|
133
|
+
</ol>
|
|
134
|
+
</div>
|
|
135
|
+
</div>
|
|
136
|
+
</div>
|
|
137
|
+
</template>
|
|
138
|
+
|
|
139
|
+
<!-- User Data Template -->
|
|
140
|
+
<template name="userData">
|
|
141
|
+
<div class="user-card">
|
|
142
|
+
<div class="user-avatar">
|
|
143
|
+
<img src="{{data:userData:picture:large}}" alt="User avatar">
|
|
144
|
+
</div>
|
|
145
|
+
<div class="user-info">
|
|
146
|
+
<h4>{{data:userData:name:first}} {{data:userData:name:last}}</h4>
|
|
147
|
+
<p>{{data:userData:email}}</p>
|
|
148
|
+
<p>{{data:userData:location:city}}, {{data:userData:location:country}}</p>
|
|
149
|
+
</div>
|
|
150
|
+
</div>
|
|
151
|
+
</template>
|
|
152
|
+
|
|
153
|
+
</section>
|
|
154
|
+
|
|
155
|
+
<!-- Core.js Framework -->
|
|
156
|
+
<script src="https://cdn.jsdelivr.net/gh/Sitezip/core.sbs/core.js"></script>
|
|
157
|
+
|
|
158
|
+
<!-- Component Loader -->
|
|
159
|
+
<script src="core-components.js"></script>
|
|
160
|
+
|
|
161
|
+
<!-- Application Logic -->
|
|
162
|
+
<script>
|
|
163
|
+
// Initialize core.js
|
|
164
|
+
core.ud.init = () => {
|
|
165
|
+
core.useRouting = true;
|
|
166
|
+
core.useDebugger = true;
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
// Counter state
|
|
170
|
+
let counter = 0;
|
|
171
|
+
|
|
172
|
+
// Increment counter
|
|
173
|
+
function incrementCounter() {
|
|
174
|
+
counter++;
|
|
175
|
+
document.getElementById('counterValue').textContent = counter;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Fetch demo data
|
|
179
|
+
async function fetchDemoData() {
|
|
180
|
+
await core.be.getData('userData', 'https://randomuser.me/api/', {
|
|
181
|
+
transform: (data) => data.results[0]
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Update stats
|
|
186
|
+
function updateStats() {
|
|
187
|
+
const cacheHits = Object.keys(core.be.cacheCreateTs.data || {}).length;
|
|
188
|
+
const dataCalls = Object.keys(core.be.fetchLogFIFO || {}).length;
|
|
189
|
+
const templates = document.querySelectorAll('#cr-data template').length;
|
|
190
|
+
const clones = document.querySelectorAll('.core-cloned').length;
|
|
191
|
+
|
|
192
|
+
document.getElementById('cacheHits').textContent = cacheHits;
|
|
193
|
+
document.getElementById('dataCalls').textContent = dataCalls;
|
|
194
|
+
document.getElementById('templates').textContent = templates;
|
|
195
|
+
document.getElementById('clones').textContent = clones;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// Update stats every second
|
|
199
|
+
setInterval(updateStats, 1000);
|
|
200
|
+
updateStats();
|
|
201
|
+
</script>
|
|
202
|
+
</body>
|
|
203
|
+
</html>
|
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
/* Core.js Welcome Page Styles */
|
|
2
|
+
|
|
3
|
+
* {
|
|
4
|
+
margin: 0;
|
|
5
|
+
padding: 0;
|
|
6
|
+
box-sizing: border-box;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/* Template Registry (hidden) */
|
|
10
|
+
.template-registry {
|
|
11
|
+
display: none;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
body {
|
|
15
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
|
|
16
|
+
background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%);
|
|
17
|
+
color: #e2e8f0;
|
|
18
|
+
min-height: 100vh;
|
|
19
|
+
padding: 2rem;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
#app {
|
|
23
|
+
max-width: 1200px;
|
|
24
|
+
margin: 0 auto;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/* Welcome Hero */
|
|
28
|
+
.welcome-hero {
|
|
29
|
+
text-align: center;
|
|
30
|
+
padding: 4rem 2rem;
|
|
31
|
+
margin-bottom: 3rem;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.logo-container {
|
|
35
|
+
margin-bottom: 2rem;
|
|
36
|
+
animation: float 3s ease-in-out infinite;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.logo {
|
|
40
|
+
width: 150px;
|
|
41
|
+
height: 150px;
|
|
42
|
+
filter: drop-shadow(0 0 20px rgba(99, 102, 241, 0.5));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
@keyframes float {
|
|
46
|
+
0%, 100% { transform: translateY(0px); }
|
|
47
|
+
50% { transform: translateY(-10px); }
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.welcome-title {
|
|
51
|
+
font-size: 3rem;
|
|
52
|
+
font-weight: 800;
|
|
53
|
+
background: linear-gradient(135deg, #6366f1 0%, #10b981 100%);
|
|
54
|
+
-webkit-background-clip: text;
|
|
55
|
+
-webkit-text-fill-color: transparent;
|
|
56
|
+
background-clip: text;
|
|
57
|
+
margin-bottom: 1rem;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.welcome-subtitle {
|
|
61
|
+
font-size: 1.25rem;
|
|
62
|
+
color: #94a3b8;
|
|
63
|
+
margin-bottom: 2rem;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.quick-links {
|
|
67
|
+
display: flex;
|
|
68
|
+
gap: 1rem;
|
|
69
|
+
justify-content: center;
|
|
70
|
+
flex-wrap: wrap;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/* Buttons */
|
|
74
|
+
.btn {
|
|
75
|
+
padding: 0.75rem 1.5rem;
|
|
76
|
+
border-radius: 0.5rem;
|
|
77
|
+
font-weight: 600;
|
|
78
|
+
text-decoration: none;
|
|
79
|
+
transition: all 0.3s ease;
|
|
80
|
+
border: none;
|
|
81
|
+
cursor: pointer;
|
|
82
|
+
font-size: 1rem;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.btn-primary {
|
|
86
|
+
background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%);
|
|
87
|
+
color: white;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
.btn-primary:hover {
|
|
91
|
+
transform: translateY(-2px);
|
|
92
|
+
box-shadow: 0 10px 20px rgba(99, 102, 241, 0.3);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.btn-secondary {
|
|
96
|
+
background: rgba(255, 255, 255, 0.1);
|
|
97
|
+
color: #e2e8f0;
|
|
98
|
+
border: 1px solid rgba(255, 255, 255, 0.2);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.btn-secondary:hover {
|
|
102
|
+
background: rgba(255, 255, 255, 0.15);
|
|
103
|
+
transform: translateY(-2px);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/* Stats Container */
|
|
107
|
+
.stats-container {
|
|
108
|
+
margin-bottom: 3rem;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.stats-container h2 {
|
|
112
|
+
text-align: center;
|
|
113
|
+
font-size: 2rem;
|
|
114
|
+
margin-bottom: 2rem;
|
|
115
|
+
color: #f1f5f9;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.stats-grid {
|
|
119
|
+
display: grid;
|
|
120
|
+
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
|
121
|
+
gap: 1.5rem;
|
|
122
|
+
margin-bottom: 3rem;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.stat-card {
|
|
126
|
+
background: rgba(255, 255, 255, 0.05);
|
|
127
|
+
border: 1px solid rgba(255, 255, 255, 0.1);
|
|
128
|
+
border-radius: 1rem;
|
|
129
|
+
padding: 2rem;
|
|
130
|
+
text-align: center;
|
|
131
|
+
transition: all 0.3s ease;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.stat-card:hover {
|
|
135
|
+
background: rgba(255, 255, 255, 0.08);
|
|
136
|
+
transform: translateY(-5px);
|
|
137
|
+
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.stat-icon {
|
|
141
|
+
font-size: 2.5rem;
|
|
142
|
+
margin-bottom: 1rem;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.stat-value {
|
|
146
|
+
font-size: 2.5rem;
|
|
147
|
+
font-weight: 800;
|
|
148
|
+
background: linear-gradient(135deg, #6366f1 0%, #10b981 100%);
|
|
149
|
+
-webkit-background-clip: text;
|
|
150
|
+
-webkit-text-fill-color: transparent;
|
|
151
|
+
background-clip: text;
|
|
152
|
+
margin-bottom: 0.5rem;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
.stat-label {
|
|
156
|
+
font-size: 0.875rem;
|
|
157
|
+
color: #94a3b8;
|
|
158
|
+
text-transform: uppercase;
|
|
159
|
+
letter-spacing: 0.05em;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/* Demos Container */
|
|
163
|
+
.demos-container {
|
|
164
|
+
margin-bottom: 3rem;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
.demos-container h2 {
|
|
168
|
+
text-align: center;
|
|
169
|
+
font-size: 2rem;
|
|
170
|
+
margin-bottom: 2rem;
|
|
171
|
+
color: #f1f5f9;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
.demo-card {
|
|
175
|
+
background: rgba(255, 255, 255, 0.05);
|
|
176
|
+
border: 1px solid rgba(255, 255, 255, 0.1);
|
|
177
|
+
border-radius: 1rem;
|
|
178
|
+
padding: 2rem;
|
|
179
|
+
margin-bottom: 1.5rem;
|
|
180
|
+
transition: all 0.3s ease;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
.demo-card:hover {
|
|
184
|
+
background: rgba(255, 255, 255, 0.08);
|
|
185
|
+
border-color: rgba(99, 102, 241, 0.3);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.demo-card h3 {
|
|
189
|
+
font-size: 1.5rem;
|
|
190
|
+
margin-bottom: 0.5rem;
|
|
191
|
+
color: #f1f5f9;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
.demo-card p {
|
|
195
|
+
color: #94a3b8;
|
|
196
|
+
margin-bottom: 1.5rem;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/* Counter Demo */
|
|
200
|
+
.counter-demo {
|
|
201
|
+
display: flex;
|
|
202
|
+
align-items: center;
|
|
203
|
+
gap: 2rem;
|
|
204
|
+
flex-wrap: wrap;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
.counter-display {
|
|
208
|
+
display: flex;
|
|
209
|
+
align-items: center;
|
|
210
|
+
gap: 1rem;
|
|
211
|
+
background: rgba(99, 102, 241, 0.1);
|
|
212
|
+
padding: 1rem 2rem;
|
|
213
|
+
border-radius: 0.5rem;
|
|
214
|
+
border: 1px solid rgba(99, 102, 241, 0.3);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
.counter-label {
|
|
218
|
+
font-size: 1rem;
|
|
219
|
+
color: #94a3b8;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
.counter-value {
|
|
223
|
+
font-size: 2rem;
|
|
224
|
+
font-weight: 800;
|
|
225
|
+
color: #6366f1;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/* User Card */
|
|
229
|
+
.user-card {
|
|
230
|
+
display: flex;
|
|
231
|
+
align-items: center;
|
|
232
|
+
gap: 1.5rem;
|
|
233
|
+
background: rgba(16, 185, 129, 0.1);
|
|
234
|
+
padding: 1.5rem;
|
|
235
|
+
border-radius: 0.75rem;
|
|
236
|
+
border: 1px solid rgba(16, 185, 129, 0.3);
|
|
237
|
+
margin-top: 1rem;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
.user-avatar img {
|
|
241
|
+
width: 80px;
|
|
242
|
+
height: 80px;
|
|
243
|
+
border-radius: 50%;
|
|
244
|
+
border: 3px solid #10b981;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
.user-info h4 {
|
|
248
|
+
font-size: 1.25rem;
|
|
249
|
+
margin-bottom: 0.5rem;
|
|
250
|
+
color: #f1f5f9;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
.user-info p {
|
|
254
|
+
color: #94a3b8;
|
|
255
|
+
margin-bottom: 0.25rem;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/* Routing Links */
|
|
259
|
+
.routing-links {
|
|
260
|
+
display: flex;
|
|
261
|
+
gap: 1rem;
|
|
262
|
+
flex-wrap: wrap;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
.route-link {
|
|
266
|
+
padding: 0.75rem 1.5rem;
|
|
267
|
+
background: rgba(139, 92, 246, 0.1);
|
|
268
|
+
border: 1px solid rgba(139, 92, 246, 0.3);
|
|
269
|
+
border-radius: 0.5rem;
|
|
270
|
+
color: #a78bfa;
|
|
271
|
+
text-decoration: none;
|
|
272
|
+
transition: all 0.3s ease;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
.route-link:hover {
|
|
276
|
+
background: rgba(139, 92, 246, 0.2);
|
|
277
|
+
transform: translateY(-2px);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/* Getting Started */
|
|
281
|
+
.getting-started {
|
|
282
|
+
background: rgba(16, 185, 129, 0.05);
|
|
283
|
+
border-color: rgba(16, 185, 129, 0.2);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
.getting-started code {
|
|
287
|
+
background: rgba(0, 0, 0, 0.3);
|
|
288
|
+
padding: 0.25rem 0.5rem;
|
|
289
|
+
border-radius: 0.25rem;
|
|
290
|
+
color: #10b981;
|
|
291
|
+
font-family: 'Courier New', monospace;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
.checklist {
|
|
295
|
+
list-style: none;
|
|
296
|
+
margin: 1.5rem 0;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
.checklist li {
|
|
300
|
+
padding: 0.5rem 0;
|
|
301
|
+
color: #10b981;
|
|
302
|
+
font-size: 1.1rem;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
.next-steps {
|
|
306
|
+
margin-top: 2rem;
|
|
307
|
+
padding-top: 2rem;
|
|
308
|
+
border-top: 1px solid rgba(255, 255, 255, 0.1);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
.next-steps h4 {
|
|
312
|
+
font-size: 1.25rem;
|
|
313
|
+
margin-bottom: 1rem;
|
|
314
|
+
color: #f1f5f9;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
.next-steps ol {
|
|
318
|
+
margin-left: 1.5rem;
|
|
319
|
+
color: #94a3b8;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
.next-steps li {
|
|
323
|
+
margin-bottom: 0.75rem;
|
|
324
|
+
line-height: 1.6;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
.next-steps a {
|
|
328
|
+
color: #10b981;
|
|
329
|
+
text-decoration: none;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
.next-steps a:hover {
|
|
333
|
+
text-decoration: underline;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/* Responsive */
|
|
337
|
+
@media (max-width: 768px) {
|
|
338
|
+
.welcome-title {
|
|
339
|
+
font-size: 2rem;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
.stats-grid {
|
|
343
|
+
grid-template-columns: repeat(2, 1fr);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
.counter-demo {
|
|
347
|
+
flex-direction: column;
|
|
348
|
+
align-items: stretch;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
.user-card {
|
|
352
|
+
flex-direction: column;
|
|
353
|
+
text-align: center;
|
|
354
|
+
}
|
|
355
|
+
}
|