create-aziz-app 2.0.7 → 2.0.8

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.8",
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,10 @@ 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
143
158
  - **[Quick Start](docs/QUICK-START.md)** - Quick examples
144
159
 
145
160
  ## 🛠️ Commands
@@ -153,8 +168,9 @@ npm run build # Generate imports manually
153
168
 
154
169
  ### Pages
155
170
  - Files in `pages/` become routes
156
- - Use `registerPage("route", Component)`
157
- - Access via `#/route`
171
+ - Name functions with "Page" suffix (e.g., `AboutPage`)
172
+ - Auto-registers as route (e.g., `#/about`)
173
+ - Optional: Use `registerPage("custom-name", Component)` for custom routes
158
174
 
159
175
  ### Components
160
176
  - Reusable UI components
package/template/app.html CHANGED
@@ -40,6 +40,7 @@
40
40
  <script type="text/babel" src="pages/About.jsx"></script>
41
41
  <script type="text/babel" src="pages/ApiDemo.jsx"></script>
42
42
  <script type="text/babel" src="pages/Contact.jsx"></script>
43
+ <script type="text/babel" src="pages/Example.jsx"></script>
43
44
  <script type="text/babel" src="pages/Home.jsx"></script>
44
45
  <script type="text/babel" src="pages/test.jsx"></script>
45
46
 
@@ -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
@@ -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,7 +26,8 @@ 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
  });
@@ -35,18 +36,74 @@ function notifyClients() {
35
36
  // Live reload script to inject
36
37
  const liveReloadScript = `
37
38
  <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();
44
- }
45
- };
46
- evtSource.onerror = () => {
47
- console.log('⚠️ Live reload disconnected');
48
- };
49
- console.log('✅ Live reload connected');
39
+ (function() {
40
+ // Create visual indicator
41
+ const indicator = document.createElement('div');
42
+ indicator.id = 'live-reload-indicator';
43
+ indicator.style.cssText = \`
44
+ position: fixed;
45
+ bottom: 20px;
46
+ right: 20px;
47
+ background: #4caf50;
48
+ color: white;
49
+ padding: 8px 16px;
50
+ border-radius: 20px;
51
+ font-size: 12px;
52
+ font-family: monospace;
53
+ z-index: 9999;
54
+ box-shadow: 0 2px 8px rgba(0,0,0,0.2);
55
+ transition: all 0.3s;
56
+ \`;
57
+ indicator.textContent = '🔌 Connecting...';
58
+ document.body.appendChild(indicator);
59
+
60
+ // Live reload client
61
+ console.log('🔌 Connecting to live reload...');
62
+ const evtSource = new EventSource('/live-reload');
63
+
64
+ evtSource.onopen = () => {
65
+ console.log('✅ Live reload connected');
66
+ indicator.style.background = '#4caf50';
67
+ indicator.textContent = '✅ Live Reload Active';
68
+ // Hide after 2 seconds
69
+ setTimeout(() => {
70
+ indicator.style.opacity = '0.3';
71
+ }, 2000);
72
+ };
73
+
74
+ evtSource.onmessage = (event) => {
75
+ if (event.data === 'reload') {
76
+ console.log('🔄 Changes detected, reloading...');
77
+ indicator.style.opacity = '1';
78
+ indicator.style.background = '#2196f3';
79
+ indicator.textContent = '🔄 Reloading...';
80
+ // Force reload and clear cache
81
+ setTimeout(() => {
82
+ window.location.reload(true);
83
+ }, 100);
84
+ }
85
+ };
86
+
87
+ evtSource.onerror = (err) => {
88
+ console.log('⚠️ Live reload disconnected, retrying...');
89
+ indicator.style.background = '#ff9800';
90
+ indicator.style.opacity = '1';
91
+ indicator.textContent = '⚠️ Reconnecting...';
92
+ evtSource.close();
93
+ // Retry connection after 2 seconds
94
+ setTimeout(() => {
95
+ window.location.reload();
96
+ }, 2000);
97
+ };
98
+
99
+ // Show indicator on hover
100
+ indicator.addEventListener('mouseenter', () => {
101
+ indicator.style.opacity = '1';
102
+ });
103
+ indicator.addEventListener('mouseleave', () => {
104
+ indicator.style.opacity = '0.3';
105
+ });
106
+ })();
50
107
  </script>
51
108
  `;
52
109
 
@@ -118,7 +175,13 @@ function createServer(port) {
118
175
  content = content.toString().replace('</body>', liveReloadScript + '</body>');
119
176
  }
120
177
 
121
- res.writeHead(200, { 'Content-Type': contentType });
178
+ // Add cache control headers to prevent caching during development
179
+ res.writeHead(200, {
180
+ 'Content-Type': contentType,
181
+ 'Cache-Control': 'no-cache, no-store, must-revalidate',
182
+ 'Pragma': 'no-cache',
183
+ 'Expires': '0'
184
+ });
122
185
  res.end(content, 'utf-8');
123
186
  }
124
187
  });
@@ -143,16 +206,35 @@ function startServer(port) {
143
206
  }
144
207
 
145
208
  // Watch directories
146
- const watchDirs = ['api', 'components', 'pages', 'modules'];
209
+ const watchDirs = ['api', 'components', 'pages', 'modules', 'styles'];
210
+
211
+ // Debounce to prevent multiple rapid reloads
212
+ let reloadTimeout = null;
147
213
 
148
214
  console.log('👀 Watching for changes in:');
149
215
  watchDirs.forEach(dir => {
150
216
  if (fs.existsSync(dir)) {
151
217
  console.log(` - ${dir}/`);
152
218
  fs.watch(dir, { recursive: false }, (eventType, filename) => {
153
- if (filename && (filename.endsWith('.js') || filename.endsWith('.jsx'))) {
219
+ if (filename && (filename.endsWith('.js') || filename.endsWith('.jsx') || filename.endsWith('.css'))) {
154
220
  console.log(`\n📝 Detected change: ${dir}/${filename}`);
155
- generateImports();
221
+
222
+ // Clear existing timeout
223
+ if (reloadTimeout) {
224
+ clearTimeout(reloadTimeout);
225
+ }
226
+
227
+ // For CSS changes, just reload without regenerating imports
228
+ if (filename.endsWith('.css')) {
229
+ reloadTimeout = setTimeout(() => {
230
+ notifyClients();
231
+ }, 300);
232
+ } else {
233
+ // For JS/JSX changes, regenerate imports
234
+ reloadTimeout = setTimeout(() => {
235
+ generateImports();
236
+ }, 500);
237
+ }
156
238
  }
157
239
  });
158
240
  }