clovie 0.1.16 → 0.1.17

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 (39) hide show
  1. package/README.md +410 -344
  2. package/bin/cli.js +159 -8
  3. package/bin/kill-port.js +99 -0
  4. package/dist/{LiveReload-CqLIyMAq.js → LiveReload-DVEZWHf3.js} +12 -8
  5. package/dist/LiveReload-DVEZWHf3.js.map +1 -0
  6. package/dist/Server-D_nOQX0E.js +530 -0
  7. package/dist/Server-D_nOQX0E.js.map +1 -0
  8. package/dist/cjs/{LiveReload-CSmPQa1-.cjs → LiveReload-Be6N_lnM.cjs} +10 -9
  9. package/dist/cjs/LiveReload-Be6N_lnM.cjs.map +1 -0
  10. package/dist/cjs/Server-CN4bVO2j.cjs +503 -0
  11. package/dist/cjs/Server-CN4bVO2j.cjs.map +1 -0
  12. package/dist/cjs/{createClovie-Dm4WUXg4.cjs → createClovie-CWEt0g2r.cjs} +1336 -271
  13. package/dist/cjs/createClovie-CWEt0g2r.cjs.map +1 -0
  14. package/dist/cjs/index-DLefxiwH.cjs +332 -0
  15. package/dist/cjs/index-DLefxiwH.cjs.map +1 -0
  16. package/dist/cjs/index.cjs +3 -2
  17. package/dist/cjs/index.cjs.map +1 -1
  18. package/dist/{createClovie-PYUiW2YJ.js → createClovie-B0jNRKtG.js} +1329 -266
  19. package/dist/createClovie-B0jNRKtG.js.map +1 -0
  20. package/dist/index-CdqSf8xZ.js +355 -0
  21. package/dist/index-CdqSf8xZ.js.map +1 -0
  22. package/dist/index.d.ts +1 -1
  23. package/dist/index.js +5 -1
  24. package/dist/index.js.map +1 -1
  25. package/package.json +10 -2
  26. package/templates/default/README.md +100 -12
  27. package/templates/default/clovie.config.js +20 -19
  28. package/templates/server/README.md +260 -66
  29. package/templates/server/clovie.config.js +75 -35
  30. package/templates/static/README.md +169 -38
  31. package/templates/static/clovie.config.js +50 -29
  32. package/dist/LiveReload-CqLIyMAq.js.map +0 -1
  33. package/dist/Server-BxIJW31q.js +0 -375
  34. package/dist/Server-BxIJW31q.js.map +0 -1
  35. package/dist/cjs/LiveReload-CSmPQa1-.cjs.map +0 -1
  36. package/dist/cjs/Server-D7RmLCVP.cjs +0 -351
  37. package/dist/cjs/Server-D7RmLCVP.cjs.map +0 -1
  38. package/dist/cjs/createClovie-Dm4WUXg4.cjs.map +0 -1
  39. package/dist/createClovie-PYUiW2YJ.js.map +0 -1
package/README.md CHANGED
@@ -1,32 +1,62 @@
1
- # Clovie - Vintage Web Dev Tooling
1
+ # Clovie - Vintage Web Dev Tooling with Modern QoL
2
2
 
3
- A Node.js-based static site generator and web framework designed to be simple, fast, and highly modular. Built on the **brickworks/engine** pattern for maximum flexibility and maintainability.
3
+ > *"The Hollow Knight of Web Dev"* - Simple but deep, easy to start but room to grow.
4
4
 
5
- ## Architecture Overview
5
+ A powerful Node.js-based **static site generator** and **full-stack web framework** that bridges the gap between simple static sites and complex web applications. Built on the **@brickworks/engine** service architecture for maximum flexibility and maintainability.
6
6
 
7
- Clovie uses a **service-oriented architecture** where all functionality is provided by services that extend `ServiceProvider` from the brickworks/engine framework. The engine orchestrates these services through dependency injection and provides stable state management.
7
+ ## 🚀 Quick Start
8
8
 
