@reldens/cms 0.20.0 → 0.23.0

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 (67) hide show
  1. package/README.md +648 -12
  2. package/admin/reldens-admin-client.css +77 -141
  3. package/admin/reldens-admin-client.js +108 -133
  4. package/admin/templates/clear-all-cache-button.html +7 -7
  5. package/admin/templates/edit.html +7 -0
  6. package/admin/templates/fields/view/audio.html +7 -0
  7. package/admin/templates/fields/view/audios.html +8 -0
  8. package/admin/templates/layout.html +15 -9
  9. package/admin/templates/list-content.html +4 -2
  10. package/admin/templates/list.html +24 -8
  11. package/admin/templates/view.html +21 -0
  12. package/install/index.html +4 -0
  13. package/lib/admin-manager/admin-filters-manager.js +177 -0
  14. package/lib/admin-manager/contents-builder.js +1 -0
  15. package/lib/admin-manager/default-translations.js +38 -0
  16. package/lib/admin-manager/router-contents.js +64 -52
  17. package/lib/admin-manager/router.js +19 -0
  18. package/lib/dynamic-form-renderer.js +228 -0
  19. package/lib/dynamic-form-request-handler.js +135 -0
  20. package/lib/dynamic-form.js +310 -0
  21. package/lib/frontend/content-renderer.js +178 -0
  22. package/lib/frontend/entity-access-manager.js +63 -0
  23. package/lib/frontend/request-processor.js +128 -0
  24. package/lib/frontend/response-manager.js +54 -0
  25. package/lib/frontend/template-cache.js +102 -0
  26. package/lib/frontend/template-resolver.js +111 -0
  27. package/lib/frontend.js +122 -629
  28. package/lib/installer.js +2 -1
  29. package/lib/manager.js +25 -12
  30. package/lib/search-renderer.js +15 -7
  31. package/lib/search-request-handler.js +67 -0
  32. package/lib/search.js +13 -1
  33. package/lib/template-engine/collections-single-transformer.js +11 -5
  34. package/lib/template-engine/collections-transformer.js +47 -34
  35. package/lib/template-engine/entities-transformer.js +3 -2
  36. package/lib/template-engine/forms-transformer.js +187 -0
  37. package/lib/template-engine/partials-transformer.js +5 -6
  38. package/lib/template-engine/system-variables-provider.js +4 -1
  39. package/lib/template-engine.js +28 -5
  40. package/lib/template-reloader.js +307 -0
  41. package/lib/templates-list.js +2 -0
  42. package/migrations/default-forms.sql +22 -0
  43. package/package.json +5 -5
  44. package/templates/{browserconfig.xml → assets/favicons/default/browserconfig.xml} +1 -1
  45. package/templates/assets/favicons/default/favicon.ico +0 -0
  46. package/templates/{site.webmanifest → assets/favicons/default/site.webmanifest} +3 -3
  47. package/templates/cms_forms/field_email.html +14 -0
  48. package/templates/cms_forms/field_number.html +17 -0
  49. package/templates/cms_forms/field_select.html +15 -0
  50. package/templates/cms_forms/field_text.html +16 -0
  51. package/templates/cms_forms/field_textarea.html +13 -0
  52. package/templates/cms_forms/form.html +22 -0
  53. package/templates/css/styles.css +4 -0
  54. package/templates/js/functions.js +144 -0
  55. package/templates/js/scripts.js +5 -0
  56. package/templates/page.html +11 -5
  57. package/templates/partials/pagedCollection.html +1 -1
  58. package/lib/admin-translations.js +0 -56
  59. package/templates/favicon.ico +0 -0
  60. /package/templates/assets/favicons/{android-icon-144x144.png → default/android-icon-144x144.png} +0 -0
  61. /package/templates/assets/favicons/{android-icon-192x192.png → default/android-icon-192x192.png} +0 -0
  62. /package/templates/assets/favicons/{android-icon-512x512.png → default/android-icon-512x512.png} +0 -0
  63. /package/templates/assets/favicons/{apple-touch-icon.png → default/apple-touch-icon.png} +0 -0
  64. /package/templates/assets/favicons/{favicon-16x16.png → default/favicon-16x16.png} +0 -0
  65. /package/templates/assets/favicons/{favicon-32x32.png → default/favicon-32x32.png} +0 -0
  66. /package/templates/assets/favicons/{mstile-150x150.png → default/mstile-150x150.png} +0 -0
  67. /package/templates/assets/favicons/{safari-pinned-tab.svg → default/safari-pinned-tab.svg} +0 -0
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  # Reldens CMS
4
4
 
5
- A powerful, flexible Content Management System built with Node.js, featuring an admin panel, multi-domain frontend support, enhanced templating with reusable content blocks, system variables, internationalization, and automated installation.
5
+ A powerful, flexible Content Management System built with Node.js, featuring an admin panel, multi-domain frontend support, enhanced templating with reusable content blocks, system variables, internationalization, template reloading, dynamic forms, and automated installation.
6
6
 
7
7
  ## Features
8
8
 
@@ -29,6 +29,9 @@ A powerful, flexible Content Management System built with Node.js, featuring an
29
29
  - **Template functions** for URLs, assets, dates, and translations
30
30
  - **Event-driven rendering** with hooks for customization
31
31
  - **Custom 404 handling**
