create-aziz-app 3.1.2 → 3.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/README.md +658 -207
  2. package/bin/create-aziz-app.js +302 -302
  3. package/package.json +1 -1
  4. package/template/README.md +402 -402
  5. package/template/_framework/api.js +219 -219
  6. package/template/_framework/boot.js +33 -33
  7. package/template/_framework/hooks.js +367 -291
  8. package/template/_framework/next-response.js +128 -128
  9. package/template/_framework/route-match.js +145 -145
  10. package/template/_framework/router.js +465 -259
  11. package/template/_framework/runtime.js +264 -264
  12. package/template/app/layout.js +18 -18
  13. package/template/app/page.js +33 -33
  14. package/template/docs/01-getting-started.md +151 -151
  15. package/template/docs/02-project-structure.md +109 -109
  16. package/template/docs/03-pages-and-layouts.md +140 -140
  17. package/template/docs/04-routing.md +120 -120
  18. package/template/docs/05-hooks.md +169 -169
  19. package/template/docs/06-api-routes.md +210 -210
  20. package/template/docs/07-api-client.md +151 -151
  21. package/template/docs/08-styling.md +94 -94
  22. package/template/docs/09-imports-and-modules.md +97 -97
  23. package/template/docs/10-database-and-models.md +154 -154
  24. package/template/docs/11-authentication.md +171 -171
  25. package/template/docs/12-production-and-deployment.md +121 -121
  26. package/template/docs/13-internals.md +179 -179
  27. package/template/docs/README.md +67 -67
  28. package/template/index.html +20 -20
  29. package/template/package.json +16 -16
  30. package/template/scripts/dev-server.js +493 -381
  31. package/template/scripts/lib/api-router.js +525 -525
  32. package/template/scripts/lib/js-transform.js +213 -195
  33. package/template/scripts/lib/module-resolver.js +132 -132
