create-aziz-app 2.0.2 → 2.0.4
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-aziz-app.js +367 -47
- package/package.json +11 -8
- package/template/README.md +8 -0
- package/template/app.html +4 -110
- package/template/docs/CSS-FRAMEWORKS.md +221 -0
- package/template/docs/STYLING.md +269 -0
- package/template/package.json +1 -1
- package/template/styles/globals.css +190 -0
- package/template/styles/tailwind.css +122 -0
- package/app.js +0 -88
- package/template/pages/NewPage.jsx +0 -39
- /package/template/pages/{Test.jsx → test.jsx} +0 -0
package/bin/create-aziz-app.js
CHANGED
|
@@ -1,64 +1,384 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
const fs
|
|
3
|
+
const fs = require("fs");
|
|
4
4
|
const path = require("path");
|
|
5
|
+
const readline = require("readline");
|
|
5
6
|
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
|
|
7
|
+
// Create readline interface
|
|
8
|
+
const rl = readline.createInterface({
|
|
9
|
+
input: process.stdin,
|
|
10
|
+
output: process.stdout
|
|
11
|
+
});
|
|
9
12
|
|
|
10
|
-
|
|
13
|
+
// Promisify question
|
|
14
|
+
function question(query) {
|
|
15
|
+
return new Promise(resolve => rl.question(query, resolve));
|
|
16
|
+
}
|
|
11
17
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
18
|
+
// Main function
|
|
19
|
+
async function main() {
|
|
20
|
+
console.log(`\n⚡ Welcome to Aziz App Creator!\n`);
|
|
21
|
+
console.log(`🎨 A React-like framework with state management, routing, and API routes\n`);
|
|
22
|
+
|
|
23
|
+
// Get project name
|
|
24
|
+
let projectName = process.argv[2];
|
|
25
|
+
if (!projectName) {
|
|
26
|
+
projectName = await question('📁 Project name (my-aziz-app): ');
|
|
27
|
+
projectName = projectName.trim() || 'my-aziz-app';
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Validate project name
|
|
31
|
+
if (!/^[a-z0-9-_]+$/i.test(projectName)) {
|
|
32
|
+
console.error(`❌ Invalid project name. Use only letters, numbers, hyphens, and underscores.`);
|
|
33
|
+
rl.close();
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const targetDir = path.join(process.cwd(), projectName);
|
|
38
|
+
|
|
39
|
+
// Check if directory exists
|
|
40
|
+
if (fs.existsSync(targetDir)) {
|
|
41
|
+
const overwrite = await question(`⚠️ Folder "${projectName}" already exists. Overwrite? (y/N): `);
|
|
42
|
+
if (overwrite.toLowerCase() !== 'y' && overwrite.toLowerCase() !== 'yes') {
|
|
43
|
+
console.log('❌ Cancelled.');
|
|
44
|
+
rl.close();
|
|
45
|
+
process.exit(0);
|
|
46
|
+
}
|
|
47
|
+
// Remove existing directory
|
|
48
|
+
fs.rmSync(targetDir, { recursive: true, force: true });
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Ask for port
|
|
52
|
+
let port = await question('🌐 Dev server port (3000): ');
|
|
53
|
+
port = port.trim() || '3000';
|
|
54
|
+
if (!/^\d+$/.test(port)) {
|
|
55
|
+
console.log('⚠️ Invalid port, using default 3000');
|
|
56
|
+
port = '3000';
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Ask for features
|
|
60
|
+
console.log('\n✨ Features to include:');
|
|
61
|
+
const includeExamples = await question(' Include example pages? (Y/n): ');
|
|
62
|
+
const includeApiExamples = await question(' Include example API routes? (Y/n): ');
|
|
63
|
+
const includeDocs = await question(' Include documentation? (Y/n): ');
|
|
64
|
+
|
|
65
|
+
// Ask for CSS framework
|
|
66
|
+
console.log('\n🎨 CSS Framework:');
|
|
67
|
+
console.log(' 1. None (custom CSS)');
|
|
68
|
+
console.log(' 2. Bootstrap 5');
|
|
69
|
+
console.log(' 3. Tailwind CSS');
|
|
70
|
+
const cssChoice = await question(' Choose (1/2/3): ');
|
|
71
|
+
|
|
72
|
+
let cssFramework = 'none';
|
|
73
|
+
if (cssChoice === '2') cssFramework = 'bootstrap';
|
|
74
|
+
else if (cssChoice === '3') cssFramework = 'tailwind';
|
|
75
|
+
|
|
76
|
+
const features = {
|
|
77
|
+
examples: includeExamples.toLowerCase() !== 'n' && includeExamples.toLowerCase() !== 'no',
|
|
78
|
+
apiExamples: includeApiExamples.toLowerCase() !== 'n' && includeApiExamples.toLowerCase() !== 'no',
|
|
79
|
+
docs: includeDocs.toLowerCase() !== 'n' && includeDocs.toLowerCase() !== 'no',
|
|
80
|
+
cssFramework: cssFramework
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
console.log(`\n⚡ Creating "${projectName}"...\n`);
|
|
84
|
+
|
|
85
|
+
const templateDir = path.join(__dirname, "../template");
|
|
86
|
+
|
|
87
|
+
// Copy the template
|
|
88
|
+
copyDir(templateDir, targetDir, features);
|
|
89
|
+
|
|
90
|
+
// Update package.json with project name
|
|
91
|
+
updatePackageJson(targetDir, projectName);
|
|
92
|
+
|
|
93
|
+
// Update dev server port
|
|
94
|
+
updateDevServerPort(targetDir, port);
|
|
95
|
+
|
|
96
|
+
// Setup CSS framework
|
|
97
|
+
setupCSSFramework(targetDir, features.cssFramework);
|
|
98
|
+
|
|
99
|
+
console.log(`✅ Done! Your project is ready.\n`);
|
|
100
|
+
console.log(`🎉 Welcome to Aziz App - A React-like Framework\n`);
|
|
101
|
+
console.log(`📁 Created project: ${projectName}\n`);
|
|
102
|
+
console.log(`👉 Get started:\n`);
|
|
103
|
+
console.log(` cd ${projectName}`);
|
|
104
|
+
console.log(` npm install`);
|
|
105
|
+
console.log(` npm run dev\n`);
|
|
106
|
+
console.log(`🌐 Dev server will run on: http://localhost:${port}/\n`);
|
|
107
|
+
console.log(`📂 Project structure:\n`);
|
|
108
|
+
console.log(` app.html ← Main HTML file`);
|
|
109
|
+
console.log(` modules/ ← Core system (router, state, API)`);
|
|
110
|
+
console.log(` pages/ ← Your pages (auto-imported)`);
|
|
111
|
+
console.log(` components/ ← Your components (auto-imported)`);
|
|
112
|
+
console.log(` api/ ← Your API routes (auto-imported)`);
|
|
113
|
+
console.log(` scripts/ ← Build tools`);
|
|
114
|
+
if (features.docs) {
|
|
115
|
+
console.log(` docs/ ← Documentation`);
|
|
116
|
+
}
|
|
117
|
+
console.log(`\n✨ Features:\n`);
|
|
118
|
+
console.log(` • State Management - useState() like React`);
|
|
119
|
+
console.log(` • File-based Routing - pages/About.jsx → #/about`);
|
|
120
|
+
console.log(` • API Routes - Next.js-like API system`);
|
|
121
|
+
console.log(` • Auto-Import - No manual script tags!`);
|
|
122
|
+
console.log(` • Live Reload - Instant browser refresh`);
|
|
123
|
+
if (features.cssFramework === 'bootstrap') {
|
|
124
|
+
console.log(` • Bootstrap 5 - Responsive CSS framework`);
|
|
125
|
+
} else if (features.cssFramework === 'tailwind') {
|
|
126
|
+
console.log(` • Tailwind CSS - Utility-first CSS framework`);
|
|
127
|
+
}
|
|
128
|
+
console.log(`\n💡 Quick tips:\n`);
|
|
129
|
+
console.log(` • Create pages/MyPage.jsx → Auto-imported!`);
|
|
130
|
+
console.log(` • Create api/todos.js → Auto-imported!`);
|
|
131
|
+
console.log(` • Just save and browser refreshes automatically`);
|
|
132
|
+
if (features.docs) {
|
|
133
|
+
console.log(` • Read docs/ folder for detailed guides`);
|
|
134
|
+
}
|
|
135
|
+
console.log(`\n🚀 Ready to build something awesome!\n`);
|
|
136
|
+
|
|
137
|
+
rl.close();
|
|
15
138
|
}
|
|
16
139
|
|
|
17
|
-
//
|
|
18
|
-
copyDir(
|
|
19
|
-
|
|
20
|
-
console.log(`✅ Done! Your project is ready.\n`);
|
|
21
|
-
console.log(`🎉 Welcome to Aziz App - A React-like Framework\n`);
|
|
22
|
-
console.log(`📁 Created project: ${projectName}\n`);
|
|
23
|
-
console.log(`👉 Get started:\n`);
|
|
24
|
-
console.log(` cd ${projectName}`);
|
|
25
|
-
console.log(` npm run dev\n`);
|
|
26
|
-
console.log(`🌐 This will:`);
|
|
27
|
-
console.log(` • Start dev server on http://localhost:3000/`);
|
|
28
|
-
console.log(` • Watch for file changes`);
|
|
29
|
-
console.log(` • Auto-import new files`);
|
|
30
|
-
console.log(` • Live reload browser\n`);
|
|
31
|
-
console.log(`� Project structure:\n`);
|
|
32
|
-
console.log(` app.html ← Main HTML file`);
|
|
33
|
-
console.log(` modules/ ← Core system (router, state, API)`);
|
|
34
|
-
console.log(` pages/ ← Your pages (auto-imported)`);
|
|
35
|
-
console.log(` components/ ← Your components (auto-imported)`);
|
|
36
|
-
console.log(` api/ ← Your API routes (auto-imported)`);
|
|
37
|
-
console.log(` scripts/ ← Build tools`);
|
|
38
|
-
console.log(` docs/ ← Documentation\n`);
|
|
39
|
-
console.log(`✨ Features:\n`);
|
|
40
|
-
console.log(` • State Management - useState() like React`);
|
|
41
|
-
console.log(` • File-based Routing - pages/About.jsx → #/about`);
|
|
42
|
-
console.log(` • API Routes - Next.js-like API system`);
|
|
43
|
-
console.log(` • Auto-Import - No manual script tags!`);
|
|
44
|
-
console.log(` • Live Reload - Instant browser refresh\n`);
|
|
45
|
-
console.log(`💡 Quick tips:\n`);
|
|
46
|
-
console.log(` • Create pages/MyPage.jsx → Auto-imported!`);
|
|
47
|
-
console.log(` • Create api/todos.js → Auto-imported!`);
|
|
48
|
-
console.log(` • Just save and browser refreshes automatically`);
|
|
49
|
-
console.log(` • Read docs/ folder for detailed guides\n`);
|
|
50
|
-
console.log(`🚀 Ready to build something awesome!\n`);
|
|
51
|
-
|
|
52
|
-
// ---- Helper ----
|
|
53
|
-
function copyDir(src, dest) {
|
|
140
|
+
// Helper to copy directory with filters
|
|
141
|
+
function copyDir(src, dest, features) {
|
|
54
142
|
fs.mkdirSync(dest, { recursive: true });
|
|
143
|
+
|
|
55
144
|
for (let file of fs.readdirSync(src)) {
|
|
56
|
-
const srcPath
|
|
145
|
+
const srcPath = path.join(src, file);
|
|
57
146
|
const destPath = path.join(dest, file);
|
|
147
|
+
|
|
148
|
+
// Skip certain files based on features
|
|
149
|
+
if (!features.docs && file === 'docs') continue;
|
|
150
|
+
if (!features.examples && file === 'pages' && fs.statSync(srcPath).isDirectory()) {
|
|
151
|
+
// Copy only essential pages
|
|
152
|
+
fs.mkdirSync(destPath, { recursive: true });
|
|
153
|
+
fs.copyFileSync(path.join(srcPath, 'Home.jsx'), path.join(destPath, 'Home.jsx'));
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
if (!features.apiExamples && file === 'api' && fs.statSync(srcPath).isDirectory()) {
|
|
157
|
+
// Skip API examples
|
|
158
|
+
fs.mkdirSync(destPath, { recursive: true });
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
|
|
58
162
|
if (fs.statSync(srcPath).isDirectory()) {
|
|
59
|
-
copyDir(srcPath, destPath);
|
|
163
|
+
copyDir(srcPath, destPath, features);
|
|
60
164
|
} else {
|
|
61
165
|
fs.copyFileSync(srcPath, destPath);
|
|
62
166
|
}
|
|
63
167
|
}
|
|
64
168
|
}
|
|
169
|
+
|
|
170
|
+
// Update package.json with project name
|
|
171
|
+
function updatePackageJson(targetDir, projectName) {
|
|
172
|
+
const packageJsonPath = path.join(targetDir, 'package.json');
|
|
173
|
+
if (fs.existsSync(packageJsonPath)) {
|
|
174
|
+
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
175
|
+
packageJson.name = projectName;
|
|
176
|
+
fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2));
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// Update dev server port
|
|
181
|
+
function updateDevServerPort(targetDir, port) {
|
|
182
|
+
const devServerPath = path.join(targetDir, 'scripts', 'dev-server.js');
|
|
183
|
+
if (fs.existsSync(devServerPath)) {
|
|
184
|
+
let content = fs.readFileSync(devServerPath, 'utf8');
|
|
185
|
+
content = content.replace(
|
|
186
|
+
'const PORT = process.env.PORT || 3000;',
|
|
187
|
+
`const PORT = process.env.PORT || ${port};`
|
|
188
|
+
);
|
|
189
|
+
fs.writeFileSync(devServerPath, content);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Setup CSS framework
|
|
194
|
+
function setupCSSFramework(targetDir, framework) {
|
|
195
|
+
const htmlPath = path.join(targetDir, 'app.html');
|
|
196
|
+
if (!fs.existsSync(htmlPath)) return;
|
|
197
|
+
|
|
198
|
+
let html = fs.readFileSync(htmlPath, 'utf8');
|
|
199
|
+
|
|
200
|
+
if (framework === 'bootstrap') {
|
|
201
|
+
// Replace globals.css with Bootstrap CDN
|
|
202
|
+
html = html.replace(
|
|
203
|
+
'<link rel="stylesheet" href="styles/globals.css">',
|
|
204
|
+
`<!-- Bootstrap 5 CSS -->
|
|
205
|
+
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
|
206
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.1/font/bootstrap-icons.css">`
|
|
207
|
+
);
|
|
208
|
+
|
|
209
|
+
// Add Bootstrap JS before closing body tag
|
|
210
|
+
const bootstrapJS = `
|
|
211
|
+
<!-- Bootstrap 5 JS -->
|
|
212
|
+
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
|
213
|
+
|
|
214
|
+
`;
|
|
215
|
+
html = html.replace('</body>', bootstrapJS + '</body>');
|
|
216
|
+
|
|
217
|
+
// Update components
|
|
218
|
+
updateComponentsForBootstrap(targetDir);
|
|
219
|
+
|
|
220
|
+
} else if (framework === 'tailwind') {
|
|
221
|
+
// Replace globals.css with Tailwind CSS
|
|
222
|
+
html = html.replace(
|
|
223
|
+
'<link rel="stylesheet" href="styles/globals.css">',
|
|
224
|
+
`<!-- Tailwind CSS -->
|
|
225
|
+
<link rel="stylesheet" href="styles/tailwind.css">
|
|
226
|
+
<script src="https://cdn.tailwindcss.com"></script>
|
|
227
|
+
<script>
|
|
228
|
+
tailwind.config = {
|
|
229
|
+
theme: {
|
|
230
|
+
extend: {
|
|
231
|
+
colors: {
|
|
232
|
+
primary: '#61dafb',
|
|
233
|
+
dark: '#282c34'
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
</script>`
|
|
239
|
+
);
|
|
240
|
+
|
|
241
|
+
// Update components
|
|
242
|
+
updateComponentsForTailwind(targetDir);
|
|
243
|
+
}
|
|
244
|
+
// If 'none', keep globals.css as is
|
|
245
|
+
|
|
246
|
+
fs.writeFileSync(htmlPath, html);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// Update components for Bootstrap
|
|
250
|
+
function updateComponentsForBootstrap(targetDir) {
|
|
251
|
+
// Update Navbar
|
|
252
|
+
const navbarPath = path.join(targetDir, 'components', 'Navbar.jsx');
|
|
253
|
+
if (fs.existsSync(navbarPath)) {
|
|
254
|
+
const navbarContent = `/** @jsx h */
|
|
255
|
+
|
|
256
|
+
function Navbar() {
|
|
257
|
+
const path = getCurrentPath();
|
|
258
|
+
|
|
259
|
+
return (
|
|
260
|
+
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
|
261
|
+
<div class="container-fluid">
|
|
262
|
+
<span class="navbar-brand" onClick={() => navigate("home")} style={{ cursor: 'pointer' }}>
|
|
263
|
+
⚡ AzizApp
|
|
264
|
+
</span>
|
|
265
|
+
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
|
|
266
|
+
<span class="navbar-toggler-icon"></span>
|
|
267
|
+
</button>
|
|
268
|
+
<div class="collapse navbar-collapse" id="navbarNav">
|
|
269
|
+
<ul class="navbar-nav">
|
|
270
|
+
<li class="nav-item">
|
|
271
|
+
<a href="#/home" class={\`nav-link \${path === "home" ? "active" : ""}\`}>Home</a>
|
|
272
|
+
</li>
|
|
273
|
+
<li class="nav-item">
|
|
274
|
+
<a href="#/about" class={\`nav-link \${path === "about" ? "active" : ""}\`}>About</a>
|
|
275
|
+
</li>
|
|
276
|
+
<li class="nav-item">
|
|
277
|
+
<a href="#/contact" class={\`nav-link \${path === "contact" ? "active" : ""}\`}>Contact</a>
|
|
278
|
+
</li>
|
|
279
|
+
<li class="nav-item">
|
|
280
|
+
<a href="#/test" class={\`nav-link \${path === "test" ? "active" : ""}\`}>Test</a>
|
|
281
|
+
</li>
|
|
282
|
+
<li class="nav-item">
|
|
283
|
+
<a href="#/api-demo" class={\`nav-link \${path === "api-demo" ? "active" : ""}\`}>API Demo</a>
|
|
284
|
+
</li>
|
|
285
|
+
</ul>
|
|
286
|
+
</div>
|
|
287
|
+
</div>
|
|
288
|
+
</nav>
|
|
289
|
+
);
|
|
290
|
+
}
|
|
291
|
+
`;
|
|
292
|
+
fs.writeFileSync(navbarPath, navbarContent);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// Update Footer
|
|
296
|
+
const footerPath = path.join(targetDir, 'components', 'Footer.jsx');
|
|
297
|
+
if (fs.existsSync(footerPath)) {
|
|
298
|
+
const footerContent = `/** @jsx h */
|
|
299
|
+
|
|
300
|
+
function Footer() {
|
|
301
|
+
return (
|
|
302
|
+
<footer class="bg-dark text-light text-center py-3 mt-auto">
|
|
303
|
+
<div class="container">
|
|
304
|
+
<p class="mb-0">Made with ⚡ AzizApp</p>
|
|
305
|
+
</div>
|
|
306
|
+
</footer>
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
`;
|
|
310
|
+
fs.writeFileSync(footerPath, footerContent);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// Update components for Tailwind
|
|
315
|
+
function updateComponentsForTailwind(targetDir) {
|
|
316
|
+
// Update Navbar
|
|
317
|
+
const navbarPath = path.join(targetDir, 'components', 'Navbar.jsx');
|
|
318
|
+
if (fs.existsSync(navbarPath)) {
|
|
319
|
+
const navbarContent = `/** @jsx h */
|
|
320
|
+
|
|
321
|
+
function Navbar() {
|
|
322
|
+
const path = getCurrentPath();
|
|
323
|
+
|
|
324
|
+
return (
|
|
325
|
+
<nav class="bg-dark shadow-lg">
|
|
326
|
+
<div class="container mx-auto px-4">
|
|
327
|
+
<div class="flex items-center justify-between h-16">
|
|
328
|
+
<span
|
|
329
|
+
class="text-primary text-xl font-bold cursor-pointer hover:text-blue-300 transition"
|
|
330
|
+
onClick={() => navigate("home")}
|
|
331
|
+
>
|
|
332
|
+
⚡ AzizApp
|
|
333
|
+
</span>
|
|
334
|
+
<div class="flex space-x-4">
|
|
335
|
+
<a href="#/home" class={\`px-3 py-2 rounded-md text-sm font-medium transition \${path === "home" ? "bg-primary text-dark" : "text-gray-300 hover:bg-gray-700 hover:text-white"}\`}>
|
|
336
|
+
Home
|
|
337
|
+
</a>
|
|
338
|
+
<a href="#/about" class={\`px-3 py-2 rounded-md text-sm font-medium transition \${path === "about" ? "bg-primary text-dark" : "text-gray-300 hover:bg-gray-700 hover:text-white"}\`}>
|
|
339
|
+
About
|
|
340
|
+
</a>
|
|
341
|
+
<a href="#/contact" class={\`px-3 py-2 rounded-md text-sm font-medium transition \${path === "contact" ? "bg-primary text-dark" : "text-gray-300 hover:bg-gray-700 hover:text-white"}\`}>
|
|
342
|
+
Contact
|
|
343
|
+
</a>
|
|
344
|
+
<a href="#/test" class={\`px-3 py-2 rounded-md text-sm font-medium transition \${path === "test" ? "bg-primary text-dark" : "text-gray-300 hover:bg-gray-700 hover:text-white"}\`}>
|
|
345
|
+
Test
|
|
346
|
+
</a>
|
|
347
|
+
<a href="#/api-demo" class={\`px-3 py-2 rounded-md text-sm font-medium transition \${path === "api-demo" ? "bg-primary text-dark" : "text-gray-300 hover:bg-gray-700 hover:text-white"}\`}>
|
|
348
|
+
API Demo
|
|
349
|
+
</a>
|
|
350
|
+
</div>
|
|
351
|
+
</div>
|
|
352
|
+
</div>
|
|
353
|
+
</nav>
|
|
354
|
+
);
|
|
355
|
+
}
|
|
356
|
+
`;
|
|
357
|
+
fs.writeFileSync(navbarPath, navbarContent);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
// Update Footer
|
|
361
|
+
const footerPath = path.join(targetDir, 'components', 'Footer.jsx');
|
|
362
|
+
if (fs.existsSync(footerPath)) {
|
|
363
|
+
const footerContent = `/** @jsx h */
|
|
364
|
+
|
|
365
|
+
function Footer() {
|
|
366
|
+
return (
|
|
367
|
+
<footer class="bg-dark text-gray-400 text-center py-4 mt-auto">
|
|
368
|
+
<div class="container mx-auto">
|
|
369
|
+
<p>Made with ⚡ AzizApp</p>
|
|
370
|
+
</div>
|
|
371
|
+
</footer>
|
|
372
|
+
);
|
|
373
|
+
}
|
|
374
|
+
`;
|
|
375
|
+
fs.writeFileSync(footerPath, footerContent);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// Run main function
|
|
380
|
+
main().catch(err => {
|
|
381
|
+
console.error('❌ Error:', err);
|
|
382
|
+
rl.close();
|
|
383
|
+
process.exit(1);
|
|
384
|
+
});
|
package/package.json
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-aziz-app",
|
|
3
|
-
"version": "2.0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "2.0.4",
|
|
4
|
+
"description": "A React-like framework with state management, routing, and API routes - Create apps with auto-import, live reload, and Next.js-like features",
|
|
5
5
|
"keywords": [
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
"
|
|
6
|
+
"react",
|
|
7
|
+
"framework",
|
|
8
|
+
"cli",
|
|
9
|
+
"create-app",
|
|
10
|
+
"routing",
|
|
11
|
+
"state-management",
|
|
12
|
+
"api-routes",
|
|
13
|
+
"live-reload"
|
|
10
14
|
],
|
|
11
|
-
"license": "
|
|
15
|
+
"license": "MIT",
|
|
12
16
|
"author": "Syed Muhammad Aziz Ahmed",
|
|
13
17
|
"type": "commonjs",
|
|
14
18
|
"files": [
|
|
@@ -18,7 +22,6 @@
|
|
|
18
22
|
"bin": {
|
|
19
23
|
"create-aziz-app": "bin/create-aziz-app.js"
|
|
20
24
|
},
|
|
21
|
-
"main": "app.js",
|
|
22
25
|
"scripts": {
|
|
23
26
|
"dev": "cd template && node scripts/dev-server.js",
|
|
24
27
|
"build": "cd template && node scripts/generate-imports.js",
|
package/template/README.md
CHANGED
|
@@ -122,6 +122,14 @@ const response = await fetchApi('/api/todos');
|
|
|
122
122
|
const data = await response.json();
|
|
123
123
|
```
|
|
124
124
|
|
|
125
|
+
### CSS Frameworks
|
|
126
|
+
Choose your preferred styling:
|
|
127
|
+
- **Custom CSS** - Built-in responsive styles
|
|
128
|
+
- **Bootstrap 5** - Popular component framework
|
|
129
|
+
- **Tailwind CSS** - Utility-first framework
|
|
130
|
+
|
|
131
|
+
The CLI will automatically set up your chosen framework!
|
|
132
|
+
|
|
125
133
|
### Auto-Import
|
|
126
134
|
- Create files in `pages/`, `components/`, or `api/`
|
|
127
135
|
- Dev server automatically detects them
|
package/template/app.html
CHANGED
|
@@ -5,116 +5,11 @@
|
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
6
|
<title>My Aziz App</title>
|
|
7
7
|
|
|
8
|
+
<!-- Global Styles -->
|
|
9
|
+
<link rel="stylesheet" href="styles/globals.css">
|
|
10
|
+
|
|
8
11
|
<!-- Babel compiles JSX in the browser -->
|
|
9
12
|
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
|
|
10
|
-
|
|
11
|
-
<style>
|
|
12
|
-
/* ---- Reset ---- */
|
|
13
|
-
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
14
|
-
|
|
15
|
-
body {
|
|
16
|
-
font-family: Arial, sans-serif;
|
|
17
|
-
background-color: #f5f5f5;
|
|
18
|
-
color: #333;
|
|
19
|
-
min-height: 100vh;
|
|
20
|
-
display: flex;
|
|
21
|
-
flex-direction: column;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/* ---- Navbar ---- */
|
|
25
|
-
nav {
|
|
26
|
-
background-color: #282c34;
|
|
27
|
-
padding: 16px 32px;
|
|
28
|
-
display: flex;
|
|
29
|
-
align-items: center;
|
|
30
|
-
gap: 24px;
|
|
31
|
-
}
|
|
32
|
-
nav .brand {
|
|
33
|
-
color: #61dafb;
|
|
34
|
-
font-size: 20px;
|
|
35
|
-
font-weight: bold;
|
|
36
|
-
cursor: pointer;
|
|
37
|
-
}
|
|
38
|
-
nav a {
|
|
39
|
-
color: #ffffffcc;
|
|
40
|
-
text-decoration: none;
|
|
41
|
-
font-size: 15px;
|
|
42
|
-
transition: color 0.2s;
|
|
43
|
-
}
|
|
44
|
-
nav a:hover, nav a.active { color: #61dafb; }
|
|
45
|
-
|
|
46
|
-
/* ---- Page wrapper ---- */
|
|
47
|
-
#root {
|
|
48
|
-
flex: 1;
|
|
49
|
-
padding: 40px 32px;
|
|
50
|
-
max-width: 900px;
|
|
51
|
-
width: 100%;
|
|
52
|
-
margin: 0 auto;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/* ---- Footer ---- */
|
|
56
|
-
footer {
|
|
57
|
-
background-color: #282c34;
|
|
58
|
-
color: #888;
|
|
59
|
-
text-align: center;
|
|
60
|
-
padding: 16px;
|
|
61
|
-
font-size: 13px;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/* ---- Utility styles ---- */
|
|
65
|
-
h1 { margin-bottom: 16px; color: #282c34; }
|
|
66
|
-
h2 { margin-bottom: 12px; }
|
|
67
|
-
p { line-height: 1.6; margin-bottom: 12px; color: #555; }
|
|
68
|
-
|
|
69
|
-
.card {
|
|
70
|
-
background: white;
|
|
71
|
-
border-radius: 10px;
|
|
72
|
-
padding: 24px;
|
|
73
|
-
box-shadow: 0 2px 8px rgba(0,0,0,0.08);
|
|
74
|
-
margin-bottom: 20px;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
.btn {
|
|
78
|
-
display: inline-block;
|
|
79
|
-
padding: 10px 22px;
|
|
80
|
-
border: none;
|
|
81
|
-
border-radius: 8px;
|
|
82
|
-
cursor: pointer;
|
|
83
|
-
font-size: 15px;
|
|
84
|
-
transition: opacity 0.2s;
|
|
85
|
-
}
|
|
86
|
-
.btn:hover { opacity: 0.85; }
|
|
87
|
-
.btn-primary { background-color: #61dafb; color: #282c34; font-weight: bold; }
|
|
88
|
-
.btn-danger { background-color: #ff6b6b; color: white; }
|
|
89
|
-
.btn-grey { background-color: #ccc; color: #333; }
|
|
90
|
-
|
|
91
|
-
/* ---- Counter (on home page) ---- */
|
|
92
|
-
.count-display {
|
|
93
|
-
font-size: 64px;
|
|
94
|
-
font-weight: bold;
|
|
95
|
-
color: #282c34;
|
|
96
|
-
margin: 16px 0;
|
|
97
|
-
text-align: center;
|
|
98
|
-
}
|
|
99
|
-
.counter-actions { display: flex; gap: 12px; justify-content: center; margin-top: 8px; }
|
|
100
|
-
|
|
101
|
-
/* ---- Form ---- */
|
|
102
|
-
form { display: flex; flex-direction: column; gap: 12px; }
|
|
103
|
-
input, textarea {
|
|
104
|
-
padding: 10px 14px;
|
|
105
|
-
border: 1px solid #ddd;
|
|
106
|
-
border-radius: 8px;
|
|
107
|
-
font-size: 15px;
|
|
108
|
-
outline: none;
|
|
109
|
-
transition: border-color 0.2s;
|
|
110
|
-
}
|
|
111
|
-
input:focus, textarea:focus { border-color: #61dafb; }
|
|
112
|
-
textarea { resize: vertical; min-height: 100px; }
|
|
113
|
-
|
|
114
|
-
/* ---- 404 ---- */
|
|
115
|
-
.not-found { text-align: center; padding: 60px 0; }
|
|
116
|
-
.not-found h1 { font-size: 80px; color: #61dafb; }
|
|
117
|
-
</style>
|
|
118
13
|
</head>
|
|
119
14
|
<body>
|
|
120
15
|
|
|
@@ -146,8 +41,7 @@
|
|
|
146
41
|
<script type="text/babel" src="pages/ApiDemo.jsx"></script>
|
|
147
42
|
<script type="text/babel" src="pages/Contact.jsx"></script>
|
|
148
43
|
<script type="text/babel" src="pages/Home.jsx"></script>
|
|
149
|
-
<script type="text/babel" src="pages/
|
|
150
|
-
<script type="text/babel" src="pages/Test.jsx"></script>
|
|
44
|
+
<script type="text/babel" src="pages/test.jsx"></script>
|
|
151
45
|
|
|
152
46
|
<!-- Start the app -->
|
|
153
47
|
<script type="text/babel">
|