32
+ - **Advanced search functionality** with template data support
33
+ - **Dynamic forms system** with template transformers and security features
34
+ - **Template reloading** for development with configurable reload strategies
32
35
 
33
36
  ### - Admin Panel
34
37
  - **Full CRUD operations** for all entities including content blocks
@@ -47,15 +50,56 @@ A powerful, flexible Content Management System built with Node.js, featuring an
47
50
  - **Translation support** for entity labels and properties
48
51
  - **Content blocks management** via cms_blocks table
49
52
  - **Entity access control** via entities_access table
53
+ - **Dynamic forms storage** via cms_forms and cms_forms_submitted tables
50
54
 
51
55
  ### - Configuration & Architecture
52
56
  - **Environment-based configuration** (.env file)
53
- - **Modular service architecture** (Frontend, AdminManager, DataServer, TemplateEngine)
57
+ - **Modular service architecture** with specialized classes for better maintainability
54
58
  - **Event-driven system** with hooks for customization
55
59
  - **Extensible authentication** (database users or custom callbacks)
56
60
  - **File security** with path validation and dangerous key filtering
57
61
  - **Internationalization support** with translation files
58
62
 
63
+ ## Architecture
64
+
65
+ ### Core Classes
66
+ The CMS uses a modular architecture with specialized classes:
67
+
68
+ **Frontend Orchestrator:**
69
+ - `Frontend` - Main orchestrator class that coordinates all frontend operations
70
+
71
+ **Template Management:**
72
+ - `TemplateResolver` - Template discovery and domain resolution
73
+ - `TemplateCache` - Template and partial caching management
74
+ - `TemplateReloader` - Template reloading with file change detection
75
+
76
+ **Request Processing:**
77
+ - `RequestProcessor` - HTTP request routing and path handling
78
+ - `SearchRequestHandler` - Dedicated search request processing
79
+ - `DynamicFormRequestHandler` - Form submission processing
80
+
81
+ **Content Management:**
82
+ - `ContentRenderer` - Content generation and template processing
83
+ - `EntityAccessManager` - Entity access control and loading
84
+
85
+ **Response Handling:**
86
+ - `ResponseManager` - HTTP response handling and caching logic
87
+
88
+ **Template Processing:**
89
+ - `TemplateEngine` - Core template rendering with enhanced context
90
+ - `SystemVariablesProvider` - System variables for templates
91
+ - `FormsTransformer` - Dynamic forms template transformer
92
+
93
+ **Forms System:**
94
+ - `DynamicForm` - Form validation and data processing
95
+ - `DynamicFormRenderer` - Template-based form rendering
96
+
97
+ This architecture follows SOLID principles, providing better:
98
+ - **Testability** - Individual components can be tested in isolation
99
+ - **Maintainability** - Changes to one area don't affect others
100
+ - **Reusability** - Components can be reused in different contexts
101
+ - **Readability** - Smaller, focused classes are easier to understand
102
+
59
103
  ## Installation
60
104
 
61
105
  ### Method 1: Automated Web Installer
@@ -102,6 +146,34 @@ RELDENS_DOMAIN_MAPPING={"dev.example.com":"development"}
102
146
  RELDENS_SITE_KEY_MAPPING={"example.com":"main"}
103
147
  ```
104
148
 
149
+ ### Template Reloading Configuration
150
+ Configure template reloading for development environments:
151
+
152
+ ```javascript
153
+ const cms = new Manager({
154
+ // Development: reload templates on every request when changes detected
155
+ reloadTime: -1,
156
+
157
+ // Production: disable template reloading (default)
158
+ reloadTime: 0,
159
+
160
+ // Interval-based: reload every 5 seconds when changes detected
161
+ reloadTime: 5000
162
+ });
163
+ ```
164
+
165
+ **Template Reloading Options:**
166
+ - **`reloadTime: 0`** (default) - Template reloading disabled. Templates load once at startup.
167
+ - **`reloadTime: -1`** - Reload templates on every request when file changes are detected. Best for active development.
168
+ - **`reloadTime: > 0`** - Check for template changes at specified interval (milliseconds) and reload when needed. Good for development with lower overhead.
169
+
170
+ **How it works:**
171
+ - Tracks file modification times for admin and frontend templates
172
+ - Only reloads templates that have actually changed
173
+ - Automatically updates admin contents and frontend template cache
174
+ - Works with both admin panel templates and frontend templates/partials
175
+ - Zero performance impact when disabled (`reloadTime: 0`)
176
+
105
177
  ### Custom Entity Configuration
106
178
  ```javascript
