underpost 2.90.0 → 2.90.4

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.
@@ -0,0 +1,807 @@
1
+ # Underpost Static Site Generator - Comprehensive Guide
2
+
3
+ ## Table of Contents
4
+
5
+ 1. [Overview](#overview)
6
+ 2. [Quick Start](#quick-start)
7
+ 3. [CLI Usage](#cli-usage)
8
+ 4. [Configuration File](#configuration-file)
9
+ 5. [Metadata Customization](#metadata-customization)
10
+ 6. [Scripts and Styles](#scripts-and-styles)
11
+ 7. [Icons and PWA](#icons-and-pwa)
12
+ 8. [SSR Components](#ssr-components)
13
+ 9. [Advanced Examples](#advanced-examples)
14
+ 10. [Best Practices](#best-practices)
15
+ 11. [API Reference](#api-reference)
16
+
17
+ ---
18
+
19
+ ## Overview
20
+
21
+ The Underpost Static Site Generator is a powerful tool for creating highly customizable static HTML pages with:
22
+
23
+ - **Comprehensive SEO metadata** (Open Graph, Twitter Cards, Schema.org)
24
+ - **Custom script and stylesheet injection**
25
+ - **Icon and PWA manifest support**
26
+ - **Server-side rendering (SSR) components**
27
+ - **Structured data (JSON-LD) support**
28
+ - **Production-ready minification**
29
+ - **Flexible configuration via CLI or JSON files**
30
+
31
+ ---
32
+
33
+ ## Quick Start
34
+
35
+ ### Basic Usage
36
+
37
+ Generate a simple static page:
38
+
39
+ ```bash
40
+ underpost static \
41
+ --page ./src/client/ssr/body/DefaultSplashScreen.js \
42
+ --output-path ./dist/index.html \
43
+ --title "My App"
44
+ ```
45
+
46
+ ### Using a Configuration File
47
+
48
+ 1. Generate a template config:
49
+
50
+ ```bash
51
+ underpost static --generate-config ./my-config.json
52
+ ```
53
+
54
+ 2. Edit the generated `my-config.json` file
55
+
56
+ 3. Build with the config:
57
+
58
+ ```bash
59
+ underpost static --config-file ./my-config.json
60
+ ```
61
+
62
+ ---
63
+
64
+ ## CLI Usage
65
+
66
+ ### Complete CLI Options
67
+
68
+ ```bash
69
+ underpost static [options]
70
+ ```
71
+
72
+ #### Page and Output Options
73
+
74
+ - `--page <path>` - SSR component path to render
75
+ - `--output-path <path>` - Where to save the generated HTML
76
+ - `--env <env>` - Environment: `development` or `production` (default: `production`)
77
+ - `--minify` / `--no-minify` - Control HTML minification
78
+
79
+ #### Metadata Options
80
+
81
+ - `--title <title>` - Page title
82
+ - `--description <desc>` - Page description for SEO
83
+ - `--keywords <keywords>` - Comma-separated keywords
84
+ - `--author <author>` - Page author
85
+ - `--theme-color <color>` - Theme color (hex format)
86
+ - `--canonical-url <url>` - Canonical URL
87
+ - `--thumbnail <url>` - Open Graph thumbnail URL
88
+ - `--locale <locale>` - Page locale (e.g., `en-US`)
89
+ - `--site-name <name>` - Site name for Open Graph
90
+
91
+ #### Script and Style Options
92
+
93
+ - `--head-scripts <paths>` - Comma-separated script URLs for `<head>`
94
+ - `--body-scripts <paths>` - Comma-separated script URLs for `<body>`
95
+ - `--styles <paths>` - Comma-separated stylesheet URLs
96
+
97
+ #### Icon Options
98
+
99
+ - `--favicon <path>` - Favicon path
100
+ - `--apple-touch-icon <path>` - Apple touch icon path
101
+ - `--manifest <path>` - Web manifest path
102
+
103
+ #### Component Options
104
+
105
+ - `--head-components <paths>` - Comma-separated SSR head component paths
106
+ - `--body-components <paths>` - Comma-separated SSR body component paths
107
+
108
+ #### Build Options
109
+
110
+ - `--deploy-id <id>` - Deployment identifier
111
+ - `--build` - Trigger build process
112
+ - `--build-host <host>` - Build host URL
113
+ - `--build-path <path>` - Build path (default: `/`)
114
+
115
+ #### Configuration Options
116
+
117
+ - `--config-file <path>` - Load configuration from JSON file
118
+ - `--generate-config [path]` - Generate template config file
119
+ - `--lang <lang>` - HTML lang attribute (default: `en`)
120
+ - `--dir <dir>` - HTML dir attribute (default: `ltr`)
121
+
122
+ ---
123
+
124
+ ## Configuration File
125
+
126
+ ### Structure
127
+
128
+ ```json
129
+ {
130
+ "page": "./src/client/ssr/body/CustomPage.js",
131
+ "outputPath": "./dist/index.html",
132
+ "env": "production",
133
+ "minify": true,
134
+ "lang": "en",
135
+ "dir": "ltr",
136
+
137
+ "metadata": { /* ... */ },
138
+ "scripts": { /* ... */ },
139
+ "styles": [ /* ... */ ],
140
+ "icons": { /* ... */ },
141
+ "headComponents": [ /* ... */ ],
142
+ "bodyComponents": [ /* ... */ ],
143
+ "microdata": [ /* ... */ ],
144
+ "customPayload": { /* ... */ }
145
+ }
146
+ ```
147
+
148
+ ### Generate Template
149
+
150
+ ```bash
151
+ underpost static --generate-config ./static-config.json
152
+ ```
153
+
154
+ This creates a fully documented template with all available options.
155
+
156
+ ---
157
+
158
+ ## Metadata Customization
159
+
160
+ ### Basic Metadata
161
+
162
+ ```json
163
+ {
164
+ "metadata": {
165
+ "title": "My Application",
166
+ "description": "A comprehensive description of my application",
167
+ "keywords": ["web app", "progressive", "modern"],
168
+ "author": "Jane Developer",
169
+ "themeColor": "#4CAF50",
170
+ "canonicalURL": "https://example.com",
171
+ "thumbnail": "https://example.com/images/og-image.png",
172
+ "locale": "en-US",
173
+ "siteName": "My Site"
174
+ }
175
+ }
176
+ ```
177
+
178
+ ### Advanced Open Graph
179
+
180
+ ```json
181
+ {
182
+ "metadata": {
183
+ "title": "My App",
184
+ "description": "App description",
185
+ "openGraph": {
186
+ "type": "website",
187
+ "image:width": "1200",
188
+ "image:height": "630",
189
+ "image:alt": "App screenshot"
190
+ }
191
+ }
192
+ }
193
+ ```
194
+
195
+ ### Twitter Cards
196
+
197
+ ```json
198
+ {
199
+ "metadata": {
200
+ "title": "My App",
201
+ "twitter": {
202
+ "card": "summary_large_image",
203
+ "site": "@myhandle",
204
+ "creator": "@developerhandle"
205
+ }
206
+ }
207
+ }
208
+ ```
209
+
210
+ ### CLI Example
211
+
212
+ ```bash
213
+ underpost static \
214
+ --page ./src/client/ssr/body/HomePage.js \
215
+ --output-path ./dist/index.html \
216
+ --title "My App" \
217
+ --description "A modern web application" \
218
+ --keywords "web,app,modern" \
219
+ --author "John Doe" \
220
+ --theme-color "#007bff" \
221
+ --canonical-url "https://myapp.com" \
222
+ --thumbnail "https://myapp.com/og-image.png"
223
+ ```
224
+
225
+ ---
226
+
227
+ ## Scripts and Styles
228
+
229
+ ### External Scripts
230
+
231
+ ```json
232
+ {
233
+ "scripts": {
234
+ "head": [
235
+ {
236
+ "src": "https://cdn.example.com/analytics.js",
237
+ "async": true
238
+ }
239
+ ],
240
+ "body": [
241
+ {
242
+ "src": "/app.js",
243
+ "type": "module",
244
+ "defer": true
245
+ }
246
+ ]
247
+ }
248
+ }
249
+ ```
250
+
251
+ ### Inline Scripts
252
+
253
+ ```json
254
+ {
255
+ "scripts": {
256
+ "head": [
257
+ {
258
+ "content": "window.config = { apiUrl: 'https://api.example.com' };",
259
+ "type": "text/javascript"
260
+ }
261
+ ]
262
+ }
263
+ }
264
+ ```
265
+
266
+ ### Advanced Script Options
267
+
268
+ ```json
269
+ {
270
+ "scripts": {
271
+ "head": [
272
+ {
273
+ "src": "https://cdn.example.com/lib.js",
274
+ "async": true,
275
+ "integrity": "sha384-...",
276
+ "crossorigin": "anonymous",
277
+ "attributes": {
278
+ "data-custom": "value"
279
+ }
280
+ }
281
+ ]
282
+ }
283
+ }
284
+ ```
285
+
286
+ ### Stylesheets
287
+
288
+ ```json
289
+ {
290
+ "styles": [
291
+ {
292
+ "href": "/styles/main.css"
293
+ },
294
+ {
295
+ "href": "https://fonts.googleapis.com/css2?family=Inter:wght@400;600&display=swap"
296
+ },
297
+ {
298
+ "content": "body { margin: 0; padding: 0; }",
299
+ "_comment": "Critical CSS inline"
300
+ },
301
+ {
302
+ "href": "/styles/print.css",
303
+ "media": "print"
304
+ }
305
+ ]
306
+ }
307
+ ```
308
+
309
+ ### CLI Example
310
+
311
+ ```bash
312
+ underpost static \
313
+ --page ./src/client/ssr/body/App.js \
314
+ --output-path ./dist/index.html \
315
+ --head-scripts "https://cdn.example.com/analytics.js,/config.js" \
316
+ --body-scripts "/app.js" \
317
+ --styles "/main.css,/theme.css"
318
+ ```
319
+
320
+ ---
321
+
322
+ ## Icons and PWA
323
+
324
+ ### Basic Icons
325
+
326
+ ```json
327
+ {
328
+ "icons": {
329
+ "favicon": "/favicon.ico",
330
+ "appleTouchIcon": "/apple-touch-icon.png",
331
+ "manifest": "/manifest.json"
332
+ }
333
+ }
334
+ ```
335
+
336
+ ### Advanced Icons
337
+
338
+ ```json
339
+ {
340
+ "icons": {
341
+ "favicon": "/favicon.ico",
342
+ "appleTouchIcon": "/apple-touch-icon.png",
343
+ "manifest": "/manifest.json",
344
+ "additional": [
345
+ {
346
+ "rel": "icon",
347
+ "type": "image/png",
348
+ "sizes": "32x32",
349
+ "href": "/favicon-32x32.png"
350
+ },
351
+ {
352
+ "rel": "icon",
353
+ "type": "image/png",
354
+ "sizes": "16x16",
355
+ "href": "/favicon-16x16.png"
356
+ },
357
+ {
358
+ "rel": "mask-icon",
359
+ "href": "/safari-pinned-tab.svg",
360
+ "color": "#4CAF50"
361
+ }
362
+ ]
363
+ }
364
+ }
365
+ ```
366
+
367
+ ### CLI Example
368
+
369
+ ```bash
370
+ underpost static \
371
+ --page ./src/client/ssr/body/App.js \
372
+ --output-path ./dist/index.html \
373
+ --favicon "/favicon.ico" \
374
+ --apple-touch-icon "/apple-touch-icon.png" \
375
+ --manifest "/manifest.json"
376
+ ```
377
+
378
+ ---
379
+
380
+ ## SSR Components
381
+
382
+ ### Head Components
383
+
384
+ Create custom SSR components for reusable head content:
385
+
386
+ ```javascript
387
+ // src/client/ssr/head/CustomMeta.js
388
+ SrrComponent = ({ title, author, themeColor }) => html`
389
+ <meta name="author" content="${author}" />
390
+ <meta name="theme-color" content="${themeColor}" />
391
+ <meta name="custom-meta" content="custom-value" />
392
+ `;
393
+ ```
394
+
395
+ Use in configuration:
396
+
397
+ ```json
398
+ {
399
+ "headComponents": [
400
+ "./src/client/ssr/head/Seo.js",
401
+ "./src/client/ssr/head/Pwa.js",
402
+ "./src/client/ssr/head/CustomMeta.js"
403
+ ]
404
+ }
405
+ ```
406
+
407
+ ### Body Components
408
+
409
+ ```javascript
410
+ // src/client/ssr/body/CustomSplash.js
411
+ SrrComponent = () => html`
412
+ <div class="splash-screen">
413
+ <div class="logo"></div>
414
+ <div class="loading">Loading...</div>
415
+ </div>
416
+ `;
417
+ ```
418
+
419
+ ### CLI Example
420
+
421
+ ```bash
422
+ underpost static \
423
+ --page ./src/client/ssr/body/MainPage.js \
424
+ --output-path ./dist/index.html \
425
+ --head-components "./src/client/ssr/head/Seo.js,./src/client/ssr/head/Pwa.js" \
426
+ --body-components "./src/client/ssr/body/Header.js,./src/client/ssr/body/Footer.js"
427
+ ```
428
+
429
+ ---
430
+
431
+ ## Advanced Examples
432
+
433
+ ### Example 1: Landing Page with Analytics
434
+
435
+ ```json
436
+ {
437
+ "page": "./src/client/ssr/body/LandingPage.js",
438
+ "outputPath": "./dist/landing.html",
439
+ "env": "production",
440
+ "metadata": {
441
+ "title": "Welcome to Our Product",
442
+ "description": "The best product for your needs",
443
+ "keywords": ["product", "solution", "innovation"],
444
+ "themeColor": "#007bff",
445
+ "canonicalURL": "https://product.com/landing"
446
+ },
447
+ "scripts": {
448
+ "head": [
449
+ {
450
+ "src": "https://www.googletagmanager.com/gtag/js?id=GA_ID",
451
+ "async": true
452
+ },
453
+ {
454
+ "content": "window.dataLayer=window.dataLayer||[];function gtag(){dataLayer.push(arguments);}gtag('js',new Date());gtag('config','GA_ID');"
455
+ }
456
+ ],
457
+ "body": [
458
+ {
459
+ "src": "/landing.js",
460
+ "defer": true
461
+ }
462
+ ]
463
+ }
464
+ }
465
+ ```
466
+
467
+ ### Example 2: Documentation Site
468
+
469
+ ```json
470
+ {
471
+ "page": "./src/client/ssr/body/DocsPage.js",
472
+ "outputPath": "./dist/docs/index.html",
473
+ "metadata": {
474
+ "title": "Documentation - My API",
475
+ "description": "Complete API documentation",
476
+ "author": "API Team"
477
+ },
478
+ "headComponents": [
479
+ "./src/client/ssr/head/Seo.js",
480
+ "./src/client/ssr/head/DocsStyles.js"
481
+ ],
482
+ "styles": [
483
+ {
484
+ "href": "/docs/prism.css"
485
+ },
486
+ {
487
+ "href": "/docs/docs.css"
488
+ }
489
+ ],
490
+ "scripts": {
491
+ "body": [
492
+ {
493
+ "src": "/docs/prism.js",
494
+ "defer": true
495
+ }
496
+ ]
497
+ }
498
+ }
499
+ ```
500
+
501
+ ### Example 3: E-commerce Product Page
502
+
503
+ ```json
504
+ {
505
+ "page": "./src/client/ssr/body/ProductPage.js",
506
+ "outputPath": "./dist/product.html",
507
+ "metadata": {
508
+ "title": "Premium Widget - Buy Now",
509
+ "description": "High-quality premium widget with free shipping",
510
+ "thumbnail": "https://shop.com/products/widget/image.jpg",
511
+ "openGraph": {
512
+ "type": "product",
513
+ "price:amount": "29.99",
514
+ "price:currency": "USD"
515
+ }
516
+ },
517
+ "microdata": [
518
+ {
519
+ "@context": "https://schema.org",
520
+ "@type": "Product",
521
+ "name": "Premium Widget",
522
+ "image": "https://shop.com/products/widget/image.jpg",
523
+ "description": "High-quality premium widget",
524
+ "offers": {
525
+ "@type": "Offer",
526
+ "price": "29.99",
527
+ "priceCurrency": "USD",
528
+ "availability": "https://schema.org/InStock"
529
+ }
530
+ }
531
+ ]
532
+ }
533
+ ```
534
+
535
+ ### Example 4: Multi-language Site
536
+
537
+ ```bash
538
+ # Generate English version
539
+ underpost static \
540
+ --config-file ./config-en.json \
541
+ --output-path ./dist/en/index.html \
542
+ --lang en \
543
+ --dir ltr
544
+
545
+ # Generate Arabic version
546
+ underpost static \
547
+ --config-file ./config-ar.json \
548
+ --output-path ./dist/ar/index.html \
549
+ --lang ar \
550
+ --dir rtl
551
+ ```
552
+
553
+ ---
554
+
555
+ ## Best Practices
556
+
557
+ ### 1. SEO Optimization
558
+
559
+ - Always include `title`, `description`, and `keywords`
560
+ - Use canonical URLs to avoid duplicate content
561
+ - Add structured data (JSON-LD) for rich snippets
562
+ - Include Open Graph and Twitter Card metadata
563
+
564
+ ```json
565
+ {
566
+ "metadata": {
567
+ "title": "Unique, descriptive title",
568
+ "description": "150-160 character description",
569
+ "keywords": ["relevant", "keywords"],
570
+ "canonicalURL": "https://example.com/page"
571
+ },
572
+ "microdata": [
573
+ {
574
+ "@context": "https://schema.org",
575
+ "@type": "WebPage",
576
+ "name": "Page Name"
577
+ }
578
+ ]
579
+ }
580
+ ```
581
+
582
+ ### 2. Performance
583
+
584
+ - Minify HTML in production (`minify: true`)
585
+ - Use `async` or `defer` for scripts
586
+ - Inline critical CSS
587
+ - Optimize images referenced in metadata
588
+
589
+ ```json
590
+ {
591
+ "env": "production",
592
+ "minify": true,
593
+ "scripts": {
594
+ "head": [
595
+ { "src": "/analytics.js", "async": true }
596
+ ],
597
+ "body": [
598
+ { "src": "/app.js", "defer": true }
599
+ ]
600
+ },
601
+ "styles": [
602
+ { "content": "/* Critical CSS */" },
603
+ { "href": "/main.css" }
604
+ ]
605
+ }
606
+ ```
607
+
608
+ ### 3. Progressive Web Apps
609
+
610
+ - Include web manifest
611
+ - Add various icon sizes
612
+ - Set theme color
613
+ - Register service worker
614
+
615
+ ```json
616
+ {
617
+ "icons": {
618
+ "favicon": "/favicon.ico",
619
+ "manifest": "/manifest.json"
620
+ },
621
+ "metadata": {
622
+ "themeColor": "#007bff"
623
+ },
624
+ "scripts": {
625
+ "body": [
626
+ {
627
+ "content": "if('serviceWorker' in navigator){navigator.serviceWorker.register('/sw.js');}"
628
+ }
629
+ ]
630
+ }
631
+ }
632
+ ```
633
+
634
+ ### 4. Security
635
+
636
+ - Use Subresource Integrity (SRI) for external resources
637
+ - Set appropriate CORS headers
638
+ - Validate all user inputs in custom payloads
639
+
640
+ ```json
641
+ {
642
+ "scripts": {
643
+ "head": [
644
+ {
645
+ "src": "https://cdn.example.com/lib.js",
646
+ "integrity": "sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC",
647
+ "crossorigin": "anonymous"
648
+ }
649
+ ]
650
+ }
651
+ }
652
+ ```
653
+
654
+ ### 5. Configuration Management
655
+
656
+ - Use config files for complex setups
657
+ - Version control your config files
658
+ - Create environment-specific configs
659
+ - Document custom configurations
660
+
661
+ ```bash
662
+ # Development
663
+ underpost static --config-file ./config.dev.json
664
+
665
+ # Production
666
+ underpost static --config-file ./config.prod.json
667
+ ```
668
+
669
+ ### 6. Component Reusability
670
+
671
+ Create reusable SSR components for common patterns:
672
+
673
+ ```javascript
674
+ // src/client/ssr/head/Analytics.js
675
+ SrrComponent = ({ gaId }) => html`
676
+ <script async src="https://www.googletagmanager.com/gtag/js?id=${gaId}"></script>
677
+ <script>
678
+ window.dataLayer = window.dataLayer || [];
679
+ function gtag(){dataLayer.push(arguments);}
680
+ gtag('js', new Date());
681
+ gtag('config', '${gaId}');
682
+ </script>
683
+ `;
684
+ ```
685
+
686
+ ---
687
+
688
+ ## API Reference
689
+
690
+ ### JavaScript API
691
+
692
+ ```javascript
693
+ import UnderpostStatic from './src/cli/static.js';
694
+
695
+ // Generate static page programmatically
696
+ await UnderpostStatic.API.callback({
697
+ page: './src/client/ssr/body/Page.js',
698
+ outputPath: './dist/index.html',
699
+ metadata: { /* ... */ },
700
+ // ... other options
701
+ });
702
+
703
+ // Generate config template
704
+ UnderpostStatic.API.generateConfigTemplate('./my-config.json');
705
+
706
+ // Use helper functions
707
+ import { TemplateHelpers } from './src/cli/static.js';
708
+
709
+ const scriptTag = TemplateHelpers.createScriptTag({
710
+ src: '/app.js',
711
+ defer: true
712
+ });
713
+
714
+ const metaTags = TemplateHelpers.createMetaTags({
715
+ title: 'My Page',
716
+ description: 'Description'
717
+ });
718
+ ```
719
+
720
+ ### Template Helpers
721
+
722
+ - `TemplateHelpers.createScriptTag(options)` - Generate script tags
723
+ - `TemplateHelpers.createStyleTag(options)` - Generate style/link tags
724
+ - `TemplateHelpers.createIconTags(icons)` - Generate icon link tags
725
+ - `TemplateHelpers.createMetaTags(metadata)` - Generate meta tags
726
+ - `TemplateHelpers.createMicrodataTags(microdata)` - Generate JSON-LD tags
727
+
728
+ ### Config Validator
729
+
730
+ ```javascript
731
+ import { ConfigValidator } from './src/cli/static.js';
732
+
733
+ const result = ConfigValidator.validate(options);
734
+ if (!result.isValid) {
735
+ console.error('Validation errors:', result.errors);
736
+ }
737
+ ```
738
+
739
+ ### Config Loader
740
+
741
+ ```javascript
742
+ import { ConfigLoader } from './src/cli/static.js';
743
+
744
+ // Load config
745
+ const config = ConfigLoader.load('./config.json');
746
+
747
+ // Save config
748
+ ConfigLoader.save('./config.json', configObject);
749
+ ```
750
+
751
+ ---
752
+
753
+ ## Troubleshooting
754
+
755
+ ### Common Issues
756
+
757
+ **Issue: Component not found**
758
+ ```
759
+ Error: Page component does not exist: ./src/client/ssr/body/Missing.js
760
+ ```
761
+ **Solution:** Verify the path to your SSR component file.
762
+
763
+ **Issue: Output directory doesn't exist**
764
+ ```
765
+ Error: Output directory does not exist: ./dist/pages
766
+ ```
767
+ **Solution:** Create the directory first or use a different output path.
768
+
769
+ **Issue: Invalid JSON in config file**
770
+ ```
771
+ Error: Error loading config file: Unexpected token
772
+ ```
773
+ **Solution:** Validate your JSON syntax using a linter.
774
+
775
+ ### Debug Mode
776
+
777
+ Use `--dev` flag for development mode with additional logging:
778
+
779
+ ```bash
780
+ underpost static --config-file ./config.json --dev
781
+ ```
782
+
783
+ ---
784
+
785
+ ## Examples Repository
786
+
787
+ See the `examples/` directory for complete working examples:
788
+
789
+ - `static-config-example.json` - Comprehensive configuration example
790
+ - Additional examples coming soon
791
+
792
+ ---
793
+
794
+ ## Contributing
795
+
796
+ To contribute improvements to the static generator:
797
+
798
+ 1. Add new features to `src/cli/static.js`
799
+ 2. Update this documentation
800
+ 3. Add examples to the `examples/` directory
801
+ 4. Include JSDoc comments for all new functions
802
+
803
+ ---
804
+
805
+ ## License
806
+
807
+ This is part of the Underpost framework. See main project license.