@@ -1,302 +1,302 @@
1
- #!/usr/bin/env node
2
-
3
- // ============================================================
4
- // create-aziz-app — project scaffolder for Aziz.js
5
- //
6
- // Usage:
7
- // npx create-aziz-app my-app
8
- // npx create-aziz-app my-app --css tailwind --no-docs
9
- // npx create-aziz-app my-app -y --port 4000
10
- //
11
- // Options:
12
- // -y, --yes Accept all defaults (no prompts)
13
- // --port <n> Dev-server port (default 3000)
14
- // --css <name> none | bootstrap | tailwind
15
- // --no-docs Skip the docs/ folder
16
- // -h, --help Show help
17
- // ============================================================
18
-
19
- const fs = require('fs');
20
- const path = require('path');
21
- const readline = require('readline');
22
-
23
- const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
24
-
25
- function question(query) {
26
- return new Promise(resolve => rl.question(query, resolve));
27
- }
28
-
29
- function parseArgs(argv) {
30
- const opts = {
31
- projectName: null,
32
- yes: false,
33
- port: null,
34
- css: null,
35
- docs: null,
36
- help: false,
37
- };
38
-
39
- for (let i = 0; i < argv.length; i++) {
40
- const arg = argv[i];
41
- switch (arg) {
42
- case '-h':
43
- case '--help': opts.help = true; break;
44
- case '-y':
45
- case '--yes': opts.yes = true; break;
46
- case '--port': opts.port = argv[++i]; break;
47
- case '--css': opts.css = argv[++i]; break;
48
- case '--no-docs': opts.docs = false; break;
49
- default:
50
- if (!arg.startsWith('-') && !opts.projectName) opts.projectName = arg;
51
- }
52
- }
53
- return opts;
54
- }
55
-
56
- function printHelp() {
57
- console.log(`
58
- ⚡ create-aziz-app — scaffold a new Aziz.js project
59
-
60
- Usage:
61
- npx create-aziz-app <project-name> [options]
62
-
63
- Options:
64
- -y, --yes Accept all defaults (skip prompts)
65
- --port <n> Dev-server port (default 3000)
66
- --css <name> none | bootstrap | tailwind
67
- --no-docs Skip the docs/ folder
68
- -h, --help Show this help
69
-
70
- Examples:
71
- npx create-aziz-app blog
72
- npx create-aziz-app shop --css tailwind --port 4000
73
- `);
74
- }
75
-
76
- // Files/folders never copied into a new project.
77
- function shouldSkip(relPath) {
78
- if (relPath === 'node_modules' || relPath.startsWith('node_modules' + path.sep)) return true;
79
- if (relPath === '.DS_Store' || relPath.endsWith('.log')) return true;
80
- return false;
81
- }
82
-
83
- function copyDir(src, dest, features) {
84
- fs.mkdirSync(dest, { recursive: true });
85
-
86
- for (const entry of fs.readdirSync(src)) {
87
- const srcPath = path.join(src, entry);
88
- const destPath = path.join(dest, entry);
89
-
90
- if (shouldSkip(entry)) continue;
91
-
92
- const isDir = fs.statSync(srcPath).isDirectory();
93
-
94
- // Docs are optional
95
- if (!features.docs && entry === 'docs' && isDir) continue;
96
-
97
- if (isDir) {
98
- copyDir(srcPath, destPath, features);
99
- } else {
100
- fs.copyFileSync(srcPath, destPath);
101
- }
102
- }
103
- }
104
-
105
- function updatePackageJson(targetDir, projectName) {
106
- const pkgPath = path.join(targetDir, 'package.json');
107
- if (!fs.existsSync(pkgPath)) return;
108
- const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
109
- pkg.name = projectName;
110
- fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n');
111
- }
112
-
113
- function updateDevServerPort(targetDir, port) {
114
- const devServerPath = path.join(targetDir, 'scripts', 'dev-server.js');
115
- if (!fs.existsSync(devServerPath)) return;
116
- let content = fs.readFileSync(devServerPath, 'utf8');
117
- content = content.replace(
118
- /const PORT = parseInt\(process\.env\.PORT, 10\) \|\| 3000;/,
119
- `const PORT = parseInt(process.env.PORT, 10) || ${port};`
120
- );
121
- fs.writeFileSync(devServerPath, content);
122
- }
123
-
124
- function updateTitle(targetDir, projectName) {
125
- const htmlPath = path.join(targetDir, 'index.html');
126
- if (!fs.existsSync(htmlPath)) return;
127
- let html = fs.readFileSync(htmlPath, 'utf8');
128
- const pretty = projectName.replace(/[-_]+/g, ' ').replace(/\b\w/g, c => c.toUpperCase());
129
- html = html.replace(/<title>.*?<\/title>/, `<title>${pretty}</title>`);
130
- fs.writeFileSync(htmlPath, html);
131
- }
132
-
133
- function injectHead(html, snippet) {
134
- return html.replace('</head>', `${snippet}\n</head>`);
135
- }
136
-
137
- function injectBody(html, snippet) {
138
- return html.replace('</body>', `${snippet}\n</body>`);
139
- }
140
-
141
- function setupCSSFramework(targetDir, framework) {
142
- const htmlPath = path.join(targetDir, 'index.html');
143
- if (!fs.existsSync(htmlPath)) return;
144
-
145
- let html = fs.readFileSync(htmlPath, 'utf8');
146
-
147
- if (framework === 'bootstrap') {
148
- html = injectHead(html, ` <!-- Bootstrap 5 -->
149
- <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
150
- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.css">`);
151
- html = injectBody(html, ` <!-- Bootstrap 5 JS -->
152
- <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>`);
153
- } else if (framework === 'tailwind') {
154
- html = injectHead(html, ` <!-- Tailwind CSS -->
155
- <script src="https://cdn.tailwindcss.com"></script>
156
- <script>
157
- tailwind.config = {
158
- theme: {
159
- extend: {
160
- colors: { primary: '#61dafb', dark: '#282c34' }
161
- }
162
- }
163
- }
164
- </script>`);
165
- }
166
- // 'none' → keep globals.css only
167
-
168
- fs.writeFileSync(htmlPath, html);
169
- }
170
-
171
- async function main() {
172
- const opts = parseArgs(process.argv.slice(2));
173
-
174
- if (opts.help) {
175
- printHelp();
176
- rl.close();
177
- return;
178
- }
179
-
180
- console.log(`\n⚡ Welcome to Aziz.js!\n`);
181
- console.log(`🎨 A lightweight Next.js clone — file-based routing, React hooks, live reload\n`);
182
-
183
- let projectName = opts.projectName;
184
- if (!projectName) {
185
- projectName = (await question('📁 Project name (my-aziz-js-app): ')).trim() || 'my-aziz-js-app';
186
- }
187
-
188
- if (!/^[a-z0-9-_]+$/i.test(projectName)) {
189
- console.error(`❌ Invalid project name. Use only letters, numbers, hyphens, and underscores.`);
190
- rl.close();
191
- process.exit(1);
192
- }
193
-
194
- const targetDir = path.join(process.cwd(), projectName);
195
-
196
- if (fs.existsSync(targetDir)) {
197
- let overwrite = 'y';
198
- if (!opts.yes) {
199
- overwrite = await question(`⚠️ Folder "${projectName}" already exists. Overwrite? (y/N): `);
200
- }
201
- if (overwrite.toLowerCase() !== 'y' && overwrite.toLowerCase() !== 'yes') {
202
- console.log('❌ Cancelled.');
203
- rl.close();
204
- process.exit(0);
205
- }
206
- fs.rmSync(targetDir, { recursive: true, force: true });
207
- }
208
-
209
- // ── Port
210
- let port = opts.port;
211
- if (!port && !opts.yes) port = (await question('🌐 Dev server port (3000): ')).trim();
212
- port = port || '3000';
213
- if (!/^\d+$/.test(port)) {
214
- console.log('⚠️ Invalid port, using default 3000');
215
- port = '3000';
216
- }
217
-
218
- // ── Features
219
- let docs = opts.docs;
220
-
221
- if (!opts.yes && docs === null) {
222
- const a = await question(' Include documentation? (Y/n): ');
223
- docs = !['n', 'no'].includes(a.trim().toLowerCase());
224
- }
225
- if (docs === null) docs = true;
226
-
227
- // ── CSS framework
228
- let css = opts.css;
229
- if (!css && !opts.yes) {
230
- console.log('\n🎨 CSS Framework:');
231
- console.log(' 1. None (custom CSS)');
232
- console.log(' 2. Bootstrap 5');
233
- console.log(' 3. Tailwind CSS');
234
- const choice = (await question(' Choose (1/2/3): ')).trim();
235
- css = choice === '2' ? 'bootstrap' : choice === '3' ? 'tailwind' : 'none';
236
- }
237
- if (!['none', 'bootstrap', 'tailwind'].includes(css)) css = 'none';
238
-
239
- const features = { docs, css };
240
-
241
- console.log(`\n⚡ Creating "${projectName}"...\n`);
242
-
243
- const templateDir = path.join(__dirname, '..', 'template');
244
- if (!fs.existsSync(templateDir)) {
245
- console.error('❌ Template folder not found. Reinstall create-aziz-app.');
246
- rl.close();
247
- process.exit(1);
248
- }
249
-
250
- // 1. Copy the template (excluding node_modules)
251
- copyDir(templateDir, targetDir, features);
252
-
253
- // 2. Personalize
254
- updatePackageJson(targetDir, projectName);
255
- updateDevServerPort(targetDir, port);
256
- updateTitle(targetDir, projectName);
257
- setupCSSFramework(targetDir, features.css);
258
-
259
- // 3. .gitignore
260
- fs.writeFileSync(path.join(targetDir, '.gitignore'), [
261
- 'node_modules/',
262
- '.DS_Store',
263
- '*.log',
264
- '',
265
- ].join('\n'));
266
-
267
- console.log(`✅ Done! Your project is ready.\n`);
268
- console.log(`📁 Created project: ${projectName}`);
269
- console.log(`🎨 CSS framework: ${features.css}`);
270
- console.log(`\n👉 Get started:\n`);
271
- console.log(` cd ${projectName}`);
272
- console.log(` npm install`);
273
- console.log(` npm run dev\n`);
274
- console.log(`🌐 Dev server: http://localhost:${port}/\n`);
275
- console.log(`📂 Project structure:\n`);
276
- console.log(` index.html ← HTML entry point`);
277
- console.log(` app/ ← pages + layouts (file-based routing)`);
278
- console.log(` layout.js ← root layout`);
279
- console.log(` page.js ← route: /`);
280
- console.log(` styles/ ← global CSS`);
281
- console.log(` _framework/ ← runtime, hooks, router`);
282
- console.log(` scripts/ ← dev server + live reload`);
283
- if (features.docs) console.log(` docs/ ← full documentation`);
284
- console.log(`\n✨ Highlights:\n`);
285
- console.log(` • File-based routing app/about/page.js → /about`);
286
- console.log(` • Dynamic routes app/blog/[slug]/page.js → /blog/:slug`);
287
- console.log(` • Nested layouts app/**/layout.js`);
288
- console.log(` • React hooks useState, useEffect, useMemo, context…`);
289
- console.log(` • Live reload instant browser refresh on save`);
290
- console.log(`\n💡 Tips:\n`);
291
- console.log(` • Create app/MyPage/page.js → route /MyPage`);
292
- if (features.docs) console.log(` • Read docs/README.md for the full guide`);
293
- console.log(`\n🚀 Happy building!\n`);
294
-
295
- rl.close();
296
- }
297
-
298
- main().catch(err => {
299
- console.error('❌ Error:', err);
300
- rl.close();
301
- process.exit(1);
302
- });
1
+ #!/usr/bin/env node
2
+
3
+ // ============================================================
4
+ // create-aziz-app — project scaffolder for Aziz.js
5
+ //
6
+ // Usage:
7
+ // npx create-aziz-app my-app
8
+ // npx create-aziz-app my-app --css tailwind --no-docs
9
+ // npx create-aziz-app my-app -y --port 4000
10
+ //
11
+ // Options:
12
+ // -y, --yes Accept all defaults (no prompts)
13
+ // --port <n> Dev-server port (default 3000)
14
+ // --css <name> none | bootstrap | tailwind
15
+ // --no-docs Skip the docs/ folder
16
+ // -h, --help Show help
17
+ // ============================================================
18
+
19
+ const fs = require('fs');
20
+ const path = require('path');
21
+ const readline = require('readline');
22
+
23
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
24
+
25
+ function question(query) {
26
+ return new Promise(resolve => rl.question(query, resolve));
27
+ }
28
+
29
+ function parseArgs(argv) {
30
+ const opts = {
31
+ projectName: null,
32
+ yes: false,
33
+ port: null,
34
+ css: null,
35
+ docs: null,
36
+ help: false,
37
+ };
38
+
39
+ for (let i = 0; i < argv.length; i++) {
40
+ const arg = argv[i];
41
+ switch (arg) {
42
+ case '-h':
43
+ case '--help': opts.help = true; break;
44
+ case '-y':
45
+ case '--yes': opts.yes = true; break;
46
+ case '--port': opts.port = argv[++i]; break;
47
+ case '--css': opts.css = argv[++i]; break;
48
+ case '--no-docs': opts.docs = false; break;
49
+ default:
50
+ if (!arg.startsWith('-') && !opts.projectName) opts.projectName = arg;
51
+ }
52
+ }
53
+ return opts;
54
+ }
55
+
56
+ function printHelp() {
57
+ console.log(`
58
+ ⚡ create-aziz-app — scaffold a new Aziz.js project
59
+
60
+ Usage:
61
+ npx create-aziz-app <project-name> [options]
62
+
63
+ Options:
64
+ -y, --yes Accept all defaults (skip prompts)
65
+ --port <n> Dev-server port (default 3000)
66
+ --css <name> none | bootstrap | tailwind
67
+ --no-docs Skip the docs/ folder
68
+ -h, --help Show this help
69
+
70
+ Examples:
71
+ npx create-aziz-app blog
72
+ npx create-aziz-app shop --css tailwind --port 4000
73
+ `);
74
+ }
75
+
76
+ // Files/folders never copied into a new project.
77
+ function shouldSkip(relPath) {
78
+ if (relPath === 'node_modules' || relPath.startsWith('node_modules' + path.sep)) return true;
79
+ if (relPath === '.DS_Store' || relPath.endsWith('.log')) return true;
80
+ return false;
81
+ }
82
+
83
+ function copyDir(src, dest, features) {
84
+ fs.mkdirSync(dest, { recursive: true });
85
+
86
+ for (const entry of fs.readdirSync(src)) {
87
+ const srcPath = path.join(src, entry);
88
+ const destPath = path.join(dest, entry);
89
+
90
+ if (shouldSkip(entry)) continue;
91
+
92
+ const isDir = fs.statSync(srcPath).isDirectory();
93
+
94
+ // Docs are optional
95
+ if (!features.docs && entry === 'docs' && isDir) continue;
96
+
97
+ if (isDir) {
98
+ copyDir(srcPath, destPath, features);
99
+ } else {
100
+ fs.copyFileSync(srcPath, destPath);
101
+ }
102
+ }
103
+ }
104
+
105
+ function updatePackageJson(targetDir, projectName) {
106
+ const pkgPath = path.join(targetDir, 'package.json');
107
+ if (!fs.existsSync(pkgPath)) return;
108
+ const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
109
+ pkg.name = projectName;
110
+ fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\n');
111
+ }
112
+
113
+ function updateDevServerPort(targetDir, port) {
114
+ const devServerPath = path.join(targetDir, 'scripts', 'dev-server.js');
115
+ if (!fs.existsSync(devServerPath)) return;
116
+ let content = fs.readFileSync(devServerPath, 'utf8');
117
+ content = content.replace(
118
+ /const PORT = parseInt\(process\.env\.PORT, 10\) \|\| 3000;/,
119
+ `const PORT = parseInt(process.env.PORT, 10) || ${port};`
120
+ );
121
+ fs.writeFileSync(devServerPath, content);
122
+ }
123
+
124
+ function updateTitle(targetDir, projectName) {
125
+ const htmlPath = path.join(targetDir, 'index.html');
126
+ if (!fs.existsSync(htmlPath)) return;
127
+ let html = fs.readFileSync(htmlPath, 'utf8');
128
+ const pretty = projectName.replace(/[-_]+/g, ' ').replace(/\b\w/g, c => c.toUpperCase());
129
+ html = html.replace(/<title>.*?<\/title>/, `<title>${pretty}</title>`);
130
+ fs.writeFileSync(htmlPath, html);
131
+ }
132
+
133
+ function injectHead(html, snippet) {
134
+ return html.replace('</head>', `${snippet}\n</head>`);
135
+ }
136
+
137
+ function injectBody(html, snippet) {
138
+ return html.replace('</body>', `${snippet}\n</body>`);
139
+ }
140
+
141
+ function setupCSSFramework(targetDir, framework) {
142
+ const htmlPath = path.join(targetDir, 'index.html');
143
+ if (!fs.existsSync(htmlPath)) return;
144
+
145
+ let html = fs.readFileSync(htmlPath, 'utf8');
146
+
147
+ if (framework === 'bootstrap') {
148
+ html = injectHead(html, ` <!-- Bootstrap 5 -->
149
+ <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
150
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.css">`);
151
+ html = injectBody(html, ` <!-- Bootstrap 5 JS -->
152
+ <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>`);
153
+ } else if (framework === 'tailwind') {
154
+ html = injectHead(html, ` <!-- Tailwind CSS -->
155
+ <script src="https://cdn.tailwindcss.com"></script>
156
+ <script>
157
+ tailwind.config = {
158
+ theme: {
159
+ extend: {
160
+ colors: { primary: '#61dafb', dark: '#282c34' }
161
+ }
162
+ }
163
+ }
164
+ </script>`);
165
+ }
166
+ // 'none' → keep globals.css only
167
+
168
+ fs.writeFileSync(htmlPath, html);
169
+ }
170
+
171
+ async function main() {
172
+ const opts = parseArgs(process.argv.slice(2));
173
+
174
+ if (opts.help) {
175
+ printHelp();
176
+ rl.close();
177
+ return;
178
+ }
179
+
180
+ console.log(`\n⚡ Welcome to Aziz.js!\n`);
181
+ console.log(`🎨 A lightweight Next.js clone — file-based routing, React hooks, live reload\n`);
182
+
183
+ let projectName = opts.projectName;
184
+ if (!projectName) {
185
+ projectName = (await question('📁 Project name (my-aziz-js-app): ')).trim() || 'my-aziz-js-app';
186
+ }
187
+
188
+ if (!/^[a-z0-9-_]+$/i.test(projectName)) {
189
+ console.error(`❌ Invalid project name. Use only letters, numbers, hyphens, and underscores.`);
190
+ rl.close();
191
+ process.exit(1);
192
+ }
193
+
194
+ const targetDir = path.join(process.cwd(), projectName);
195
+
196
+ if (fs.existsSync(targetDir)) {
197
+ let overwrite = 'y';
198
+ if (!opts.yes) {
199
+ overwrite = await question(`⚠️ Folder "${projectName}" already exists. Overwrite? (y/N): `);
200
+ }
201
+ if (overwrite.toLowerCase() !== 'y' && overwrite.toLowerCase() !== 'yes') {
202
+ console.log('❌ Cancelled.');
203
+ rl.close();
204
+ process.exit(0);
205
+ }
206
+ fs.rmSync(targetDir, { recursive: true, force: true });
207
+ }
208
+
209
+ // ── Port
210
+ let port = opts.port;
211
+ if (!port && !opts.yes) port = (await question('🌐 Dev server port (3000): ')).trim();
212
+ port = port || '3000';
213
+ if (!/^\d+$/.test(port)) {
214
+ console.log('⚠️ Invalid port, using default 3000');
215
+ port = '3000';
216
+ }
217
+
218
+ // ── Features
219
+ let docs = opts.docs;
220
+
221
+ if (!opts.yes && docs === null) {
222
+ const a = await question(' Include documentation? (Y/n): ');
223
+ docs = !['n', 'no'].includes(a.trim().toLowerCase());
224
+ }
225
+ if (docs === null) docs = true;
226
+
227
+ // ── CSS framework
228
+ let css = opts.css;
229
+ if (!css && !opts.yes) {
230
+ console.log('\n🎨 CSS Framework:');
231
+ console.log(' 1. None (custom CSS)');
232
+ console.log(' 2. Bootstrap 5');
233
+ console.log(' 3. Tailwind CSS');
234
+ const choice = (await question(' Choose (1/2/3): ')).trim();
235
+ css = choice === '2' ? 'bootstrap' : choice === '3' ? 'tailwind' : 'none';
236
+ }
237
+ if (!['none', 'bootstrap', 'tailwind'].includes(css)) css = 'none';
238
+
239
+ const features = { docs, css };
240
+
241
+ console.log(`\n⚡ Creating "${projectName}"...\n`);
242
+
243
+ const templateDir = path.join(__dirname, '..', 'template');
244
+ if (!fs.existsSync(templateDir)) {
245
+ console.error('❌ Template folder not found. Reinstall create-aziz-app.');
246
+ rl.close();
247
+ process.exit(1);
248
+ }
249
+
250
+ // 1. Copy the template (excluding node_modules)
251
+ copyDir(templateDir, targetDir, features);
252
+
253
+ // 2. Personalize
254
+ updatePackageJson(targetDir, projectName);
255
+ updateDevServerPort(targetDir, port);
256
+ updateTitle(targetDir, projectName);
257
+ setupCSSFramework(targetDir, features.css);
258
+
259
+ // 3. .gitignore
260
+ fs.writeFileSync(path.join(targetDir, '.gitignore'), [
261
+ 'node_modules/',
262
+ '.DS_Store',
263
+ '*.log',
264
+ '',
265
+ ].join('\n'));
266
+
267
+ console.log(`✅ Done! Your project is ready.\n`);
268
+ console.log(`📁 Created project: ${projectName}`);
269
+ console.log(`🎨 CSS framework: ${features.css}`);
270
+ console.log(`\n👉 Get started:\n`);
271
+ console.log(` cd ${projectName}`);
272
+ console.log(` npm install`);
273
+ console.log(` npm run dev\n`);
274
+ console.log(`🌐 Dev server: http://localhost:${port}/\n`);
275
+ console.log(`📂 Project structure:\n`);
276
+ console.log(` index.html ← HTML entry point`);
277
+ console.log(` app/ ← pages + layouts (file-based routing)`);
278
+ console.log(` layout.js ← root layout`);
279
+ console.log(` page.js ← route: /`);
280
+ console.log(` styles/ ← global CSS`);
281
+ console.log(` _framework/ ← runtime, hooks, router`);
282
+ console.log(` scripts/ ← dev server + live reload`);
283
+ if (features.docs) console.log(` docs/ ← full documentation`);
284
+ console.log(`\n✨ Highlights:\n`);
285
+ console.log(` • File-based routing app/about/page.js → /about`);
286
+ console.log(` • Dynamic routes app/blog/[slug]/page.js → /blog/:slug`);
287
+ console.log(` • Nested layouts app/**/layout.js`);
288
+ console.log(` • React hooks useState, useEffect, useMemo, context…`);
289
+ console.log(` • Live reload instant browser refresh on save`);
290
+ console.log(`\n💡 Tips:\n`);
291
+ console.log(` • Create app/MyPage/page.js → route /MyPage`);
292
+ if (features.docs) console.log(` • Read docs/README.md for the full guide`);
293
+ console.log(`\n🚀 Happy building!\n`);
294
+
295
+ rl.close();
296
+ }
297
+
298
+ main().catch(err => {
299
+ console.error('❌ Error:', err);
300
+ rl.close();
301
+ process.exit(1);
302
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-aziz-app",
3
- "version": "3.1.2",
3
+ "version": "3.1.3",
4
4
  "description": "Create Aziz.js apps — lightweight Next.js clone with file-based routing, React hooks, and API routes",
5
5
  "keywords": [
6
6
  "aziz.js",