107
179
  const entityConfig = {
@@ -131,6 +203,413 @@ const cms = new Manager({
131
203
  });
132
204
  ```
133
205
 
206
+ ## Dynamic Forms System
207
+
208
+ ### Basic Form Usage
209
+ Create forms in your templates using the `<cmsForm>` tag:
210
+
211
+ ```html
212
+ <!-- Render all form fields -->
213
+ <cmsForm key="contactForm"/>
214
+
215
+ <!-- Render specific fields only -->
216
+ <cmsForm key="contactForm" fields="name,email,subject,message"/>
217
+
218
+ <!-- Custom form attributes -->
219
+ <cmsForm key="newsletterSignup"
220
+ fields="email,name"
221
+ submitButtonText="Subscribe Now"
222
+ cssClass="newsletter-form"
223
+ successRedirect="/thank-you"
224
+ errorRedirect="/contact-error"/>
225
+ ```
226
+
227
+ ### Form Configuration in Database
228
+ Forms are configured in the `cms_forms` table via the admin panel:
229
+
230
+ ```sql
231
+ -- Example form configuration
232
+ INSERT INTO cms_forms (form_key, fields_schema, enabled) VALUES
233
+ ('contactForm', '[
234
+ {
235
+ "name": "name",
236
+ "type": "text",
237
+ "label": "Full Name",
238
+ "required": true,
239
+ "maxLength": 100,
240
+ "placeholder": "Enter your full name"
241
+ },
242
+ {
243
+ "name": "email",
244
+ "type": "email",
245
+ "label": "Email Address",
246
+ "required": true,
247
+ "placeholder": "your@email.com"
248
+ },
249
+ {
250
+ "name": "subject",
251
+ "type": "select",
252
+ "label": "Subject",
253
+ "required": true,
254
+ "options": [
255
+ {"value": "general", "label": "General Inquiry"},
256
+ {"value": "support", "label": "Technical Support"},
257
+ {"value": "sales", "label": "Sales Question"}
258
+ ]
259
+ },
260
+ {
261
+ "name": "message",
262
+ "type": "textarea",
263
+ "label": "Message",
264
+ "required": true,
265
+ "maxLength": 1000,
266
+ "placeholder": "Enter your message here..."
267
+ }
268
+ ]', 1);
269
+ ```
270
+
271
+ ### Supported Field Types
272
+ The forms system supports various field types with validation:
273
+
274
+ - **text** - Basic text input with maxLength, pattern validation
275
+ - **email** - Email input with built-in email validation
276
+ - **number** - Numeric input with min/max validation
277
+ - **textarea** - Multi-line text with maxLength
278
+ - **select** - Dropdown with options array
279
+ - **password** - Password input (masked)
280
+ - **tel** - Phone number input
281
+ - **url** - URL input with validation
282
+ - **date** - Date picker input
283
+
284
+ ### Field Schema Properties
285
+ Each field in the `fields_schema` JSON supports:
286
+
287
+ ```json
288
+ {
289
+ "name": "fieldName", // Required: Field identifier
290
+ "type": "text", // Required: Field type
291
+ "label": "Field Label", // Display label
292
+ "required": true, // Validation: required field
293
+ "placeholder": "Enter text...", // Input placeholder
294
+ "helpText": "Additional help", // Help text below field
295
+ "maxLength": 100, // String length limit
296
+ "minLength": 3, // Minimum string length
297
+ "pattern": "^[A-Za-z]+$", // Regex validation pattern
298
+ "min": 0, // Number minimum value
299
+ "max": 100, // Number maximum value
300
+ "step": 1, // Number step increment
301
+ "defaultValue": "default", // Default field value
302
+ "options": [ // Select/radio options
303
+ {"value": "val1", "label": "Option 1"},
304
+ {"value": "val2", "label": "Option 2"}
305
+ ]
306
+ }
307
+ ```
308
+
309
+ ### Security Features
310
+ The form system includes comprehensive security measures:
311
+
312
+ #### 1. Honeypot Protection
313
+ Automatic bot detection using invisible fields:
314
+ ```html
315
+ <!-- Automatically added to all forms -->
316
+ <div class="hidden">
317
+ <input type="text" name="website_url" value="" />
318
+ </div>
319
+ ```
320
+
321
+ #### 2. Server-Side Validation
322
+ - **SchemaValidator integration** - Uses `@reldens/utils` SchemaValidator
323
+ - **Required field validation** - Ensures all required fields are provided
324
+ - **Type validation** - Email, number, string validation with patterns
325
+ - **Length limits** - Configurable per field via schema
326
+ - **Custom validation** - Extensible validation rules
327
+
328
+ #### 3. Data Sanitization
329
+ - **XSS protection** - Handled by `@reldens/server-utils` SecurityConfigurer
330
+ - **Input normalization** - Type-specific data processing
331
+ - **Length truncation** - Based on field schema maxLength
332
+
333
+ #### 4. Rate Limiting
334
+ - **AppServerFactory integration** - Uses existing rate limiting from server-utils
335
+ - **No duplicate implementation** - Leverages proven security measures
336
+
337
+ ### Template Customization
338
+ Forms use a domain-aware template fallback system:
339
+
340
+ ```
341
+ templates/
342
+ ├── domains/
343
+ │ └── example.com/
344
+ │ └── cms_forms/
345
+ │ ├── form.html # Domain-specific form wrapper
346
+ │ ├── field_text.html # Domain-specific text field
347
+ │ └── field_email.html # Domain-specific email field
348
+ └── cms_forms/ # Default templates
349
+ ├── form.html # Main form wrapper
350
+ ├── field_text.html # Text input template
351
+ ├── field_email.html # Email input template
352
+ ├── field_textarea.html # Textarea template
353
+ ├── field_select.html # Select dropdown template
354
+ └── field_number.html # Number input template
355
+ ```
356
+
357
+ ### Custom Field Templates
358
+ Create custom field templates for specific types:
359
+
360
+ **templates/cms_forms/field_text.html:**
361
+ ```html
362
+ <div class="form-field {{errorClass}} {{requiredClass}}">
363
+ <label for="{{fieldName}}" class="form-label">
364
+ {{fieldLabel}}{{#isRequired}} <span class="required-indicator">*</span>{{/isRequired}}
365
+ </label>
366
+ <input type="{{fieldType}}"
367
+ name="submittedValues[{{fieldName}}]"
368
+ id="{{fieldName}}"
369
+ value="{{fieldValue}}"
370
+ class="form-control {{#hasError}}is-invalid{{/hasError}}"
371
+ {{#isRequired}}required{{/isRequired}}
372
+ {{#placeholder}}placeholder="{{placeholder}}"{{/placeholder}}
373
+ {{#maxLength}}maxlength="{{maxLength}}"{{/maxLength}}
374
+ {{#pattern}}pattern="{{pattern}}"{{/pattern}} />
375
+ {{#helpText}}<div class="form-text">{{helpText}}</div>{{/helpText}}
376
+ {{#hasError}}<div class="invalid-feedback">{{fieldError}}</div>{{/hasError}}
377
+ </div>
378
+ ```
379
+
380
+ **templates/cms_forms/form.html:**
381
+ ```html
382
+ <form method="POST" action="{{submitUrl}}" class="{{cssClass}}">
383
+ <input type="hidden" name="formKey" value="{{formKey}}" />
384
+ <input type="hidden" name="successRedirect" value="{{successRedirect}}" />
385
+ <input type="hidden" name="errorRedirect" value="{{errorRedirect}}" />
386
+ <div class="hidden">
387
+ <input type="text" name="{{honeypotFieldName}}" value="" />
388
+ </div>
389
+ {{&formFields}}
390
+ <div class="form-submit">
391
+ <button type="submit" class="btn btn-primary">{{submitButtonText}}</button>
392
+ </div>
393
+ </form>
394
+ ```
395
+
396
+ ### Forms with System Variables
397
+ Forms can access system variables and enhanced data in templates:
398
+
399
+ ```html
400
+ <!-- Form with the current user context -->
401
+ <cmsForm key="userProfile" fields="name,email,bio"/>
402
+
403
+ <!-- In the form template, access system variables: -->
404
+ <form method="POST" action="{{submitUrl}}" class="{{cssClass}}">
405
+ <h2>Update Profile for {{currentRequest.host}}</h2>
406
+ <p>Current time: {{systemInfo.timestamp}}</p>
407
+ {{&formFields}}
408
+ <button type="submit">Update Profile</button>
409
+ </form>
410
+ ```
411
+
412
+ ### Event System Integration
413
+ The forms system provides comprehensive event hooks:
414
+
415
+ ```javascript
416
+ // Listen for form events
417
+ cms.events.on('reldens.formsTransformer.beforeRender', (eventData) => {
418
+ console.log('Rendering form:', eventData.formKey);
419
+ // Modify form attributes or fields before rendering
420
+ eventData.formAttributes.cssClass += ' custom-form';
421
+ });
422
+
423
+ cms.events.on('reldens.dynamicForm.beforeValidation', (eventData) => {
424
+ console.log('Validating form:', eventData.formKey);
425
+ // Add custom validation logic
426
+ });
427
+
428
+ cms.events.on('reldens.dynamicForm.afterSave', (eventData) => {
429
+ console.log('Form saved:', eventData.result.id);
430
+ // Send notifications, trigger workflows, etc.
431
+ });
432
+
433
+ cms.events.on('reldens.dynamicFormRequestHandler.beforeSave', (eventData) => {
434
+ // Modify prepared values before saving
435
+ eventData.preparedValues.submissionDate = new Date().toISOString();
436
+ });
437
+ ```
438
+
439
+ ### Available Form Events
440
+ - `reldens.formsTransformer.beforeRender` - Before form rendering
441
+ - `reldens.formsTransformer.afterRender` - After form rendering
442
+ - `reldens.dynamicForm.beforeValidation` - Before form validation
443
+ - `reldens.dynamicForm.afterValidation` - After form validation
444
+ - `reldens.dynamicForm.beforeSave` - Before saving to the database
445
+ - `reldens.dynamicForm.afterSave` - After successful save
446
+ - `reldens.dynamicFormRenderer.beforeFieldsRender` - Before rendering fields
447
+ - `reldens.dynamicFormRenderer.afterFieldsRender` - After rendering fields
448
+ - `reldens.dynamicFormRequestHandler.beforeValidation` - Before request validation
449
+ - `reldens.dynamicFormRequestHandler.beforeSave` - Before save process
450
+ - `reldens.dynamicFormRequestHandler.afterSave` - After successful save
451
+
452
+ ### Database Tables
453
+ The forms system uses two main tables:
454
+
455
+ #### cms_forms Table
456
+ Store form configurations:
457
+ ```sql
458
+ CREATE TABLE `cms_forms` (
459
+ `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
460
+ `form_key` VARCHAR(255) NOT NULL UNIQUE,
461
+ `fields_schema` JSON NOT NULL,
462
+ `enabled` TINYINT UNSIGNED NOT NULL DEFAULT '0',
463
+ `created_at` TIMESTAMP NOT NULL DEFAULT (NOW()),
464
+ `updated_at` TIMESTAMP NOT NULL DEFAULT (NOW()) ON UPDATE CURRENT_TIMESTAMP,
465
+ PRIMARY KEY (`id`)
466
+ );
467
+ ```
468
+
469
+ #### cms_forms_submitted Table
470
+ Store form submissions:
471
+ ```sql
472
+ CREATE TABLE `cms_forms_submitted` (
473
+ `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
474
+ `form_id` INT UNSIGNED NOT NULL,
475
+ `submitted_values` JSON NOT NULL,
476
+ `created_at` TIMESTAMP NOT NULL DEFAULT (NOW()),
477
+ PRIMARY KEY (`id`),
478
+ FOREIGN KEY (`form_id`) REFERENCES `cms_forms`(`id`)
479
+ );
480
+ ```
481
+
482
+ ### Form Processing Flow
483
+ 1. **Template Processing** - `FormsTransformer` finds `<cmsForm>` tags
484
+ 2. **Form Loading** - Loads form configuration from database
485
+ 3. **Field Filtering** - Applies field filter if specified
486
+ 4. **Template Rendering** - Renders form using domain-aware templates
487
+ 5. **Form Submission** - POST request to `/dynamic-form` endpoint
488
+ 6. **Validation** - Honeypot, required fields, and schema validation
489
+ 7. **Data Processing** - Input sanitization and normalization
490
+ 8. **Database Storage** - Save to `cms_forms_submitted` table
491
+ 9. **Response** - Redirect with success/error parameters
492
+
493
+ ### Advanced Form Usage
494
+
495
+ #### Multi-Step Forms
496
+ ```html
497
+ <!-- Step 1: Basic info -->
498
+ <cmsForm key="applicationForm" fields="name,email,phone"/>
499
+
500
+ <!-- Step 2: Details (separate form) -->
501
+ <cmsForm key="applicationDetails" fields="experience,portfolio"/>
502
+ ```
503
+
504
+ #### Conditional Field Display
505
+ Use JavaScript to show/hide fields based on selections:
506
+ ```html
507
+ <cmsForm key="surveyForm" fields="age,experience,expertise"/>
508
+
509
+ <script>
510
+ document.addEventListener('DOMContentLoaded', function() {
511
+ const ageField = document.getElementById('age');
512
+ const experienceField = document.getElementById('experience');
513
+
514
+ ageField.addEventListener('change', function() {
515
+ if(parseInt(this.value) >= 18) {
516
+ experienceField.parentElement.style.display = 'block';
517
+ return;
518
+ }
519
+ experienceField.parentElement.style.display = 'none';
520
+ });
521
+ });
522
+ </script>
523
+ ```
524
+
525
+ #### AJAX Form Submissions
526
+ Enable JSON responses for AJAX handling:
527
+ ```javascript
528
+ const cms = new Manager({
529
+ enableJsonResponse: true // Enable JSON responses for forms
530
+ });
531
+ ```
532
+
533
+ ```javascript
534
+ // Frontend AJAX handling
535
+ document.querySelector('.dynamic-form').addEventListener('submit', async function(e) {
536
+ e.preventDefault();
537
+
538
+ const response = await fetch('/dynamic-form', {method: 'POST', body: new FormData(this)});
539
+
540
+ const result = await response.json();
541
+ if(result.success) {
542
+ alert('Form submitted successfully!');
543
+ return;
544
+ }
545
+ alert('Error: ' + result.error);
546
+ });
547
+ ```
548
+
549
+ ## Search Functionality
550
+
551
+ ### Basic Search
552
+ ```bash
553
+ # Simple search
554
+ /search?search=technology
555
+
556
+ # Entity-specific search with custom limit
557
+ /search?search=javascript&limit=20
558
+
559
+ # Custom template rendering
560
+ /search?search=news&renderPartial=newsListView&renderLayout=minimal
561
+ ```
562
+
563
+ ### Advanced Search with Template Data
564
+ ```bash
565
+ # Pass custom template variables
566
+ /search?search=articles&templateData[columnsClass]=col-md-4&templateData[showExcerpt]=true
567
+
568
+ # Multiple template variables
569
+ /search?search=technology&templateData[columnsClass]=col-lg-6&templateData[cardClass]=shadow-sm&templateData[showAuthor]=false
570
+ ```
571
+
572
+ ### Search Template Variables
573
+ Templates receive dynamic data through URL parameters:
574
+
575
+ **URL:** `/search?search=tech&templateData[columnsClass]=col-md-6&templateData[showDate]=true`
576
+
577
+ **Template (entriesListView.html):**
578
+ ```html
579
+ <div class="{{columnsClass}}">
580
+ <div class="card">
581
+ <h3>{{row.title}}</h3>
582
+ <p>{{row.content}}</p>
583
+ {{#showDate}}
584
+ <span class="date">{{row.created_at}}</span>
585
+ {{/showDate}}
586
+ </div>
587
+ </div>
588
+ ```
589
+
590
+ **Default Values:**
591
+ - `columnsClass` defaults to `col-lg-6` if not provided or empty
592
+ - Custom variables can be added via `templateData[variableName]=value`
593
+
594
+ ### Search Configuration
595
+ ```javascript
596
+ // Custom search sets in Manager configuration
597
+ const searchSets = {
598
+ articlesSearch: {
599
+ entities: [{
600
+ name: 'articles',
601
+ fields: ['title', 'content', 'summary'],
602
+ relations: 'authors'
603
+ }],
604
+ pagination: {active: true, limit: 15, sortBy: 'created_at', sortDirection: 'desc'}
605
+ }
606
+ };
607
+
608
+ const cms = new Manager({
609
+ searchSets: searchSets
610
+ });
611
+ ```
612
+
134
613
  ## Enhanced Templating System
135
614
 
136
615
  ### System Variables
@@ -171,10 +650,10 @@ Templates support dynamic functions for common operations:
171
650
  <!-- URL generation with current domain -->
172
651
  [url(/articles)] <!-- https://example.com/articles -->
173
652
  [url(/contact#form)] <!-- https://example.com/contact#form -->
653
+ [url(/css/styles.css)] <!-- https://example.com/css/styles.css -->
174
654
 
175
655
  <!-- Asset URLs with domain -->
176
- [asset(/css/styles.css)] <!-- https://example.com/css/styles.css -->
177
- [asset(/images/logo.png)] <!-- https://example.com/images/logo.png -->
656
+ [asset(/assets/images/logo.png)] <!-- https://example.com/images/logo.png -->
178
657
 
179
658
  <!-- Date formatting -->
180
659
  [date()] <!-- Current date with default format -->
@@ -303,10 +782,10 @@ Pagination state is managed via URL query parameters:
303
782
  Create `templates/partials/pagedCollection.html`:
304
783
  ```html
305
784
  <div class="row paginated-contents">
306
- <div class="collection-content col-lg-12 mt-2 mb-2">
785
+ <div class="collection-content col-lg-12">
307
786
  {{&collectionContentForCurrentPage}}
308
787
  </div>
309
- <div class="pagination col-lg-12 mt-2 mb-2">
788
+ <div class="pagination col-lg-12">
310
789
  <ul class="pagination-list">
311
790
  {{#prevPageUrl}}
312
791
  <li><a href="{{prevPageUrl}}" class="page-link">{{&prevPageLabel}}</a></li>
@@ -497,11 +976,11 @@ The CMS uses a two-tier layout system:
497
976
  <head>
498
977
  <title>{{title}}</title>
499
978
  <meta name="description" content="{{description}}"/>
500
- <link href="[asset(/css/styles.css)]" rel="stylesheet"/>
979
+ <link href="[url(/css/styles.css)]" rel="stylesheet"/>
501
980
  </head>
502
981
  <body class="{{siteHandle}}">
503
982
  {{&content}}
504
- <script src="[asset(/js/scripts.js)]"></script>
983
+ <script src="[url(/js/scripts.js)]"></script>
505
984
  </body>
506
985
  </html>
507
986
  ```
@@ -528,7 +1007,7 @@ The CMS uses a two-tier layout system:
528
1007
 
529
1008
  Pages can use different layouts by setting the `layout` field in `cms_pages`:
530
1009
  - `default` - Header, sidebar, main content, footer
531
- - `full-width` - Full width without sidebars
1010
+ - `full-width` - Full width without sidebars
532
1011
  - `minimal` - Basic layout with minimal styling
533
1012
 
534
1013
  ### Content Blocks
@@ -567,6 +1046,9 @@ templates/
567
1046
  │ │ ├── partials/
568
1047
  │ │ │ ├── header.html
569
1048
  │ │ │ └── footer.html
1049
+ │ │ ├── cms_forms/ # Domain-specific form templates
1050
+ │ │ │ ├── form.html
1051
+ │ │ │ └── field_text.html
570
1052
  │ │ ├── page.html # Domain-specific page wrapper
571
1053
  │ │ └── index.html
572
1054
  │ └── dev.example.com/
@@ -574,6 +1056,10 @@ templates/
574
1056
  ├── partials/
575
1057
  │ ├── header.html (default)
576
1058
  │ └── footer.html (default)
1059
+ ├── cms_forms/ # Default form templates
1060
+ │ ├── form.html
1061
+ │ ├── field_text.html
1062
+ │ └── field_email.html
577
1063
  ├── translations/
578
1064
  │ ├── en.json
579
1065
  │ ├── es.json
@@ -584,6 +1070,32 @@ templates/
584
1070
 
585
1071
  ## Advanced Usage
586
1072
 
1073
+ ### Template Reloading for Development
1074
+ ```javascript
1075
+ // Different configurations for development vs production
1076
+ const isDevelopment = process.env.NODE_ENV === 'development';
1077
+
1078
+ const cms = new Manager({
1079
+ // Enable aggressive template reloading in development
1080
+ reloadTime: isDevelopment ? -1 : 0,
1081
+
1082
+ // Other development-friendly settings
1083
+ cache: !isDevelopment,
1084
+
1085
+ entityAccess: {
1086
+ articles: { public: true, operations: ['read'] },
1087
+ cmsPages: { public: true, operations: ['read'] }
1088
+ }
1089
+ });
1090
+ ```
1091
+
1092
+ **Development Workflow with Template Reloading:**
1093
+ 1. Set `reloadTime: -1` for instant template updates
1094
+ 2. Edit admin templates in `admin/templates/` - changes appear immediately
1095
+ 3. Edit frontend templates in `templates/` - changes appear on next page load
1096
+ 4. No server restart needed for template changes
1097
+ 5. Switch to `reloadTime: 0` in production for optimal performance
1098
+
587
1099
  ### Event System
588
1100
  The CMS provides hooks for customization through event listeners:
589
1101
 
@@ -607,6 +1119,17 @@ cms.events.on('reldens.afterContentProcess', (eventData) => {
607
1119
  // Modify processed content
608
1120
  eventData.processedContent += '\n<!-- Processed at ' + new Date() + ' -->';
609
1121
  });
1122
+
1123
+ // Listen for template reloading events
1124
+ cms.events.on('reldens.templateReloader.templatesChanged', (eventData) => {
1125
+ console.log('Templates changed:', eventData.changedFiles);
1126
+ });
1127
+
1128
+ // Listen for form events
1129
+ cms.events.on('reldens.dynamicForm.afterSave', (eventData) => {
1130
+ // Send email notifications, trigger workflows, etc.
1131
+ console.log('Form submission received:', eventData.result.id);
1132
+ });
610
1133
  ```
611
1134
 
612
1135
  ### Custom Authentication
@@ -663,6 +1186,10 @@ cms.events.on('adminEntityExtraData', ({entitySerializedData, entity}) => {
663
1186
  - `entities_meta` - Generic metadata storage
664
1187
  - `cms_pages_meta` - Page-specific metadata
665
1188
 
1189
+ ### Forms Tables
1190
+ - `cms_forms` - Form configurations with JSON schema
1191
+ - `cms_forms_submitted` - Form submissions with JSON data
1192
+
666
1193
  ### Installation Options
667
1194
  The installer provides checkboxes for:
668
1195
  - CMS core tables
@@ -671,6 +1198,7 @@ The installer provides checkboxes for:
671
1198
  - Default homepage
672
1199
  - Default content blocks
673
1200
  - Entity access control rules
1201
+ - Dynamic forms system
674
1202
 
675
1203
  ## API Reference
676
1204
 
@@ -679,11 +1207,58 @@ The installer provides checkboxes for:
679
1207
  - `isInstalled()` - Check if CMS is installed
680
1208
  - `initializeServices()` - Initialize all services
681
1209
 
682
- ### Frontend Class
1210
+ ### Frontend Architecture Classes
1211
+
1212
+ #### Frontend Class (Orchestrator)
683
1213
  - `initialize()` - Set up frontend routes and templates
684
1214
  - `handleRequest(req, res)` - Main request handler
685
- - `findRouteByPath(path)` - Database route lookup
686
- - `findEntityByPath(path)` - Entity-based URL handling
1215
+ - `renderRoute(route, domain, res, req)` - Route-based rendering
1216
+ - `setupStaticAssets()` - Configure static asset serving
1217
+
1218
+ #### TemplateResolver Class
1219
+ - `findTemplatePath(templateName, domain)` - Template discovery with domain fallback
1220
+ - `findLayoutPath(layoutName, domain)` - Layout path resolution
1221
+ - `findTemplateByPath(path, domain)` - Template lookup by URL path
1222
+ - `resolveDomainToFolder(domain)` - Domain to folder mapping
1223
+ - `resolveDomainToSiteKey(domain)` - Domain to site key mapping
1224
+
1225
+ #### TemplateCache Class
1226
+ - `loadPartials()` - Load and cache template partials
1227
+ - `setupDomainTemplates()` - Initialize domain-specific templates
1228
+ - `getPartialsForDomain(domain)` - Get domain-specific partials with fallback
1229
+
1230
+ #### TemplateReloader Class
1231
+ - `checkAndReloadAdminTemplates()` - Check and reload admin templates when changed
1232
+ - `checkAndReloadFrontendTemplates()` - Check and reload frontend templates when changed
1233
+ - `trackTemplateFiles(templatesPaths)` - Start tracking template files for changes
1234
+ - `shouldReloadAdminTemplates(mappedAdminTemplates)` - Check if admin templates need reloading
1235
+ - `shouldReloadFrontendTemplates(templatesPath, templateExtensions)` - Check if frontend templates need reloading
1236
+ - `handleAdminTemplateReload(adminManager)` - Complete admin template reload process
1237
+ - `handleFrontendTemplateReload(templateCache, templateResolver)` - Complete frontend template reload process
1238
+
1239
+ #### RequestProcessor Class
1240
+ - `findRouteByPath(path, domain)` - Database route lookup
1241
+ - `handleRouteRedirect(route, res)` - Handle route redirects
1242
+ - `getDomainFromRequest(req)` - Extract domain from request
1243
+ - `buildCacheKey(path, req)` - Generate cache keys
1244
+
1245
+ #### ContentRenderer Class
1246
+ - `renderWithTemplateContent(content, data, domain, req, route)` - Main content rendering
1247
+ - `generateRouteContent(route, domain, req)` - Route-based content generation
1248
+ - `generateTemplateContent(templatePath, domain, req, data)` - Template-based content generation
1249
+ - `fetchMetaFields(data)` - Process meta fields for templates
1250
+
1251
+ #### EntityAccessManager Class
1252
+ - `loadEntityAccessRules()` - Load entity access configuration
1253
+ - `isEntityAccessible(entityName)` - Check entity accessibility
1254
+ - `findEntityByPath(path)` - Entity lookup by URL path
1255
+
1256
+ #### ResponseManager Class
1257
+ - `renderWithCacheHandler(contentGenerator, errorHandler, responseHandler, domain, res, path, req)` - Generic cached response handler
1258
+ - `renderNotFound(domain, res, req)` - 404 error handling
1259
+
1260
+ #### SearchRequestHandler Class
1261
+ - `handleSearchRequest(req, res)` - Process search requests with template data support
687
1262
 
688
1263
  ### TemplateEngine Class
689
1264
  - `render(template, data, partials, domain, req, route, currentEntityData)` - Main template rendering with enhanced context
@@ -696,6 +1271,41 @@ The installer provides checkboxes for:
696
1271
  - `buildCurrentRouteData(route)` - Build route context
697
1272
  - `buildCurrentDomainData(domain)` - Build domain context
698
1273
 
1274
+ ### Search Classes
1275
+ - `Search.parseSearchParameters(query)` - Parse search query parameters including templateData
1276
+ - `Search.executeSearch(config)` - Execute search with configuration
1277
+ - `SearchRenderer.renderSearchResults(searchResults, config, domain, req)` - Render search results with template data
1278
+
1279
+ ### Forms System Classes
1280
+
1281
+ #### DynamicForm Class
1282
+ - `validateFormSubmission(formKey, submittedValues, req)` - Validate form submission
1283
+ - `getFormConfig(formKey)` - Load form configuration from database
1284
+ - `validateHoneypot(submittedValues)` - Check honeypot field for bots
1285
+ - `validateFields(fieldsSchema, submittedValues)` - Schema-based field validation
1286
+ - `prepareSubmittedValues(submittedValues, fieldsSchema)` - Process and normalize values
1287
+ - `saveFormSubmission(formConfig, preparedValues)` - Save to database
1288
+
1289
+ #### DynamicFormRenderer Class
1290
+ - `renderForm(formConfig, fieldsToRender, domain, req, attributes)` - Render complete form
1291
+ - `renderFormFields(fieldsToRender, domain, req)` - Render field set
1292
+ - `renderFormField(field, domain, submittedValues, errors)` - Render individual field
1293
+ - `loadFormTemplate(templateName, domain)` - Load form template with domain fallback
1294
+ - `findFormTemplate(templateName, domain)` - Template discovery for forms
1295
+
1296
+ #### DynamicFormRequestHandler Class
1297
+ - `handleFormSubmission(req, res)` - Process POST form submissions
1298
+ - `handleBadRequest(res, message)` - Handle validation errors
1299
+ - `handleSuccessResponse(req, res, formKey, result)` - Handle successful submissions
1300
+ - `buildErrorRedirectPath(req, error, formKey)` - Build error redirect URLs
1301
+ - `buildSuccessRedirectPath(successRedirect, formKey)` - Build success redirect URLs
1302
+
1303
+ #### FormsTransformer Class
1304
+ - `transform(template, domain, req, systemVariables, enhancedData)` - Process cmsForm tags
1305
+ - `findAllFormTags(template)` - Find cmsForm tags in template
1306
+ - `parseFormAttributes(fullTag)` - Parse tag attributes
1307
+ - `parseFieldsFilter(attributes, formConfig)` - Filter fields based on attributes
1308
+
699
1309
  ### AdminManager Class
700
1310
  - `setupAdmin()` - Initialize admin panel
701
1311
  - `generateListRouteContent()` - Entity list pages
@@ -713,10 +1323,36 @@ The installer provides checkboxes for:
713
1323
  project/
714
1324
  ├── admin/
715
1325
  │ └── templates/ # Admin panel templates
1326
+ ├── lib/
1327
+ │ ├── frontend/ # Frontend specialized classes
1328
+ │ │ ├── template-resolver.js
1329
+ │ │ ├── template-cache.js
1330
+ │ │ ├── request-processor.js
1331
+ │ │ ├── entity-access-manager.js
1332
+ │ │ ├── content-renderer.js
1333
+ │ │ └── response-manager.js
1334
+ │ ├── template-engine/ # Template processing classes
1335
+ │ │ └── forms-transformer.js
1336
+ │ ├── frontend.js # Main Frontend orchestrator
1337
+ │ ├── template-reloader.js # Template reloading functionality
1338
+ │ ├── search-request-handler.js
1339
+ │ ├── search.js # Search functionality
1340
+ │ ├── search-renderer.js # Search result rendering
1341
+ │ ├── dynamic-form.js # Forms validation and processing
1342
+ │ ├── dynamic-form-renderer.js # Forms template rendering
1343
+ │ ├── dynamic-form-request-handler.js # Forms request handling
1344
+ │ └── template-engine.js # Core template processing
716
1345
  ├── templates/
717
1346
  │ ├── layouts/ # Body content layouts
718
1347
  │ ├── domains/ # Domain-specific templates
1348
+ │ │ └── example.com/
1349
+ │ │ └── cms_forms/ # Domain-specific form templates
719
1350
  │ ├── partials/ # Shared template partials
1351
+ │ ├── cms_forms/ # Default form templates
1352
+ │ │ ├── form.html # Main form wrapper
1353
+ │ │ ├── field_text.html # Text field template
1354
+ │ │ ├── field_email.html # Email field template
1355
+ │ │ └── field_select.html # Select field template
720
1356
  │ ├── page.html # Base HTML wrapper
721
1357
  │ └── 404.html # Error page
722
1358
  ├── translations/