9
- ### Core Services
9
+ ```bash
10
+ # Create a new project
11
+ npx clovie create my-site
10
12
 
11
- - **File** - File system operations (reading, writing, watching)
12
- - **Compiler** - Template compilation with live reload injection
13
- - **Views** - View discovery and processing
14
- - **Routes** - Route generation and processing (static & dynamic)
15
- - **Build** - Static site generation orchestration
16
- - **Server** - Express server management (conditionally loaded)
17
- - **Cache** - Build caching and incremental builds
13
+ # Start development
14
+ cd my-site
15
+ npm install
16
+ npm run dev
17
+ ```
18
+
19
+ ## Key Features
20
+
21
+ - **🎯 Dual Mode**: Static site generation OR full Express server applications
22
+ - **🔄 Zero Config**: Smart auto-detection of project structure
23
+ - **⚡ Fast Builds**: Incremental builds with intelligent caching
24
+ - **🎨 Template Agnostic**: Handlebars, Nunjucks, Pug, Mustache, or custom engines
25
+ - **📦 Asset Pipeline**: SCSS compilation, JavaScript bundling with esbuild
26
+ - **🔄 Live Reload**: WebSocket-based live reload during development
27
+ - **🗄️ Database Ready**: SQLite integration for server mode applications
28
+ - **🛣️ Dynamic Routing**: Data-driven page generation and API endpoints
29
+ - **🔧 Service Architecture**: Modular, extensible service-oriented design
18
30
 
19
- ### Two Operating Modes
31
+ ## 🏗️ Architecture Overview
20
32
 
21
- **Static Mode (`type: 'static'`)**:
22
- - Generates static HTML files to output directory
23
- - Uses Express server only for development (live reload, file serving)
24
- - Traditional static site generator behavior
33
+ Clovie uses a **service-oriented architecture** built on `@brickworks/engine`. All functionality is provided by services that extend `ServiceProvider`, orchestrated through dependency injection with reactive state management.
34
+
35
+ ### Core Services
25
36
 
26
- **Server Mode (`type: 'server'`)**:
27
- - Builds a real Express application
28
- - Serves static files + handles dynamic routes/API endpoints
29
- - Full web application server with server-side rendering
37
+ - **🗂️ File** - File system operations with intelligent watching
38
+ - **⚙️ Compile** - Asset compilation with progress tracking
39
+ - **📝 Configurator** - Configuration management with hot-reloading
40
+ - **🏃 Run** - Build orchestration and task execution
41
+ - **🌐 Server** - Express server with kernel-based request handling
42
+ - **🔄 LiveReload** - Development live-reload with WebSocket
43
+ - **🛣️ Router** - Route processing for both static and dynamic content
44
+ - **💾 Cache** - Smart caching for incremental builds
45
+
46
+ ### Operating Modes
47
+
48
+ **🗂️ Static Mode (`type: 'static'`)**:
49
+ - Generates optimized static HTML files
50
+ - Perfect for blogs, documentation, marketing sites
51
+ - Uses development server only for live reload
52
+ - Deployable to any static hosting (Netlify, Vercel, GitHub Pages)
53
+
54
+ **🌐 Server Mode (`type: 'server'`)**:
55
+ - Full Express.js web application
56
+ - API endpoints with state management
57
+ - Server-side rendering with dynamic routes
58
+ - Database integration and real-time features
59
+ - Perfect for web apps, dashboards, APIs
30
60
 
31
61
  ## Project Structure
32
62
 
