create-aziz-app 2.0.7 → 2.0.9

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-aziz-app",
3
- "version": "2.0.7",
3
+ "version": "2.0.9",
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
6
  "react",
@@ -72,8 +72,7 @@ Just create files in the appropriate folders - they're automatically imported!
72
72
  // pages/Profile.jsx
73
73
  /** @jsx h */
74
74
 
75
- registerPage("profile", ProfilePage);
76
-
75
+ // Auto-registers as "#/profile" - no registerPage() needed!
77
76
  function ProfilePage() {
78
77
  const [name, setName] = useState('');
79
78
 
@@ -93,8 +92,19 @@ function ProfilePage() {
93
92
 
94
93
  **Navigate to:** `http://localhost:3000/#/profile`
95
94
 
95
+ ✨ **That's it!** No `registerPage()` call needed. Just name your function `YourNamePage()` and it auto-registers!
96
+
96
97
  ## ✨ Features
97
98
 
99
+ ### Auto-Registration ⚡
100
+ ```javascript
101
+ // Just name your function with "Page" suffix
102
+ function AboutPage() {
103
+ return <div><h1>About</h1></div>;
104
+ }
105
+ // Automatically becomes route "#/about"
106
+ ```
107
+
98
108
  ### State Management
99
109
  ```javascript
100
110
  const [count, setCount] = useState(0);
@@ -103,8 +113,11 @@ const [name, setName] = useState('');
103
113
 
104
114
  ### Routing
105
115
  ```javascript
106
- // Register a page
107
- registerPage("about", AboutPage);
116
+ // Auto-registers based on function name
117
+ function HomePage() { } // → #/home
118
+
119
+ // Or manually register for custom names
120
+ registerPage("user-profile", UserProfilePage);
108
121
 
109
122
  // Navigate
110
123
  navigate("about");
@@ -138,8 +151,11 @@ The CLI will automatically set up your chosen framework!
138
151
  ## 📚 Documentation
139
152
 
140
153
  - **[Getting Started](docs/GETTING-STARTED.md)** - Complete setup guide
154
+ - **[Auto-Registration](docs/AUTO-REGISTRATION.md)** - How pages auto-register
141
155
  - **[API Guide](docs/API-GUIDE.md)** - How to create API routes
142
156
  - **[Auto-Import](docs/AUTO-IMPORT.md)** - Auto-import system details
157
+ - **[Dev Server](docs/DEV-SERVER.md)** - Live reload and development
158
+ - **[Troubleshooting](docs/TROUBLESHOOTING.md)** - Fix common issues
143
159
  - **[Quick Start](docs/QUICK-START.md)** - Quick examples
144
160
 
145
161
  ## 🛠️ Commands
@@ -153,8 +169,9 @@ npm run build # Generate imports manually
153
169
 
154
170
  ### Pages
155
171
  - Files in `pages/` become routes
156
- - Use `registerPage("route", Component)`
157
- - Access via `#/route`
172
+ - Name functions with "Page" suffix (e.g., `AboutPage`)
173
+ - Auto-registers as route (e.g., `#/about`)
174
+ - Optional: Use `registerPage("custom-name", Component)` for custom routes
158
175
 
159
176
  ### Components
160
177
  - Reusable UI components
package/template/app.html CHANGED
@@ -3,6 +3,9 @@
3
3
  <head>
4
4
  <meta charset="UTF-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
7
+ <meta http-equiv="Pragma" content="no-cache">
8
+ <meta http-equiv="Expires" content="0">
6
9
  <title>My Aziz App</title>
7
10
 
8
11
  <!-- Global Styles -->
@@ -22,30 +25,31 @@
22
25
  <!-- Footer is always visible -->
23
26
  <div id="footer"></div>
24
27
 
25
- <!-- Load core modules -->
26
- <script type="text/babel" src="modules/router.js"></script>
27
- <script type="text/babel" src="modules/state.js"></script>
28
- <script type="text/babel" src="modules/api.js"></script>
29
-
30
- <!-- Load API routes -->
31
- <script type="text/babel" src="api/hello.js"></script>
32
- <script type="text/babel" src="api/users.js"></script>
33
-
34
- <!-- Load shared components -->
35
- <script type="text/babel" src="components/Counter.jsx"></script>
36
- <script type="text/babel" src="components/Footer.jsx"></script>
37
- <script type="text/babel" src="components/Navbar.jsx"></script>
38
-
39
- <!-- Load pages -->
40
- <script type="text/babel" src="pages/About.jsx"></script>
41
- <script type="text/babel" src="pages/ApiDemo.jsx"></script>
42
- <script type="text/babel" src="pages/Contact.jsx"></script>
43
- <script type="text/babel" src="pages/Home.jsx"></script>
44
- <script type="text/babel" src="pages/test.jsx"></script>
45
-
46
- <!-- Start the app -->
47
- <script type="text/babel">
48
- startApp();
28
+ <!-- Load core modules -->
29
+ <script type="text/babel" src="modules/router.js"></script>
30
+ <script type="text/babel" src="modules/state.js"></script>
31
+ <script type="text/babel" src="modules/api.js"></script>
32
+
33
+ <!-- Load API routes -->
34
+ <script type="text/babel" src="api/hello.js"></script>
35
+ <script type="text/babel" src="api/users.js"></script>
36
+
37
+ <!-- Load shared components -->
38
+ <script type="text/babel" src="components/Counter.jsx"></script>
39
+ <script type="text/babel" src="components/Footer.jsx"></script>
40
+ <script type="text/babel" src="components/Navbar.jsx"></script>
41
+
42
+ <!-- Load pages -->
43
+ <script type="text/babel" src="pages/About.jsx"></script>
44
+ <script type="text/babel" src="pages/ApiDemo.jsx"></script>
45
+ <script type="text/babel" src="pages/Contact.jsx"></script>
46
+ <script type="text/babel" src="pages/Example.jsx"></script>
47
+ <script type="text/babel" src="pages/Home.jsx"></script>
48
+ <script type="text/babel" src="pages/test.jsx"></script>
49
+
50
+ <!-- Start the app -->
51
+ <script type="text/babel">
52
+ startApp();
49
53
  </script>
50
54
 
51
55
  </body>
@@ -0,0 +1,248 @@
1
+ # Auto-Registration Guide
2
+
3
+ ## Overview
4
+
5
+ Pages automatically register themselves based on their function name. No need to call `registerPage()` manually!
6
+
7
+ ## How It Works
8
+
9
+ ### ✨ Automatic Registration
10
+
11
+ Just name your page function with "Page" at the end:
12
+
13
+ ```jsx
14
+ /** @jsx h */
15
+
16
+ // That's it! Automatically becomes route "#/example"
17
+ function ExamplePage() {
18
+ return (
19
+ <div>
20
+ <h1>Example Page</h1>
21
+ <p>This page auto-registered!</p>
22
+ </div>
23
+ );
24
+ }
25
+ ```
26
+
27
+ ### Function Name → Route Mapping
28
+
29
+ The system converts your function name to a route:
30
+
31
+ | Function Name | Auto Route | URL |
32
+ |--------------|------------|-----|
33
+ | `HomePage()` | `home` | `#/home` |
34
+ | `AboutPage()` | `about` | `#/about` |
35
+ | `ContactPage()` | `contact` | `#/contact` |
36
+ | `UserProfilePage()` | `userprofile` | `#/userprofile` |
37
+ | `MyAwesomePage()` | `myawesome` | `#/myawesome` |
38
+
39
+ **Rule:** Remove "Page" suffix and convert to lowercase.
40
+
41
+ ## Manual Registration (Optional)
42
+
43
+ You can still manually register for custom route names:
44
+
45
+ ```jsx
46
+ /** @jsx h */
47
+
48
+ // Custom route name with dashes or different naming
49
+ registerPage("user-profile", UserProfilePage);
50
+
51
+ function UserProfilePage() {
52
+ return <div><h1>User Profile</h1></div>;
53
+ }
54
+ ```
55
+
56
+ ### When to Use Manual Registration
57
+
58
+ - **Custom route names** with dashes: `"api-demo"`, `"user-settings"`
59
+ - **Multiple routes** pointing to same component
60
+ - **Override auto-registration** with different name
61
+
62
+ ## Examples
63
+
64
+ ### Example 1: Simple Auto Page
65
+
66
+ ```jsx
67
+ /** @jsx h */
68
+
69
+ function ProductsPage() {
70
+ return (
71
+ <div>
72
+ <h1>Products</h1>
73
+ <p>Browse our products</p>
74
+ </div>
75
+ );
76
+ }
77
+ ```
78
+
79
+ Access at: `#/products`
80
+
81
+ ### Example 2: With State
82
+
83
+ ```jsx
84
+ /** @jsx h */
85
+
86
+ function DashboardPage() {
87
+ const [count, setCount] = useState(0);
88
+
89
+ return (
90
+ <div>
91
+ <h1>Dashboard</h1>
92
+ <p>Count: {count}</p>
93
+ <button onClick={() => setCount(count + 1)}>
94
+ Increment
95
+ </button>
96
+ </div>
97
+ );
98
+ }
99
+ ```
100
+
101
+ Access at: `#/dashboard`
102
+
103
+ ### Example 3: Manual Registration
104
+
105
+ ```jsx
106
+ /** @jsx h */
107
+
108
+ // Want route "#/user-settings" instead of "#/usersettings"
109
+ registerPage("user-settings", UserSettingsPage);
110
+
111
+ function UserSettingsPage() {
112
+ return (
113
+ <div>
114
+ <h1>User Settings</h1>
115
+ </div>
116
+ );
117
+ }
118
+ ```
119
+
120
+ Access at: `#/user-settings`
121
+
122
+ ## Creating a New Page
123
+
124
+ ### Step 1: Create the file
125
+
126
+ Create `pages/MyNewPage.jsx`:
127
+
128
+ ```jsx
129
+ /** @jsx h */
130
+
131
+ function MyNewPage() {
132
+ return (
133
+ <div>
134
+ <h1>My New Page</h1>
135
+ <div class="card">
136
+ <p>This is my new page!</p>
137
+ </div>
138
+ </div>
139
+ );
140
+ }
141
+ ```
142
+
143
+ ### Step 2: That's it!
144
+
145
+ The dev server will:
146
+ 1. Detect the new file
147
+ 2. Auto-generate the import in `app.html`
148
+ 3. Auto-register the route as `#/mynew`
149
+ 4. Reload the browser
150
+
151
+ Navigate to `#/mynew` and your page appears!
152
+
153
+ ## Debugging
154
+
155
+ ### Check Auto-Registration
156
+
157
+ Open browser console when the app starts. You'll see:
158
+
159
+ ```
160
+ 📄 Auto-registered: home → HomePage()
161
+ 📄 Auto-registered: about → AboutPage()
162
+ 📄 Auto-registered: contact → ContactPage()
163
+ 📄 Auto-registered: mynew → MyNewPage()
164
+ ```
165
+
166
+ ### Page Not Found?
167
+
168
+ 1. **Check function name** - Must end with "Page"
169
+ 2. **Check file is loaded** - Look in `app.html` for the script tag
170
+ 3. **Check console** - Look for auto-registration message
171
+ 4. **Try manual registration** - Use `registerPage("route", ComponentPage)`
172
+
173
+ ## Best Practices
174
+
175
+ ### ✅ Do This
176
+
177
+ ```jsx
178
+ // Clear, descriptive names
179
+ function HomePage() { }
180
+ function AboutPage() { }
181
+ function ContactPage() { }
182
+ function UserProfilePage() { }
183
+ ```
184
+
185
+ ### ❌ Avoid This
186
+
187
+ ```jsx
188
+ // Won't auto-register (missing "Page" suffix)
189
+ function Home() { }
190
+ function About() { }
191
+
192
+ // Will create weird routes
193
+ function Page() { } // route: "" (empty)
194
+ function MyPage() { } // route: "my" (too generic)
195
+ ```
196
+
197
+ ## Migration Guide
198
+
199
+ ### Old Way (Still Works)
200
+
201
+ ```jsx
202
+ /** @jsx h */
203
+
204
+ registerPage("about", AboutPage);
205
+
206
+ function AboutPage() {
207
+ return <div><h1>About</h1></div>;
208
+ }
209
+ ```
210
+
211
+ ### New Way (Simpler)
212
+
213
+ ```jsx
214
+ /** @jsx h */
215
+
216
+ function AboutPage() {
217
+ return <div><h1>About</h1></div>;
218
+ }
219
+ ```
220
+
221
+ Both work! The new way is just less code.
222
+
223
+ ## Advanced: Multiple Routes
224
+
225
+ Point multiple routes to the same component:
226
+
227
+ ```jsx
228
+ /** @jsx h */
229
+
230
+ // Auto-registers as "dashboard"
231
+ function DashboardPage() {
232
+ return <div><h1>Dashboard</h1></div>;
233
+ }
234
+
235
+ // Also register as "home" and "index"
236
+ registerPage("home", DashboardPage);
237
+ registerPage("index", DashboardPage);
238
+ ```
239
+
240
+ Now `#/dashboard`, `#/home`, and `#/index` all show the same page!
241
+
242
+ ## Summary
243
+
244
+ - **Function name ends with "Page"** → Auto-registers
245
+ - **Route name** = function name without "Page", lowercase
246
+ - **Manual registration** still available for custom names
247
+ - **Dev server** handles everything automatically
248
+ - **Zero configuration** needed for basic pages
@@ -0,0 +1,98 @@
1
+ # Dev Server Guide
2
+
3
+ ## Overview
4
+
5
+ The dev server provides a smooth development experience with live reload, automatic import generation, and file watching.
6
+
7
+ ## Features
8
+
9
+ ### 🔄 Live Reload
10
+ - **Automatic browser refresh** when you save files
11
+ - **Visual indicator** in bottom-right corner shows connection status
12
+ - **Smart caching** - forces cache clear on reload to always show latest changes
13
+ - **CSS hot reload** - instant updates without regenerating imports
14
+
15
+ ### 👀 File Watching
16
+ The dev server watches these directories:
17
+ - `api/` - API route files
18
+ - `components/` - React-like components
19
+ - `pages/` - Page components
20
+ - `modules/` - Core system modules
21
+ - `styles/` - CSS files
22
+
23
+ ### 🚀 Auto Import Generation
24
+ - Automatically generates script tags in `app.html`
25
+ - Runs on startup and whenever JS/JSX files change
26
+ - No need to manually add imports
27
+
28
+ ### 🎯 Smart Port Selection
29
+ - Defaults to port 3000
30
+ - Automatically finds next available port if 3000 is busy
31
+ - Shows the actual URL in console
32
+
33
+ ## Usage
34
+
35
+ ```bash
36
+ npm run dev
37
+ ```
38
+
39
+ Then open the URL shown in console (usually `http://localhost:3000/`)
40
+
41
+ ## Visual Indicators
42
+
43
+ The live reload indicator in the bottom-right corner shows:
44
+ - 🔌 **Connecting...** - Initial connection
45
+ - ✅ **Live Reload Active** - Connected and watching (fades after 2s)
46
+ - 🔄 **Reloading...** - Changes detected, refreshing page
47
+ - ⚠️ **Reconnecting...** - Connection lost, attempting to reconnect
48
+
49
+ Hover over the indicator to make it fully visible.
50
+
51
+ ## How It Works
52
+
53
+ 1. **Server starts** and generates initial imports
54
+ 2. **Browser connects** via Server-Sent Events (SSE)
55
+ 3. **File watcher** detects changes in watched directories
56
+ 4. **Debouncing** prevents multiple rapid reloads (300ms for CSS, 500ms for JS)
57
+ 5. **Import regeneration** (for JS/JSX changes only)
58
+ 6. **Browser notification** via SSE
59
+ 7. **Page reload** with cache busting
60
+
61
+ ## Cache Control
62
+
63
+ The dev server sends these headers to prevent caching:
64
+ ```
65
+ Cache-Control: no-cache, no-store, must-revalidate
66
+ Pragma: no-cache
67
+ Expires: 0
68
+ ```
69
+
70
+ This ensures you always see the latest changes without needing Ctrl+Shift+R.
71
+
72
+ ## Troubleshooting
73
+
74
+ ### Changes not showing?
75
+ 1. Check the visual indicator - is it green?
76
+ 2. Open browser console - look for "✅ Live reload connected"
77
+ 3. Check terminal - does it show "🔄 Notifying X browser(s) to reload..."?
78
+ 4. Try hard refresh once: Ctrl+Shift+R (Windows) or Cmd+Shift+R (Mac)
79
+
80
+ ### Port already in use?
81
+ The server will automatically try the next port (3001, 3002, etc.)
82
+
83
+ ### Live reload disconnected?
84
+ The page will automatically try to reconnect after 2 seconds.
85
+
86
+ ## Performance
87
+
88
+ - **Debouncing** prevents reload spam when saving multiple files
89
+ - **CSS-only changes** skip import regeneration for faster updates
90
+ - **SSE connection** is lightweight and efficient
91
+ - **Multiple browsers** can connect simultaneously
92
+
93
+ ## Development Tips
94
+
95
+ 1. Keep the terminal visible to see file change notifications
96
+ 2. The visual indicator helps confirm live reload is working
97
+ 3. CSS changes are faster than JS changes (no import regeneration)
98
+ 4. Multiple browser tabs will all reload simultaneously
@@ -0,0 +1,282 @@
1
+ # Troubleshooting Guide
2
+
3
+ ## Live Reload Issues
4
+
5
+ ### Indicator Stuck on "Connecting..."
6
+
7
+ **Symptoms:**
8
+ - Green indicator shows "🔌 Connecting..." and never changes
9
+ - Changes don't show without hard refresh (Ctrl+Shift+R)
10
+
11
+ **Causes:**
12
+ - Browser cached old version of `app.html` without live reload script
13
+ - SSE connection blocked by browser extension or firewall
14
+
15
+ **Solutions:**
16
+
17
+ 1. **Hard refresh once** to clear cache:
18
+ - Windows/Linux: `Ctrl + Shift + R`
19
+ - Mac: `Cmd + Shift + R`
20
+
21
+ 2. **Check browser console** (F12):
22
+ - Look for: `"🔌 Connecting to live reload at http://localhost:3000/live-reload"`
23
+ - Look for: `"✅ Live reload connected"`
24
+ - If you see errors, note them
25
+
26
+ 3. **Disable browser extensions** temporarily:
27
+ - Ad blockers can block SSE connections
28
+ - Try in incognito/private mode
29
+
30
+ 4. **Check terminal output**:
31
+ - Should show: `"🔌 [time] Browser connected for live reload (1 total)"`
32
+ - If not showing, SSE connection failed
33
+
34
+ 5. **Restart dev server**:
35
+ ```bash
36
+ # Stop with Ctrl+C
37
+ npm run dev
38
+ ```
39
+
40
+ 6. **Clear browser cache completely**:
41
+ - Chrome: Settings → Privacy → Clear browsing data
42
+ - Firefox: Settings → Privacy → Clear Data
43
+ - Edge: Settings → Privacy → Clear browsing data
44
+
45
+ ### Changes Not Showing
46
+
47
+ **Symptoms:**
48
+ - Indicator shows "✅ Live Reload Active"
49
+ - Page reloads but changes don't appear
50
+
51
+ **Solutions:**
52
+
53
+ 1. **Check file was saved**:
54
+ - Verify file has no unsaved indicator in editor
55
+ - Check terminal shows: `"📝 Detected change: pages/Home.jsx"`
56
+
57
+ 2. **Check imports were regenerated**:
58
+ - Terminal should show: `"🔄 Regenerating imports..."`
59
+ - Check `app.html` has your file listed
60
+
61
+ 3. **Verify file location**:
62
+ - Files must be in: `api/`, `components/`, `pages/`, `modules/`, or `styles/`
63
+ - Files outside these folders won't trigger reload
64
+
65
+ 4. **Check for JavaScript errors**:
66
+ - Open browser console (F12)
67
+ - Look for red error messages
68
+ - Fix any syntax errors in your code
69
+
70
+ 5. **Manual import regeneration**:
71
+ ```bash
72
+ npm run build
73
+ ```
74
+
75
+ ### Indicator Shows "❌ Connection Error"
76
+
77
+ **Symptoms:**
78
+ - Red indicator with error message
79
+ - Console shows EventSource errors
80
+
81
+ **Solutions:**
82
+
83
+ 1. **Check dev server is running**:
84
+ - Terminal should show: `"✅ Dev server running with live reload!"`
85
+ - If not, run: `npm run dev`
86
+
87
+ 2. **Check port is correct**:
88
+ - Browser URL should match terminal output
89
+ - Example: `http://localhost:3000/`
90
+
91
+ 3. **Firewall blocking connection**:
92
+ - Allow Node.js through firewall
93
+ - Try different port: `PORT=3001 npm run dev`
94
+
95
+ 4. **Browser doesn't support EventSource**:
96
+ - Update to latest browser version
97
+ - Try different browser (Chrome, Firefox, Edge)
98
+
99
+ ## Page Not Found (404)
100
+
101
+ **Symptoms:**
102
+ - Clicking link shows 404 page
103
+ - URL is correct but page doesn't load
104
+
105
+ **Solutions:**
106
+
107
+ 1. **Check function name**:
108
+ ```jsx
109
+ // ✅ Correct - ends with "Page"
110
+ function AboutPage() { }
111
+
112
+ // ❌ Wrong - missing "Page"
113
+ function About() { }
114
+ ```
115
+
116
+ 2. **Check file is loaded**:
117
+ - Open `app.html`
118
+ - Look for: `<script type="text/babel" src="pages/YourPage.jsx"></script>`
119
+ - If missing, run: `npm run build`
120
+
121
+ 3. **Check browser console**:
122
+ - Look for: `"📄 Auto-registered: about → AboutPage()"`
123
+ - If missing, function name is wrong
124
+
125
+ 4. **Manual registration**:
126
+ ```jsx
127
+ // Add this if auto-registration fails
128
+ registerPage("about", AboutPage);
129
+ ```
130
+
131
+ ## State Not Working
132
+
133
+ **Symptoms:**
134
+ - `useState` is undefined
135
+ - State doesn't update
136
+
137
+ **Solutions:**
138
+
139
+ 1. **Check `/** @jsx h */` at top of file**:
140
+ ```jsx
141
+ /** @jsx h */
142
+
143
+ function MyPage() {
144
+ const [count, setCount] = useState(0);
145
+ // ...
146
+ }
147
+ ```
148
+
149
+ 2. **Check state.js is loaded**:
150
+ - Open `app.html`
151
+ - Look for: `<script type="text/babel" src="modules/state.js"></script>`
152
+
153
+ 3. **Check browser console for errors**:
154
+ - Look for: `"useState is not defined"`
155
+ - If found, state.js didn't load
156
+
157
+ ## Styling Not Applied
158
+
159
+ **Symptoms:**
160
+ - Page has no styling
161
+ - Looks like plain HTML
162
+
163
+ **Solutions:**
164
+
165
+ 1. **Check CSS file is linked**:
166
+ - Open `app.html`
167
+ - Look for: `<link rel="stylesheet" href="styles/globals.css">`
168
+
169
+ 2. **Check CSS file exists**:
170
+ - Verify `styles/globals.css` exists
171
+ - Check file has content
172
+
173
+ 3. **Check class names**:
174
+ ```jsx
175
+ // ✅ Correct
176
+ <div class="card">
177
+
178
+ // ❌ Wrong (React syntax)
179
+ <div className="card">
180
+ ```
181
+
182
+ 4. **Hard refresh**:
183
+ - CSS might be cached
184
+ - Press: `Ctrl + Shift + R` (Windows) or `Cmd + Shift + R` (Mac)
185
+
186
+ ## API Routes Not Working
187
+
188
+ **Symptoms:**
189
+ - `fetchApi()` returns 404
190
+ - API endpoint not found
191
+
192
+ **Solutions:**
193
+
194
+ 1. **Check API file is loaded**:
195
+ - Open `app.html`
196
+ - Look for: `<script type="text/babel" src="api/yourfile.js"></script>`
197
+
198
+ 2. **Check route registration**:
199
+ ```jsx
200
+ // In api/users.js
201
+ registerApiRoute('users', async (req, res) => {
202
+ // handler
203
+ });
204
+ ```
205
+
206
+ 3. **Check URL format**:
207
+ ```jsx
208
+ // ✅ Correct
209
+ await fetchApi('/api/users');
210
+
211
+ // ❌ Wrong
212
+ await fetchApi('api/users'); // missing leading /
213
+ await fetchApi('/users'); // missing /api/
214
+ ```
215
+
216
+ 4. **Check browser console**:
217
+ - Look for network errors
218
+ - Check request URL is correct
219
+
220
+ ## Port Already in Use
221
+
222
+ **Symptoms:**
223
+ - Error: `EADDRINUSE: address already in use :::3000`
224
+
225
+ **Solutions:**
226
+
227
+ 1. **Server auto-finds next port**:
228
+ - Check terminal for actual port
229
+ - Example: `"Server running at http://localhost:3001/"`
230
+
231
+ 2. **Kill process on port 3000**:
232
+ ```bash
233
+ # Windows
234
+ netstat -ano | findstr :3000
235
+ taskkill /PID <PID> /F
236
+
237
+ # Mac/Linux
238
+ lsof -ti:3000 | xargs kill -9
239
+ ```
240
+
241
+ 3. **Use different port**:
242
+ ```bash
243
+ PORT=3001 npm run dev
244
+ ```
245
+
246
+ ## General Tips
247
+
248
+ ### Before Asking for Help
249
+
250
+ 1. **Check browser console** (F12) for errors
251
+ 2. **Check terminal output** for server errors
252
+ 3. **Try hard refresh** (Ctrl+Shift+R)
253
+ 4. **Try incognito mode** to rule out extensions
254
+ 5. **Restart dev server** (Ctrl+C, then `npm run dev`)
255
+
256
+ ### Debug Checklist
257
+
258
+ - [ ] Dev server is running
259
+ - [ ] Browser URL matches server URL
260
+ - [ ] File is saved
261
+ - [ ] File is in correct folder
262
+ - [ ] `/** @jsx h */` at top of JSX files
263
+ - [ ] Function name ends with "Page"
264
+ - [ ] No JavaScript errors in console
265
+ - [ ] Live reload indicator is green
266
+
267
+ ### Still Having Issues?
268
+
269
+ 1. **Check documentation**:
270
+ - [Getting Started](GETTING-STARTED.md)
271
+ - [Auto-Registration](AUTO-REGISTRATION.md)
272
+ - [Dev Server](DEV-SERVER.md)
273
+
274
+ 2. **Create minimal reproduction**:
275
+ - Create new app: `npx create-aziz-app test-app`
276
+ - Test if issue persists in fresh app
277
+
278
+ 3. **Report issue** with:
279
+ - Browser console output
280
+ - Terminal output
281
+ - Code that's not working
282
+ - Steps to reproduce
@@ -56,17 +56,35 @@ function h(tag, props, ...children) {
56
56
  // "#/contact" → Contact page
57
57
  //
58
58
  // To add a new page:
59
- // 1. Create pages/YourPage.jsx
60
- // 2. Load it in app.html with <script type="text/babel">
61
- // 3. Register it below in the `routes` object
59
+ // 1. Create pages/YourPage.jsx with a function like AboutPage()
60
+ // 2. The page will automatically be registered!
61
+ // 3. Optional: Call registerPage("about", AboutPage) for custom route names
62
62
  // ============================================================
63
63
  const routes = {};
64
64
 
65
65
  // registerPage("about", AboutPage) — called by each page file
66
+ // Now optional! Pages auto-register based on function name
66
67
  function registerPage(path, component) {
67
68
  routes[path] = component;
68
69
  }
69
70
 
71
+ // Auto-register pages from global scope
72
+ // Looks for functions ending with "Page" (e.g., AboutPage, HomePage)
73
+ function autoRegisterPages() {
74
+ for (let key in window) {
75
+ if (key.endsWith('Page') && typeof window[key] === 'function') {
76
+ // Convert "AboutPage" → "about", "HomePage" → "home"
77
+ const routeName = key.replace('Page', '').toLowerCase();
78
+
79
+ // Only register if not already registered
80
+ if (!routes[routeName]) {
81
+ routes[routeName] = window[key];
82
+ console.log(`📄 Auto-registered: ${routeName} → ${key}()`);
83
+ }
84
+ }
85
+ }
86
+ }
87
+
70
88
  function getCurrentPath() {
71
89
  // Remove the "#/" prefix → "about", "contact", or "" for home
72
90
  return window.location.hash.replace("#/", "") || "home";
@@ -162,8 +180,10 @@ function NotFoundPage() {
162
180
  return (
163
181
  <div class="not-found">
164
182
  <h1>404</h1>
165
- <p>Page not found.</p>
166
- <button class="btn btn-primary" onClick={() => navigate("home")}>Go Home</button>
183
+ <p>Oops! The page you're looking for doesn't exist.</p>
184
+ <button class="btn btn-primary" onClick={() => navigate("home")}>
185
+ Go Home
186
+ </button>
167
187
  </div>
168
188
  );
169
189
  }
@@ -174,6 +194,9 @@ function NotFoundPage() {
174
194
  // Called once after all scripts are loaded
175
195
  // ============================================================
176
196
  function startApp() {
197
+ // Auto-register any pages that weren't manually registered
198
+ autoRegisterPages();
199
+
177
200
  renderShell();
178
201
  renderPage();
179
202
 
@@ -1,8 +1,9 @@
1
1
  /** @jsx h */
2
2
 
3
- // Register this page at route "about" → "#/about"
4
- registerPage("about", AboutPage);
3
+ // Optional: You can still manually register if you want a custom route name
4
+ // registerPage("about", AboutPage);
5
5
 
6
+ // Or just define the function and it auto-registers as "about"
6
7
  function AboutPage() {
7
8
  return (
8
9
  <div>
@@ -28,6 +29,20 @@ function AboutPage() {
28
29
  Go to Contact →
29
30
  </button>
30
31
  </div>
32
+
33
+ <div class="card">
34
+ <h2>✨ Auto-Registration</h2>
35
+ <p>
36
+ This page works without calling <code>registerPage()</code>!
37
+ Just name your function <code>YourNamePage()</code> and it automatically
38
+ becomes a route.
39
+ </p>
40
+ <ul style={{ lineHeight: '1.8', marginLeft: '20px' }}>
41
+ <li><code>HomePage()</code> → <code>#/home</code></li>
42
+ <li><code>AboutPage()</code> → <code>#/about</code></li>
43
+ <li><code>ContactPage()</code> → <code>#/contact</code></li>
44
+ </ul>
45
+ </div>
31
46
  </div>
32
47
  );
33
48
  }
@@ -1,6 +1,6 @@
1
1
  /** @jsx h */
2
2
 
3
- // Register this page at route "api-demo" → "#/api-demo"
3
+ // Auto-registered as "api-demo" route (or manually register for custom name)
4
4
  registerPage("api-demo", ApiDemoPage);
5
5
 
6
6
  function ApiDemoPage() {
@@ -1,8 +1,6 @@
1
1
  /** @jsx h */
2
2
 
3
- // Register this page at route "contact" → "#/contact"
4
- registerPage("contact", ContactPage);
5
-
3
+ // Auto-registered as "contact" route
6
4
  function ContactPage() {
7
5
  return (
8
6
  <div>
@@ -0,0 +1,59 @@
1
+ /** @jsx h */
2
+
3
+ // That's it! No registerPage() needed.
4
+ // This automatically becomes route "#/example"
5
+ function ExamplePage() {
6
+ const [message, setMessage] = useState('Hello from Example Page! 🎉');
7
+
8
+ return (
9
+ <div>
10
+ <h1>Example Page</h1>
11
+
12
+ <div class="card">
13
+ <h2>✨ Auto-Registration Demo</h2>
14
+ <p>
15
+ This page was created without calling <code>registerPage()</code>.
16
+ Just define a function ending with "Page" and it works!
17
+ </p>
18
+
19
+ <div style={{
20
+ background: '#f0f0f0',
21
+ padding: '16px',
22
+ borderRadius: '8px',
23
+ fontFamily: 'monospace',
24
+ fontSize: '14px'
25
+ }}>
26
+ <strong>Function name:</strong> ExamplePage()<br/>
27
+ <strong>Auto route:</strong> #/example<br/>
28
+ <strong>URL:</strong> {window.location.href}
29
+ </div>
30
+ </div>
31
+
32
+ <div class="card">
33
+ <h2>State Management Works Too</h2>
34
+ <p>{message}</p>
35
+ <button
36
+ class="btn btn-primary"
37
+ onClick={() => setMessage('State updated! ✅')}
38
+ >
39
+ Update Message
40
+ </button>
41
+ </div>
42
+
43
+ <div class="card">
44
+ <h2>Navigation</h2>
45
+ <div style={{ display: 'flex', gap: '12px' }}>
46
+ <button class="btn btn-primary" onClick={() => navigate("home")}>
47
+ Home
48
+ </button>
49
+ <button class="btn btn-primary" onClick={() => navigate("about")}>
50
+ About
51
+ </button>
52
+ <button class="btn btn-primary" onClick={() => navigate("test")}>
53
+ Test
54
+ </button>
55
+ </div>
56
+ </div>
57
+ </div>
58
+ );
59
+ }
@@ -1,7 +1,6 @@
1
1
  /** @jsx h */
2
2
 
3
- registerPage("home", HomePage);
4
-
3
+ // Auto-registered as "home" route
5
4
  function HomePage() {
6
5
  return (
7
6
  <div>
@@ -1,7 +1,6 @@
1
1
  /** @jsx h */
2
2
 
3
- registerPage("test", TestPage);
4
-
3
+ // Auto-registered as "test" route
5
4
  function TestPage() {
6
5
  const [count, setCount] = useState(0);
7
6
  const [name, setName] = useState('');
@@ -26,57 +26,136 @@ function generateImports() {
26
26
 
27
27
  // Notify all clients to reload
28
28
  function notifyClients() {
29
- console.log('🔄 Notifying browser to reload...');
29
+ const timestamp = new Date().toLocaleTimeString();
30
+ console.log(`🔄 [${timestamp}] Notifying ${clients.length} browser(s) to reload...`);
30
31
  clients.forEach(client => {
31
32
  client.write('data: reload\n\n');
32
33
  });
33
34
  }
34
35
 
35
36
  // Live reload script to inject
36
- const liveReloadScript = `
37
+ function getLiveReloadScript() {
38
+ return `
37
39
  <script>
38
- // Live reload client
39
- const evtSource = new EventSource('/live-reload');
40
- evtSource.onmessage = (event) => {
41
- if (event.data === 'reload') {
42
- console.log('🔄 Changes detected, reloading...');
43
- location.reload();
40
+ (function() {
41
+ // Create visual indicator
42
+ const indicator = document.createElement('div');
43
+ indicator.id = 'live-reload-indicator';
44
+ indicator.style.cssText = 'position: fixed; bottom: 20px; right: 20px; background: #4caf50; color: white; padding: 8px 16px; border-radius: 20px; font-size: 12px; font-family: monospace; z-index: 9999; box-shadow: 0 2px 8px rgba(0,0,0,0.2); transition: all 0.3s;';
45
+ indicator.textContent = '🔌 Connecting...';
46
+ document.body.appendChild(indicator);
47
+
48
+ // Live reload client
49
+ console.log('🔌 Connecting to live reload at ' + window.location.origin + '/live-reload');
50
+
51
+ let evtSource;
52
+ let reconnectAttempts = 0;
53
+ const maxReconnectAttempts = 5;
54
+
55
+ function connect() {
56
+ try {
57
+ evtSource = new EventSource('/live-reload');
58
+
59
+ evtSource.onopen = function() {
60
+ console.log('✅ Live reload connected');
61
+ reconnectAttempts = 0;
62
+ indicator.style.background = '#4caf50';
63
+ indicator.textContent = '✅ Live Reload Active';
64
+ setTimeout(function() {
65
+ indicator.style.opacity = '0.3';
66
+ }, 2000);
67
+ };
68
+
69
+ evtSource.onmessage = function(event) {
70
+ if (event.data === 'reload') {
71
+ console.log('🔄 Changes detected, reloading...');
72
+ indicator.style.opacity = '1';
73
+ indicator.style.background = '#2196f3';
74
+ indicator.textContent = '🔄 Reloading...';
75
+ setTimeout(function() {
76
+ // Add timestamp to force cache bust
77
+ var url = window.location.href.split('?')[0];
78
+ window.location.href = url + '?t=' + Date.now();
79
+ }, 100);
80
+ }
81
+ };
82
+
83
+ evtSource.onerror = function(err) {
84
+ console.log('⚠️ Live reload connection error');
85
+ indicator.style.background = '#ff9800';
86
+ indicator.style.opacity = '1';
87
+ indicator.textContent = '⚠️ Connection Lost';
88
+
89
+ if (evtSource) {
90
+ evtSource.close();
91
+ }
92
+
93
+ if (reconnectAttempts < maxReconnectAttempts) {
94
+ reconnectAttempts++;
95
+ console.log('Reconnecting... attempt ' + reconnectAttempts);
96
+ setTimeout(connect, 2000);
97
+ } else {
98
+ indicator.textContent = '❌ Reload Failed';
99
+ console.log('Max reconnection attempts reached. Please refresh manually.');
100
+ }
101
+ };
102
+ } catch (e) {
103
+ console.error('Failed to create EventSource:', e);
104
+ indicator.style.background = '#f44336';
105
+ indicator.textContent = '❌ Connection Error';
106
+ }
44
107
  }
45
- };
46
- evtSource.onerror = () => {
47
- console.log('⚠️ Live reload disconnected');
48
- };
49
- console.log('✅ Live reload connected');
108
+
109
+ connect();
110
+
111
+ // Show indicator on hover
112
+ indicator.addEventListener('mouseenter', function() {
113
+ indicator.style.opacity = '1';
114
+ });
115
+ indicator.addEventListener('mouseleave', function() {
116
+ if (indicator.textContent.includes('Active')) {
117
+ indicator.style.opacity = '0.3';
118
+ }
119
+ });
120
+ })();
50
121
  </script>
51
122
  `;
123
+ }
52
124
 
53
125
  // Create HTTP server
54
126
  function createServer(port) {
55
127
  return http.createServer((req, res) => {
56
128
  // Handle live reload SSE endpoint
57
- if (req.url === '/live-reload') {
129
+ if (req.url === '/live-reload' || req.url.startsWith('/live-reload?')) {
58
130
  res.writeHead(200, {
59
131
  'Content-Type': 'text/event-stream',
60
- 'Cache-Control': 'no-cache',
132
+ 'Cache-Control': 'no-cache, no-store, must-revalidate',
61
133
  'Connection': 'keep-alive',
62
- 'Access-Control-Allow-Origin': '*'
134
+ 'Access-Control-Allow-Origin': '*',
135
+ 'X-Accel-Buffering': 'no'
63
136
  });
64
137
 
138
+ // Send initial connection message
139
+ res.write(':ok\n\n');
140
+
65
141
  clients.push(res);
66
- console.log('🔌 Browser connected for live reload');
142
+ const timestamp = new Date().toLocaleTimeString();
143
+ console.log(`🔌 [${timestamp}] Browser connected for live reload (${clients.length} total)`);
67
144
 
68
145
  req.on('close', () => {
69
146
  const index = clients.indexOf(res);
70
147
  if (index !== -1) {
71
148
  clients.splice(index, 1);
72
149
  }
73
- console.log('🔌 Browser disconnected from live reload');
150
+ const closeTime = new Date().toLocaleTimeString();
151
+ console.log(`🔌 [${closeTime}] Browser disconnected (${clients.length} remaining)`);
74
152
  });
75
153
 
76
154
  return;
77
155
  }
78
156
 
79
- let filePath = '.' + req.url;
157
+ // Strip query parameters for file serving (cache busting)
158
+ let filePath = '.' + req.url.split('?')[0];
80
159
  if (filePath === './') {
81
160
  filePath = './app.html';
82
161
  }
@@ -115,10 +194,16 @@ function createServer(port) {
115
194
  } else {
116
195
  // Inject live reload script into HTML files
117
196
  if (extname === '.html') {
118
- content = content.toString().replace('</body>', liveReloadScript + '</body>');
197
+ content = content.toString().replace('</body>', getLiveReloadScript() + '</body>');
119
198
  }
120
199
 
121
- res.writeHead(200, { 'Content-Type': contentType });
200
+ // Add cache control headers to prevent caching during development
201
+ res.writeHead(200, {
202
+ 'Content-Type': contentType,
203
+ 'Cache-Control': 'no-cache, no-store, must-revalidate',
204
+ 'Pragma': 'no-cache',
205
+ 'Expires': '0'
206
+ });
122
207
  res.end(content, 'utf-8');
123
208
  }
124
209
  });
@@ -143,16 +228,35 @@ function startServer(port) {
143
228
  }
144
229
 
145
230
  // Watch directories
146
- const watchDirs = ['api', 'components', 'pages', 'modules'];
231
+ const watchDirs = ['api', 'components', 'pages', 'modules', 'styles'];
232
+
233
+ // Debounce to prevent multiple rapid reloads
234
+ let reloadTimeout = null;
147
235
 
148
236
  console.log('👀 Watching for changes in:');
149
237
  watchDirs.forEach(dir => {
150
238
  if (fs.existsSync(dir)) {
151
239
  console.log(` - ${dir}/`);
152
240
  fs.watch(dir, { recursive: false }, (eventType, filename) => {
153
- if (filename && (filename.endsWith('.js') || filename.endsWith('.jsx'))) {
241
+ if (filename && (filename.endsWith('.js') || filename.endsWith('.jsx') || filename.endsWith('.css'))) {
154
242
  console.log(`\n📝 Detected change: ${dir}/${filename}`);
155
- generateImports();
243
+
244
+ // Clear existing timeout
245
+ if (reloadTimeout) {
246
+ clearTimeout(reloadTimeout);
247
+ }
248
+
249
+ // For CSS changes, just reload without regenerating imports
250
+ if (filename.endsWith('.css')) {
251
+ reloadTimeout = setTimeout(() => {
252
+ notifyClients();
253
+ }, 300);
254
+ } else {
255
+ // For JS/JSX changes, regenerate imports
256
+ reloadTimeout = setTimeout(() => {
257
+ generateImports();
258
+ }, 500);
259
+ }
156
260
  }
157
261
  });
158
262
  }