@@ -101,289 +131,327 @@ actions(useContext) {
101
131
  - **Incremental Builds**: Smart caching for faster rebuilds
102
132
  - **Auto-Discovery**: Intelligent project structure detection
103
133
 
104
- ## Usage
134
+ ## 📦 Installation & Usage
105
135
 
106
- ### Installation
136
+ ### Creating New Projects
107
137
 
108
- #### Option 1: Local Installation (Recommended)
138
+ #### Quick Start with Templates
109
139
  ```bash
110
- # Install as dev dependency in your project
111
- npm install --save-dev clovie
140
+ # Static site (blogs, docs, marketing)
141
+ npx clovie create my-blog --template static
112
142
 
113
- # Use via npm scripts
114
- npm run build
115
- npm run dev
116
- ```
143
+ # Server application (APIs, web apps)
144
+ npx clovie create my-app --template server
117
145
 
118
- #### Option 2: Global Installation
119
- ```bash
120
- # Install globally
121
- npm install -g clovie
146
+ # Default (auto-detected)
147
+ npx clovie create my-site
122
148
  ```
123
149
 
124
- ### Creating New Projects
125
-
126
- #### Using Clovie CLI (Recommended)
150
+ #### Manual Installation
127
151
  ```bash
128
- # Create a new project
129
- npx clovie create my-site
152
+ # Install in existing project
153
+ npm install --save-dev clovie
130
154
 
131
- # Or with global install
132
- clovie create my-site
155
+ # Or globally
156
+ npm install -g clovie
133
157
  ```
134
158
 
159
+ ### Development Workflow
135
160
 
136
-
137
- ### Building and Development
138
-
139
- #### Static Mode (Default)
161
+ #### 🗂️ Static Site Development
140
162
  ```bash
141
- # Build static files
142
- clovie build
163
+ # Start development server with live reload
164
+ npm run dev
143
165
  # or
144
- npm run build
166
+ clovie dev
145
167
 
146
- # Development server with live reload
147
- clovie watch
168
+ # Build optimized static files
169
+ npm run build
148
170
  # or
149
- npm run dev
171
+ clovie build
172
+
173
+ # Preview production build
174
+ clovie serve --static
150
175
  ```
151
176
 
152
- #### Server Mode
177
+ #### 🌐 Server Application Development
153
178
  ```bash
154
- # Run as Express server application
155
- clovie server
156
- # or add to package.json:
157
- # "scripts": { "serve": "clovie server" }
179
+ # Start development server with live reload
180
+ npm run dev
181
+ # or
182
+ clovie dev
183
+
184
+ # Start production server
185
+ npm start
186
+ # or
187
+ clovie serve
188
+
189
+ # Build assets only (server handles routing)
190
+ clovie build
158
191
  ```
159
192
 
160
- ## Configuration
193
+ ## ⚙️ Configuration
161
194
 
162
- ### Minimal Configuration (Recommended)
195
+ ### Zero Config Start
163
196
 
164
- Clovie uses smart defaults and auto-detection, so you can start with just:
197
+ Clovie uses **smart auto-detection** - just create your files and start:
165
198
 
166
199
  ```javascript
200
+ // clovie.config.js (minimal)
167
201
  export default {
168
202
  data: {
169
- title: 'My Site'
203
+ title: 'My Site',
204
+ description: 'Built with Clovie'
170
205
  }
171
206
  };
172
207
  ```
173
208
 
174
- Clovie will automatically detect:
175
- - `views/` directory for HTML templates
176
- - `scripts/main.js` for JavaScript entry point
177
- - `styles/main.scss` for SCSS entry point
178
- - `assets/` directory for static files
209
+ Automatically detects:
210
+ - `views/` HTML templates
211
+ - `scripts/main.js` JavaScript entry
212
+ - `styles/main.scss` SCSS entry
213
+ - `assets/` Static assets
214
+ - `partials/` → Reusable components
215
+
216
+ ### 🗂️ Static Site Configuration
179
217
 
180
- ### Static Site Configuration
218
+ Perfect for blogs, documentation, and marketing sites:
181
219
 
182
220
  ```javascript
183
221
  export default {
184
- type: 'static', // Default - generates static files
185
-
186
- // Auto-detected paths (override if needed)
187
- views: './src/views',
188
- scripts: './src/js/app.js',
189
- styles: './src/scss/main.scss',
190
- assets: './public',
191
- outputDir: './dist',
222
+ type: 'static', // Generate static HTML files
192
223
 
193
- // Template compilation
194
- templateCompiler: (template, data) => {
195
- return yourTemplateEngine(template, data);
224
+ // Data available in all templates
225
+ data: {
226
+ site: {
227
+ title: 'My Blog',
228
+ url: 'https://myblog.com',
229
+ description: 'A fast static blog'
230
+ },
231
+ nav: [
232
+ { title: 'Home', url: '/' },
233
+ { title: 'About', url: '/about' },
234
+ { title: 'Blog', url: '/blog' }
235
+ ]
196
236
  },
197
237
 
198
- // Routes for dynamic pages from data
238
+ // Template engine (auto-detected from usage)
239
+ renderEngine: 'handlebars', // or nunjucks, pug, custom function
240
+
241
+ // Dynamic pages from data
199
242
  routes: [{
200
243
  name: 'Blog Posts',
201
244
  path: '/posts/:slug',
202
245
  template: 'post.html',
203
- repeat: (state) => state.get(['posts']),
204
- data: (state, post) => ({
205
- ...post,
206
- title: post.title,
207
- slug: post.slug
246
+ repeat: (data) => data.posts, // Generate page for each post
247
+ data: (globalData, post) => ({
248
+ ...globalData,
249
+ post,
250
+ title: `${post.title} - ${globalData.site.title}`
208
251
  })
209
- }]
252
+ }],
253
+
254
+ // Build optimizations
255
+ minify: true,
256
+ generateSitemap: true
210
257
  };
211
258
  ```
212
259
 
213
- ### Server Application Configuration
260
+ ### 🌐 Server Application Configuration
261
+
262
+ Full-stack web applications with APIs and dynamic content:
214
263
 
215
264
  ```javascript
265
+ import express from 'express';
266
+
216
267
  export default {
217
268
  type: 'server', // Express application mode
218
-
219
269
  port: 3000,
220
- outputDir: './dist', // Serve static files from here
221
-
222
- // Same view/asset processing as static mode
223
- views: './src/views',
224
- scripts: './src/js',
225
- styles: './src/scss',
226
270
 
227
- // Server-specific routes
228
- routes: [{
229
- name: 'Posts API',
230
- path: '/api/posts',
231
- method: 'GET',
232
- handler: async (req, res) => {
233
- const posts = await getPosts();
234
- res.json(posts);
235
- }
236
- }, {
237
- name: 'Post Pages',
238
- path: '/posts/:slug',
239
- template: 'post.html',
240
- data: async (state, params) => {
241
- const post = await getPost(params.slug);
242
- return { post };
271
+ // Shared data and configuration
272
+ data: {
273
+ app: {
274
+ name: 'My App',
275
+ version: '1.0.0'
243
276
  }
244
- }],
277
+ },
245
278
 
246
- // API routes
247
- api: [{
248
- path: '/api/users',
249
- method: 'POST',
250
- handler: async (req, res) => {
251
- const user = await createUser(req.body);
252
- res.json(user);
253
- }
254
- }],
279
+ // Database configuration (optional)
280
+ dbPath: './data/app.db',
255
281
 
256
282
  // Express middleware
257
283
  middleware: [
258
284
  express.json(),
259
- cors()
285
+ express.urlencoded({ extended: true }),
286
+ // Add CORS, authentication, etc.
287
+ ],
288
+
289
+ // API endpoints
290
+ api: [
291
+ {
292
+ path: '/api/users',
293
+ method: 'GET',
294
+ action: async (state, event) => {
295
+ const users = await state.db.query('SELECT * FROM users');
296
+ return { users, total: users.length };
297
+ }
298
+ },
299
+ {
300
+ path: '/api/users',
301
+ method: 'POST',
302
+ action: async (state, event) => {
303
+ const { name, email } = event.body;
304
+ const user = await state.db.insert('users', { name, email });
305
+ return { success: true, user };
306
+ }
307
+ },
308
+ {
309
+ path: '/api/users/:id',
310
+ method: 'GET',
311
+ action: async (state, event) => {
312
+ const user = await state.db.findById('users', event.params.id);
313
+ return user ? { user } : { error: 'User not found', status: 404 };
314
+ }
315
+ }
316
+ ],
317
+
318
+ // Server-rendered routes
319
+ routes: [
320
+ {
321
+ name: 'User Dashboard',
322
+ path: '/dashboard/:userId',
323
+ template: 'dashboard.html',
324
+ data: async (state, params) => {
325
+ const user = await state.db.findById('users', params.userId);
326
+ const stats = await getUserStats(params.userId);
327
+ return { user, stats, title: `Dashboard - ${user.name}` };
328
+ }
329
+ }
260
330
  ]
261
331
  };
262
332
  ```
263
333
 
264
- ## Advanced Features
334
+ ## 🚀 Advanced Features
265
335
 
266
- ### Async Data Loading
336
+ ### 📊 Database Integration (Server Mode)
267
337
 
268
- Clovie supports asynchronous data loading for dynamic content:
338
+ Clovie includes built-in SQLite database support for server applications:
269
339
 
270
340
  ```javascript
271
- // clovie.config.js
272
341
  export default {
273
- // ... other config
274
- data: async () => {
275
- // Fetch data from API
276
- const response = await fetch('https://api.example.com/posts');
277
- const posts = await response.json();
278
-
279
- return {
280
- title: 'My Blog',
281
- posts: posts,
282
- timestamp: new Date().toISOString()
283
- };
284
- }
342
+ type: 'server',
343
+ dbPath: './data/app.db', // SQLite database path
344
+
345
+ // Database is available in API actions and routes
346
+ api: [{
347
+ path: '/api/posts',
348
+ method: 'GET',
349
+ action: async (state, event) => {
350
+ // Access database through state.db
351
+ const posts = await state.db.query('SELECT * FROM posts ORDER BY created_at DESC');
352
+ return { posts };
353
+ }
354
+ }]
285
355
  };
286
356
  ```
287
357
 
288
- ### Dynamic Routes & Data-Driven Pages
358
+ ### 🔄 Async Data Loading
289
359
 
290
- Create multiple pages from data arrays using the routes system:
360
+ Load data dynamically at build time or runtime:
291
361
 
292
362
  ```javascript
293
- // clovie.config.js
294
363
  export default {
295
- // ... other config
296
- data: {
297
- title: 'My Blog',
298
- posts: [
299
- { id: 1, title: 'First Post', content: 'Hello World', slug: 'first-post' },
300
- { id: 2, title: 'Second Post', content: 'Another post', slug: 'second-post' },
301
- { id: 3, title: 'Third Post', content: 'Yet another', slug: 'third-post' }
302
- ]
364
+ // Static: Load data at build time
365
+ data: async () => {
366
+ const posts = await fetch('https://api.example.com/posts').then(r => r.json());
367
+ const authors = await loadAuthorsFromFile('./data/authors.json');
368
+
369
+ return {
370
+ site: { title: 'My Blog' },
371
+ posts,
372
+ authors,
373
+ buildTime: new Date().toISOString()
374
+ };
303
375
  },
376
+
377
+ // Server: Load data per request
304
378
  routes: [{
305
- name: 'Blog Posts',
306
379
  path: '/posts/:slug',
307
380
  template: 'post.html',
308
- repeat: (state) => state.get(['posts']),
309
- data: (state, post) => ({
310
- ...post,
311
- excerpt: post.content.substring(0, 100) + '...',
312
- date: new Date().toISOString()
313
- })
381
+ data: async (state, params) => {
382
+ const post = await fetchPostBySlug(params.slug);
383
+ const comments = await fetchComments(post.id);
384
+ return { post, comments };
385
+ }
314
386
  }]
315
387
  };
316
388
  ```
317
389
 
318
- **Template (`post.html`):**
319
- ```html
320
- <!DOCTYPE html>
321
- <html>
322
- <head>
323
- <title>{{title}} - {{../title}}</title>
324
- </head>
325
- <body>
326
- <article>
327
- <h1>{{title}}</h1>
328
- <p>{{excerpt}}</p>
329
- <div>{{content}}</div>
330
- </article>
331
- </body>
332
- </html>
333
- ```
390
+ ### 🎯 Dynamic Route Generation
391
+
392
+ Generate pages from data with powerful routing:
334
393
 
335
- **Output:**
336
- - `posts/first-post.html` - First post page
337
- - `posts/second-post.html` - Second post page
338
- - `posts/third-post.html` - Third post page
394
+ ```javascript
395
+ export default {
396
+ data: {
397
+ posts: [
398
+ { id: 1, title: 'Getting Started', slug: 'getting-started', category: 'tutorial' },
399
+ { id: 2, title: 'Advanced Usage', slug: 'advanced-usage', category: 'guide' }
400
+ ],
401
+ categories: ['tutorial', 'guide', 'news']
402
+ },
403
+
404
+ routes: [
405
+ // Individual post pages
406
+ {
407
+ name: 'Blog Posts',
408
+ path: '/posts/:slug',
409
+ template: 'post.html',
410
+ repeat: (data) => data.posts,
411
+ data: (globalData, post) => ({ ...globalData, post })
412
+ },
413
+
414
+ // Category pages
415
+ {
416
+ name: 'Category Pages',
417
+ path: '/category/:category',
418
+ template: 'category.html',
419
+ repeat: (data) => data.categories,
420
+ data: (globalData, category) => ({
421
+ ...globalData,
422
+ category,
423
+ posts: globalData.posts.filter(p => p.category === category)
424
+ })
425
+ }
426
+ ]
427
+ };
428
+ ```
339
429
 
340
- ### Custom Template Engines
430
+ ### 🎨 Template Engine Support
341
431
 
342
- Clovie is template-engine agnostic. Here are examples for popular engines:
432
+ Use any template engine or create custom ones:
343
433
 
344
- #### Handlebars
345
434
  ```javascript
435
+ // Handlebars
346
436
  import Handlebars from 'handlebars';
347
-
348
437
  export default {
349
- // ... other config
350
- compiler: (template, data) => {
438
+ renderEngine: (template, data) => {
351
439
  const compiled = Handlebars.compile(template);
352
440
  return compiled(data);
353
441
  }
354
442
  };
355
- ```
356
443
 
357
- #### Nunjucks
358
- ```javascript
444
+ // Nunjucks
359
445
  import nunjucks from 'nunjucks';
360
-
361
446
  export default {
362
- // ... other config
363
- compiler: (template, data) => {
447
+ renderEngine: (template, data) => {
364
448
  return nunjucks.renderString(template, data);
365
449
  }
366
450
  };
367
- ```
368
-
369
- #### Pug
370
- ```javascript
371
- import pug from 'pug';
372
451
 
452
+ // Custom engine
373
453
  export default {
374
- // ... other config
375
- compiler: (template, data) => {
376
- return pug.render(template, { ...data, pretty: true });
377
- }
378
- };
379
- ```
380
-
381
- #### Custom Engine
382
- ```javascript
383
- export default {
384
- // ... other config
385
- compiler: (template, data) => {
386
- // Simple variable replacement
454
+ renderEngine: (template, data) => {
387
455
  return template.replace(/\{\{(\w+)\}\}/g, (match, key) => {
388
456
  return data[key] || match;
389
457
  });
@@ -391,185 +459,183 @@ export default {
391
459
  };
392
460
  ```
393
461
 
394
- ### Route Pagination
462
+ ### 🛠️ CLI Commands
395
463
 
396
- Routes support built-in pagination for large datasets:
464
+ Clovie includes powerful CLI tools for development and deployment:
397
465
 
398
- ```javascript
399
- export default {
400
- // ... other config
401
- routes: [{
402
- name: 'Blog Pagination',
403
- path: '/blog/:page?',
404
- template: 'blog.html',
405
- paginate: 5, // 5 posts per page
406
- repeat: (state) => state.get(['posts']),
407
- data: (state, posts, pageInfo) => ({
408
- posts,
409
- pagination: pageInfo,
410
- title: `Blog - Page ${pageInfo.current}`
411
- })
412
- }]
413
- };
414
- ```
415
-
416
- **Output:**
417
- - `blog.html` - First 5 posts (page 1)
418
- - `blog/2.html` - Next 5 posts (page 2)
419
- - `blog/3.html` - Remaining posts (page 3)
466
+ ```bash
467
+ # Project creation
468
+ clovie create <name> [--template static|server|default]
420
469
 
421
- ### Data Transformation in Routes
470
+ # Development
471
+ clovie dev # Start development server with live reload
472
+ clovie watch # Alias for dev
422
473
 
423
- Transform data before rendering using the `data` function:
474
+ # Building
475
+ clovie build # Build for production
476
+ clovie serve # Start production server
424
477
 
425
- ```javascript
426
- export default {
427
- // ... other config
428
- routes: [{
429
- name: 'Products',
430
- path: '/products/:slug',
431
- template: 'product.html',
432
- repeat: (state) => state.get(['products']),
433
- data: (state, product) => ({
434
- ...product,
435
- price: `$${product.price.toFixed(2)}`,
436
- slug: product.name.toLowerCase().replace(/\s+/g, '-'),
437
- inStock: product.quantity > 0,
438
- relatedProducts: state.get(['products']).filter(p =>
439
- p.category === product.category && p.id !== product.id
440
- )
441
- })
442
- }]
443
- };
478
+ # Utilities
479
+ clovie kill --port 3000 # Kill process on port 3000
480
+ clovie kill --common # Kill processes on common dev ports
481
+ clovie kill --check # Check which ports are in use
444
482
  ```
445
483
 
446
- ## Error Handling & Best Practices
447
-
448
- ### Error Handling
449
-
450
- Clovie includes robust error handling for common issues:
484
+ ### 📁 Project Structure
451
485
 
452
- - **Missing directories**: Gracefully handles missing views, scripts, or assets folders
453
- - **File read errors**: Continues processing even if individual files fail
454
- - **Template errors**: Provides clear error messages for compilation failures
455
- - **Data validation**: Warns about invalid data structures
456
-
457
- ### Progress Indicators
458
-
459
- Clovie provides clear feedback during builds:
486
+ When you create a new project, you get a clean, organized structure:
460
487
 
461
488
  ```
462
- 🚀 Starting build...
463
- 🧹 Cleaning output directory...
464
- 📊 Loading data...
465
- Loaded 2 data sources
466
- 📝 Processing views...
467
- Processed 5 views
468
- 🎨 Rendering templates...
469
- Rendered 5 templates
470
- Bundling scripts...
471
- Bundled 1 script files
472
- 🎨 Compiling styles...
473
- Compiled 1 style files
474
- 📦 Processing assets...
475
- Processed 3 asset files
476
- 💾 Writing files...
477
- Build completed in 45ms
489
+ my-site/
490
+ ├── clovie.config.js # Configuration file
491
+ ├── package.json # Dependencies and scripts
492
+ ├── views/ # HTML templates
493
+ │ ├── index.html # Homepage
494
+ └── about.html # Additional pages
495
+ ├── partials/ # Reusable components (optional)
496
+ ├── header.html # Site header
497
+ │ └── footer.html # Site footer
498
+ ├── scripts/ # JavaScript
499
+ │ └── main.js # Main JS entry point
500
+ ├── styles/ # SCSS/CSS
501
+ │ └── main.scss # Main stylesheet
502
+ ├── assets/ # Static files
503
+ │ └── images/ # Images, fonts, etc.
504
+ └── dist/ # Build output (generated)
478
505
  ```
479
506
 
480
- ### Auto-Discovery
507
+ ### 🚀 Performance Features
481
508
 
482
- Clovie automatically detects common project structures:
509
+ - **⚡ Incremental Builds**: Only rebuilds changed files
510
+ - **📦 Smart Caching**: Content-based cache invalidation
511
+ - **🔄 Live Reload**: WebSocket-based for instant updates
512
+ - **📊 Progress Tracking**: Real-time build progress
513
+ - **🗜️ Asset Optimization**: Minification and optimization
514
+ - **🌐 Static + Server**: Best of both worlds
483
515
 
484
- ```
485
- 🔍 Auto-detected views directory: views
486
- 🔍 Auto-detected scripts entry: scripts/main.js
487
- 🔍 Auto-detected styles entry: styles/main.scss
488
- 🔍 Auto-detected assets directory: assets
489
- ```
516
+ ## 💡 Best Practices & Tips
490
517
 
491
- ### Best Practices
518
+ ### 🎯 Development Best Practices
492
519
 
493
- 1. **Use partial templates** (files starting with `_`) for reusable components
494
- 2. **Validate data structures** before passing to routes
495
- 3. **Handle async data** with proper error catching in route data functions
496
- 4. **Use meaningful route paths** for SEO and organization
497
- 5. **Transform data** in route data functions, not in templates
498
- 6. **Separate static and dynamic routes** for better performance
520
+ **Static Sites:**
521
+ - Use `partials/` for reusable components (header, footer, nav)
522
+ - Organize data in the config file or external JSON files
523
+ - Use semantic HTML and meaningful route paths for SEO
524
+ - Test builds regularly with `npm run build`
499
525
 
500
- ### Project Structure
526
+ **Server Applications:**
527
+ - Validate input data in API actions
528
+ - Use middleware for authentication and request parsing
529
+ - Handle errors gracefully in API endpoints
530
+ - Implement proper database migrations and seeding
501
531
 
502
- When you create a new project with `clovie create`, you get this structure:
532
+ ### 🔧 Configuration Tips
503
533
 
504
- ```
505
- my-site/
506
- ├── clovie.config.js # Configuration
507
- ├── package.json # Dependencies and scripts
508
- ├── README.md # Project documentation
509
- ├── views/ # HTML templates
510
- │ └── index.html # Home page template
511
- ├── scripts/ # JavaScript
512
- │ └── main.js # Main script file
513
- ├── styles/ # SCSS
514
- │ └── main.scss # Main stylesheet
515
- └── assets/ # Static files (images, etc.)
534
+ ```javascript
535
+ export default {
536
+ // Environment-specific config
537
+ ...(process.env.NODE_ENV === 'production' && {
538
+ baseUrl: 'https://mysite.com',
539
+ minify: true
540
+ }),
541
+
542
+ // Async data with error handling
543
+ data: async () => {
544
+ try {
545
+ const posts = await fetchPosts();
546
+ return { posts, lastUpdated: Date.now() };
547
+ } catch (error) {
548
+ console.warn('Failed to fetch posts:', error);
549
+ return { posts: [], lastUpdated: Date.now() };
550
+ }
551
+ }
552
+ };
516
553
  ```
517
554
 
518
- #### Custom Project Structure
519
- You can also create your own structure:
555
+ ### 📊 Performance Optimization
520
556
 
521
- ```
522
- my-site/
523
- ├── clovie.config.js # Configuration
524
- ├── views/ # Templates
525
- │ ├── _base.html # Base template (partial)
526
- │ ├── _header.html # Header partial
527
- │ ├── index.html # Home page
528
- │ └── _post.html # Post template (partial)
529
- ├── scripts/ # JavaScript
530
- │ └── main.js
531
- ├── styles/ # SCSS
532
- │ └── main.scss
533
- ├── assets/ # Static files
534
- │ └── images/
535
- └── data/ # Data files (optional)
536
- └── posts.json
557
+ - **Use incremental builds**: Clovie's caching handles this automatically
558
+ - **Optimize images**: Place optimized images in `assets/`
559
+ - **Minimize JavaScript**: Use esbuild's built-in minification
560
+ - **Cache API responses**: Implement caching in server mode API actions
561
+ - **Static generation**: Use static mode for content that doesn't change often
562
+
563
+ ### 🔄 Development Workflow
564
+
565
+ ```bash
566
+ # Recommended development flow
567
+ npm run dev # Start with live reload
568
+ # Edit files and see changes instantly
569
+ npm run build # Test production build
570
+ npm run serve # Test production serving (server mode)
537
571
  ```
538
572
 
539
- ## Development
573
+ ## 🛠️ Development & Contributing
540
574
 
541
575
  ```bash
576
+ # Clone repository
577
+ git clone https://github.com/adrianjonmiller/clovie.git
578
+ cd clovie
579
+
542
580
  # Install dependencies
543
581
  npm install
544
582
 
545
- # Run tests
583
+ # Run tests
546
584
  npm test
585
+ npm run test:watch # Watch mode
586
+ npm run test:coverage # Coverage report
547
587
 
548
- # Run tests in watch mode
549
- npm run test:watch
588
+ # Build package
589
+ npm run build
590
+
591
+ # Test with example projects
592
+ npm run dev # Uses __dev__ example
550
593
  ```
551
594
 
552
- ## Troubleshooting
595
+ ## 🐛 Troubleshooting
553
596
 
554
597
  ### Common Issues
555
598
 
556
- **"Views directory does not exist"**
557
- - Ensure the `views` path in your config is correct
558
- - Create the views directory if it doesn't exist
599
+ **Port Already in Use**
600
+ ```bash
601
+ clovie kill --port 3000 # Kill specific port
602
+ clovie kill --common # Kill common dev ports
603
+ clovie kill --check # Check port status
604
+ ```
605
+
606
+ **Build Errors**
607
+ - Check that all file paths in config exist
608
+ - Verify template syntax matches your render engine
609
+ - Ensure async data functions handle errors properly
610
+ - Check console output for detailed error messages
611
+
612
+ **Template Not Found**
613
+ - Verify the `views` directory path in your config
614
+ - Check that template files have correct extensions
615
+ - Ensure partial files are in the `partials` directory
616
+
617
+ **Database Connection Issues (Server Mode)**
618
+ - Check that `dbPath` in config points to a writable directory
619
+ - Ensure SQLite is properly installed
620
+ - Verify database initialization in your API actions
621
+
622
+ **Live Reload Not Working**
623
+ - Check that you're in development mode (`npm run dev`)
624
+ - Verify WebSocket connection in browser dev tools
625
+ - Try refreshing the page manually
626
+
627
+ ### Getting Help
628
+
629
+ - 📚 [Documentation](https://github.com/adrianjonmiller/clovie)
630
+ - 🐛 [Issue Tracker](https://github.com/adrianjonmiller/clovie/issues)
631
+ - 💬 [Discussions](https://github.com/adrianjonmiller/clovie/discussions)
559
632
 
560
- **"Route repeat function must return an array"**
561
- - Check that your route's repeat function returns an array
562
- - Ensure the data structure matches the route configuration
633
+ ## 📄 License
563
634
 
564
- **"Maximum directory depth exceeded"**
565
- - Check for circular symlinks or extremely deep directory structures
566
- - The limit is 50 levels deep (configurable in code)
635
+ MIT - see [LICENSE](LICENSE) file for details.
567
636
 
568
- **Build failures**
569
- - Check console output for specific error messages
570
- - Verify all referenced files exist
571
- - Ensure template syntax matches your compiler
637
+ ---
572
638
 
573
- ## License
639
+ **Built with ❤️ by [Adrian Miller](https://github.com/adrianjonmiller)**
574
640
 
575
- MIT
641
+ *Clovie: Vintage web dev tooling with modern quality of life.*