@jsonpages/cli 3.0.21 → 3.0.22
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/assets/src_tenant_alpha.sh +505 -419
- package/package.json +1 -1
- package/src/index.js +1 -1
|
@@ -29,6 +29,7 @@ echo "Creating src/App.tsx..."
|
|
|
29
29
|
cat << 'END_OF_FILE_CONTENT' > "src/App.tsx"
|
|
30
30
|
/**
|
|
31
31
|
* Thin Entry Point (Tenant).
|
|
32
|
+
* Loads from localStorage draft when present (same key as Core autosave), else from file.
|
|
32
33
|
*/
|
|
33
34
|
import { useState, useEffect } from 'react';
|
|
34
35
|
import { JsonPagesEngine } from '@jsonpages/core';
|
|
@@ -36,10 +37,11 @@ import type { LibraryImageEntry } from '@jsonpages/core';
|
|
|
36
37
|
import { ComponentRegistry } from '@/lib/ComponentRegistry';
|
|
37
38
|
import { SECTION_SCHEMAS } from '@/lib/schemas';
|
|
38
39
|
import { addSectionConfig } from '@/lib/addSectionConfig';
|
|
40
|
+
import { getHydratedData } from '@/lib/draftStorage';
|
|
39
41
|
import type { JsonPagesConfig } from '@jsonpages/core';
|
|
40
42
|
import type { PageConfig, SiteConfig, ThemeConfig, MenuConfig } from '@/types';
|
|
41
43
|
|
|
42
|
-
// Tenant data
|
|
44
|
+
// Tenant data (file-backed fallback)
|
|
43
45
|
import siteData from '@/data/config/site.json';
|
|
44
46
|
import themeData from '@/data/config/theme.json';
|
|
45
47
|
import menuData from '@/data/config/menu.json';
|
|
@@ -48,15 +50,21 @@ import homeData from '@/data/pages/home.json';
|
|
|
48
50
|
// Tenant CSS
|
|
49
51
|
import tenantCss from './index.css?inline';
|
|
50
52
|
|
|
51
|
-
const siteConfig = siteData as unknown as SiteConfig;
|
|
52
53
|
const themeConfig = themeData as unknown as ThemeConfig;
|
|
53
54
|
const menuConfig = menuData as unknown as MenuConfig;
|
|
54
55
|
|
|
55
|
-
const
|
|
56
|
+
const TENANT_ID = 'alpha';
|
|
57
|
+
const filePages: Record<string, PageConfig> = {
|
|
56
58
|
home: homeData as unknown as PageConfig,
|
|
57
59
|
};
|
|
60
|
+
const fileSiteConfig = siteData as unknown as SiteConfig;
|
|
61
|
+
|
|
62
|
+
function getInitialData() {
|
|
63
|
+
return getHydratedData(TENANT_ID, filePages, fileSiteConfig);
|
|
64
|
+
}
|
|
58
65
|
|
|
59
66
|
function App() {
|
|
67
|
+
const [{ pages, siteConfig }] = useState(getInitialData);
|
|
60
68
|
const [assetsManifest, setAssetsManifest] = useState<LibraryImageEntry[]>([]);
|
|
61
69
|
|
|
62
70
|
// #region agent log
|
|
@@ -78,7 +86,7 @@ function App() {
|
|
|
78
86
|
}, []);
|
|
79
87
|
|
|
80
88
|
const config: JsonPagesConfig = {
|
|
81
|
-
tenantId:
|
|
89
|
+
tenantId: TENANT_ID,
|
|
82
90
|
registry: ComponentRegistry as JsonPagesConfig['registry'],
|
|
83
91
|
schemas: SECTION_SCHEMAS as unknown as JsonPagesConfig['schemas'],
|
|
84
92
|
pages,
|
|
@@ -2450,421 +2458,433 @@ END_OF_FILE_CONTENT
|
|
|
2450
2458
|
mkdir -p "src/data/pages"
|
|
2451
2459
|
echo "Creating src/data/pages/home.json..."
|
|
2452
2460
|
cat << 'END_OF_FILE_CONTENT' > "src/data/pages/home.json"
|
|
2453
|
-
{
|
|
2454
|
-
"id": "home-page",
|
|
2455
|
-
"slug": "home",
|
|
2456
|
-
"meta": {
|
|
2457
|
-
"title": "JsonPages — Global Authoring. Global Governance.",
|
|
2458
|
-
"description": "A high-fidelity Site Factory that solves the scalability bottleneck of traditional CMS systems."
|
|
2459
|
-
},
|
|
2460
|
-
"sections": [
|
|
2461
|
-
{
|
|
2462
|
-
"id": "hero-main",
|
|
2463
|
-
"type": "hero",
|
|
2464
|
-
"data": {
|
|
2465
|
-
"badge": "Composable UI Engine · v1.0",
|
|
2466
|
-
"title": "Local Authoring",
|
|
2467
|
-
"titleHighlight": "Global Governance",
|
|
2468
|
-
"description": "JsonPages is a high-fidelity Site Factory that solves the scalability bottleneck of traditional CMS systems. Distribute, govern, and render UI components across hundreds of independent sites — without technical drift.",
|
|
2469
|
-
"ctas": [
|
|
2470
|
-
{
|
|
2471
|
-
"label": "Explore Products →",
|
|
2472
|
-
"href": "#products",
|
|
2473
|
-
"variant": "primary"
|
|
2474
|
-
},
|
|
2475
|
-
{
|
|
2476
|
-
"label": "Read the Spec",
|
|
2477
|
-
"href": "#architecture",
|
|
2478
|
-
"variant": "secondary"
|
|
2479
|
-
}
|
|
2480
|
-
],
|
|
2481
|
-
"metrics": [
|
|
2482
|
-
{
|
|
2483
|
-
"val": "100+",
|
|
2484
|
-
"label": "Pages per tenant"
|
|
2485
|
-
},
|
|
2486
|
-
{
|
|
2487
|
-
"val": "0ms",
|
|
2488
|
-
"label": "Runtime overhead"
|
|
2489
|
-
},
|
|
2490
|
-
{
|
|
2491
|
-
"val": "∞",
|
|
2492
|
-
"label": "Scalable blocks"
|
|
2493
|
-
}
|
|
2494
|
-
]
|
|
2495
|
-
},
|
|
2496
|
-
"settings": {}
|
|
2497
|
-
},
|
|
2498
|
-
{
|
|
2499
|
-
"id": "
|
|
2500
|
-
"type": "
|
|
2501
|
-
"data": {
|
|
2502
|
-
"
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
"
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
"
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
"
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
"
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2578
|
-
"
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
"
|
|
2593
|
-
"
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
"
|
|
2597
|
-
"
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
"
|
|
2601
|
-
"
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
{
|
|
2629
|
-
"number": "
|
|
2630
|
-
"layerLevel": "
|
|
2631
|
-
"title": "
|
|
2632
|
-
"description": "
|
|
2633
|
-
}
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
"
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
"
|
|
2643
|
-
"
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
{
|
|
2650
|
-
"content": "
|
|
2651
|
-
"tokenType": "comment"
|
|
2652
|
-
},
|
|
2653
|
-
{
|
|
2654
|
-
"content": "
|
|
2655
|
-
"tokenType": "plain"
|
|
2656
|
-
},
|
|
2657
|
-
{
|
|
2658
|
-
"content": "",
|
|
2659
|
-
"tokenType": "
|
|
2660
|
-
},
|
|
2661
|
-
{
|
|
2662
|
-
"content": "
|
|
2663
|
-
"tokenType": "
|
|
2664
|
-
},
|
|
2665
|
-
{
|
|
2666
|
-
"content": "
|
|
2667
|
-
"tokenType": "
|
|
2668
|
-
},
|
|
2669
|
-
{
|
|
2670
|
-
"content": "
|
|
2671
|
-
"tokenType": "
|
|
2672
|
-
},
|
|
2673
|
-
{
|
|
2674
|
-
"content": "
|
|
2675
|
-
"tokenType": "
|
|
2676
|
-
},
|
|
2677
|
-
{
|
|
2678
|
-
"content": "
|
|
2679
|
-
"tokenType": "type"
|
|
2680
|
-
},
|
|
2681
|
-
{
|
|
2682
|
-
"content": "
|
|
2683
|
-
"tokenType": "
|
|
2684
|
-
},
|
|
2685
|
-
{
|
|
2686
|
-
"content": "",
|
|
2687
|
-
"tokenType": "
|
|
2688
|
-
},
|
|
2689
|
-
{
|
|
2690
|
-
"content": "
|
|
2691
|
-
"tokenType": "
|
|
2692
|
-
},
|
|
2693
|
-
{
|
|
2694
|
-
"content": "
|
|
2695
|
-
"tokenType": "
|
|
2696
|
-
},
|
|
2697
|
-
{
|
|
2698
|
-
"content": "
|
|
2699
|
-
"tokenType": "
|
|
2700
|
-
},
|
|
2701
|
-
{
|
|
2702
|
-
"content": "
|
|
2703
|
-
"tokenType": "
|
|
2704
|
-
}
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
{
|
|
2738
|
-
"text": "
|
|
2739
|
-
}
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
{
|
|
2763
|
-
"text": "
|
|
2764
|
-
},
|
|
2765
|
-
{
|
|
2766
|
-
"text": "
|
|
2767
|
-
}
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
{
|
|
2778
|
-
"text": "
|
|
2779
|
-
}
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
{
|
|
2790
|
-
"text": "
|
|
2791
|
-
},
|
|
2792
|
-
{
|
|
2793
|
-
"text": "
|
|
2794
|
-
}
|
|
2795
|
-
|
|
2796
|
-
|
|
2797
|
-
|
|
2798
|
-
|
|
2799
|
-
|
|
2800
|
-
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
"
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
"
|
|
2833
|
-
},
|
|
2834
|
-
{
|
|
2835
|
-
"label": "
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
2849
|
-
|
|
2850
|
-
|
|
2851
|
-
"
|
|
2852
|
-
|
|
2853
|
-
}
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
"
|
|
2858
|
-
"
|
|
2859
|
-
|
|
2860
|
-
"
|
|
2861
|
-
"
|
|
2862
|
-
"
|
|
2863
|
-
"
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
2461
|
+
{
|
|
2462
|
+
"id": "home-page",
|
|
2463
|
+
"slug": "home",
|
|
2464
|
+
"meta": {
|
|
2465
|
+
"title": "JsonPages — Global Authoring. Global Governance.",
|
|
2466
|
+
"description": "A high-fidelity Site Factory that solves the scalability bottleneck of traditional CMS systems."
|
|
2467
|
+
},
|
|
2468
|
+
"sections": [
|
|
2469
|
+
{
|
|
2470
|
+
"id": "hero-main",
|
|
2471
|
+
"type": "hero",
|
|
2472
|
+
"data": {
|
|
2473
|
+
"badge": "Composable UI Engine · v1.0",
|
|
2474
|
+
"title": "Local Authoring.",
|
|
2475
|
+
"titleHighlight": "Global Governance.",
|
|
2476
|
+
"description": "JsonPages is a high-fidelity Site Factory that solves the scalability bottleneck of traditional CMS systems. Distribute, govern, and render UI components across hundreds of independent sites — without technical drift.",
|
|
2477
|
+
"ctas": [
|
|
2478
|
+
{
|
|
2479
|
+
"label": "Explore Products →",
|
|
2480
|
+
"href": "#products",
|
|
2481
|
+
"variant": "primary"
|
|
2482
|
+
},
|
|
2483
|
+
{
|
|
2484
|
+
"label": "Read the Spec",
|
|
2485
|
+
"href": "#architecture",
|
|
2486
|
+
"variant": "secondary"
|
|
2487
|
+
}
|
|
2488
|
+
],
|
|
2489
|
+
"metrics": [
|
|
2490
|
+
{
|
|
2491
|
+
"val": "100+",
|
|
2492
|
+
"label": "Pages per tenant"
|
|
2493
|
+
},
|
|
2494
|
+
{
|
|
2495
|
+
"val": "0ms",
|
|
2496
|
+
"label": "Runtime overhead"
|
|
2497
|
+
},
|
|
2498
|
+
{
|
|
2499
|
+
"val": "∞",
|
|
2500
|
+
"label": "Scalable blocks"
|
|
2501
|
+
}
|
|
2502
|
+
]
|
|
2503
|
+
},
|
|
2504
|
+
"settings": {}
|
|
2505
|
+
},
|
|
2506
|
+
{
|
|
2507
|
+
"id": "image-break-1",
|
|
2508
|
+
"type": "image-break",
|
|
2509
|
+
"data": {
|
|
2510
|
+
"image": {
|
|
2511
|
+
"url": "https://images.unsplash.com/photo-1464226184884-fa280b87c399?w=800",
|
|
2512
|
+
"alt": "Verdure fresche dall'orto"
|
|
2513
|
+
},
|
|
2514
|
+
"caption": "Il nostro orto a pochi passi dalla cucina — raccolto ogni mattina all'alba"
|
|
2515
|
+
},
|
|
2516
|
+
"settings": {}
|
|
2517
|
+
},
|
|
2518
|
+
{
|
|
2519
|
+
"id": "problem-statement",
|
|
2520
|
+
"type": "problem-statement",
|
|
2521
|
+
"data": {
|
|
2522
|
+
"siloGroups": [
|
|
2523
|
+
{
|
|
2524
|
+
"blocks": [
|
|
2525
|
+
{
|
|
2526
|
+
"label": "Agency A Stack",
|
|
2527
|
+
"variant": "red"
|
|
2528
|
+
},
|
|
2529
|
+
{
|
|
2530
|
+
"label": "Custom CMS",
|
|
2531
|
+
"variant": "red"
|
|
2532
|
+
},
|
|
2533
|
+
{
|
|
2534
|
+
"label": "PHP Backend",
|
|
2535
|
+
"variant": "red"
|
|
2536
|
+
}
|
|
2537
|
+
],
|
|
2538
|
+
"label": "Silo #1"
|
|
2539
|
+
},
|
|
2540
|
+
{
|
|
2541
|
+
"blocks": [
|
|
2542
|
+
{
|
|
2543
|
+
"label": "Agency B Tools",
|
|
2544
|
+
"variant": "amber"
|
|
2545
|
+
},
|
|
2546
|
+
{
|
|
2547
|
+
"label": "WordPress",
|
|
2548
|
+
"variant": "amber"
|
|
2549
|
+
},
|
|
2550
|
+
{
|
|
2551
|
+
"label": "LAMP Stack",
|
|
2552
|
+
"variant": "amber"
|
|
2553
|
+
}
|
|
2554
|
+
],
|
|
2555
|
+
"label": "Silo #2"
|
|
2556
|
+
},
|
|
2557
|
+
{
|
|
2558
|
+
"blocks": [
|
|
2559
|
+
{
|
|
2560
|
+
"label": "Agency C Kit",
|
|
2561
|
+
"variant": "green"
|
|
2562
|
+
},
|
|
2563
|
+
{
|
|
2564
|
+
"label": "React App",
|
|
2565
|
+
"variant": "green"
|
|
2566
|
+
},
|
|
2567
|
+
{
|
|
2568
|
+
"label": "Node.js",
|
|
2569
|
+
"variant": "green"
|
|
2570
|
+
}
|
|
2571
|
+
],
|
|
2572
|
+
"label": "Silo #3"
|
|
2573
|
+
}
|
|
2574
|
+
],
|
|
2575
|
+
"title": "Traditional CMS systems create closed silos.",
|
|
2576
|
+
"paragraphs": [
|
|
2577
|
+
{
|
|
2578
|
+
"text": "When global brands delegate web projects to multiple agencies, each agency picks its own stack, its own conventions, its own deployment pipeline. The result is a portfolio of ungovernable sites with inconsistent quality and unpredictable maintenance costs.",
|
|
2579
|
+
"isBold": false
|
|
2580
|
+
},
|
|
2581
|
+
{
|
|
2582
|
+
"text": "JsonPages eliminates this by providing a centralized protocol to distribute, govern, and render UI components — ensuring every site, regardless of who builds it, conforms to a single typed ontology.",
|
|
2583
|
+
"isBold": true
|
|
2584
|
+
}
|
|
2585
|
+
],
|
|
2586
|
+
"anchorId": "aa"
|
|
2587
|
+
},
|
|
2588
|
+
"settings": {}
|
|
2589
|
+
},
|
|
2590
|
+
{
|
|
2591
|
+
"id": "architecture-pillars",
|
|
2592
|
+
"type": "pillars-grid",
|
|
2593
|
+
"data": {
|
|
2594
|
+
"anchorId": "architecture",
|
|
2595
|
+
"label": "Core Architecture",
|
|
2596
|
+
"title": "Three Pillars of Composability",
|
|
2597
|
+
"description": "A contract-first architecture designed to scale without core refactoring.",
|
|
2598
|
+
"pillars": [
|
|
2599
|
+
{
|
|
2600
|
+
"icon": "box",
|
|
2601
|
+
"iconVariant": "split",
|
|
2602
|
+
"title": "The Machine-Readable Blueprint. 📐",
|
|
2603
|
+
"description": "We enforce a strict file-system ontology that physically separates Global Governance from Local Content. By utilizing \"Dumb Components\" (CIP), we create a deterministic environment where the UI is a predictable function of data. This protocol allows AI agents to understand your site structure instantly, eliminating the \"guessing game\" of traditional web development.",
|
|
2604
|
+
"tag": "The Foundation",
|
|
2605
|
+
"tagVariant": "core"
|
|
2606
|
+
},
|
|
2607
|
+
{
|
|
2608
|
+
"icon": "sparkles",
|
|
2609
|
+
"iconVariant": "registry",
|
|
2610
|
+
"title": "The Semantic Brain. 🧠",
|
|
2611
|
+
"description": "We reject hardcoded Union Types. The Kernel defines an open registry where independent modules inject their DNA via Zod schemas. This provides the AI with a precise, type-safe vocabulary to build brand-compliant interfaces. Because the registry is the Single Source of Truth, the AI knows exactly which components exist and how to configure them without ever touching the core code.",
|
|
2612
|
+
"tag": "The Vocabulary",
|
|
2613
|
+
"tagVariant": "pattern"
|
|
2614
|
+
},
|
|
2615
|
+
{
|
|
2616
|
+
"icon": "zap",
|
|
2617
|
+
"iconVariant": "federation",
|
|
2618
|
+
"title": "The 5-Minute Tenant. 🤖",
|
|
2619
|
+
"description": "AI doesn't guess; it follows the Protocol. Because our ecosystem is governed by 5 deterministic standards, agents like Claude can project a complex, multi-page, brand-compliant tenant in under 5 minutes. The result is 100% Type-Safe JSON that perfectly matches your schemas, delivering a production-ready site with zero technical drift and an instant polymorphic CMS.",
|
|
2620
|
+
"tag": "The Multiplier",
|
|
2621
|
+
"tagVariant": "enterprise"
|
|
2622
|
+
}
|
|
2623
|
+
]
|
|
2624
|
+
},
|
|
2625
|
+
"settings": {}
|
|
2626
|
+
},
|
|
2627
|
+
{
|
|
2628
|
+
"id": "layered-architecture",
|
|
2629
|
+
"type": "arch-layers",
|
|
2630
|
+
"data": {
|
|
2631
|
+
"anchorId": "layers",
|
|
2632
|
+
"label": "Engineering Layers",
|
|
2633
|
+
"title": "Strict Boundaries. Clean Contracts.",
|
|
2634
|
+
"description": "Three architectural layers maintain the separation between engine and implementation.",
|
|
2635
|
+
"layers": [
|
|
2636
|
+
{
|
|
2637
|
+
"number": "0",
|
|
2638
|
+
"layerLevel": "l0",
|
|
2639
|
+
"title": "The Immutable Kernel",
|
|
2640
|
+
"description": "Defines the base structure of a Section — ID, Type, Payload, Settings — and exports the computed union. Zero knowledge of UI implementation or business logic."
|
|
2641
|
+
},
|
|
2642
|
+
{
|
|
2643
|
+
"number": "1",
|
|
2644
|
+
"layerLevel": "l1",
|
|
2645
|
+
"title": "The Standard Library",
|
|
2646
|
+
"description": "Fundamental components (Hero, Text, Grid) used across 90% of projects. Augments the Kernel's registry while remaining part of the internal ecosystem."
|
|
2647
|
+
},
|
|
2648
|
+
{
|
|
2649
|
+
"number": "2",
|
|
2650
|
+
"layerLevel": "l2",
|
|
2651
|
+
"title": "User-Land Extensions",
|
|
2652
|
+
"description": "The enabling layer. Third-party developers define specialized blocks — StockTickers, CRM Forms — in their own repositories. These extensions plug into the Kernel at compile-time."
|
|
2653
|
+
}
|
|
2654
|
+
],
|
|
2655
|
+
"codeFilename": "libs/shared-data/src/lib/core.ts",
|
|
2656
|
+
"codeLines": [
|
|
2657
|
+
{
|
|
2658
|
+
"content": "// 🛡️ KERNEL — Single Source of Truth",
|
|
2659
|
+
"tokenType": "comment"
|
|
2660
|
+
},
|
|
2661
|
+
{
|
|
2662
|
+
"content": "",
|
|
2663
|
+
"tokenType": "plain"
|
|
2664
|
+
},
|
|
2665
|
+
{
|
|
2666
|
+
"content": "export interface SectionDataRegistry {",
|
|
2667
|
+
"tokenType": "keyword"
|
|
2668
|
+
},
|
|
2669
|
+
{
|
|
2670
|
+
"content": " // Open Registry: modules inject here",
|
|
2671
|
+
"tokenType": "comment"
|
|
2672
|
+
},
|
|
2673
|
+
{
|
|
2674
|
+
"content": "}",
|
|
2675
|
+
"tokenType": "plain"
|
|
2676
|
+
},
|
|
2677
|
+
{
|
|
2678
|
+
"content": "",
|
|
2679
|
+
"tokenType": "plain"
|
|
2680
|
+
},
|
|
2681
|
+
{
|
|
2682
|
+
"content": "export interface BaseSection<K extends keyof SectionDataRegistry> {",
|
|
2683
|
+
"tokenType": "keyword"
|
|
2684
|
+
},
|
|
2685
|
+
{
|
|
2686
|
+
"content": " id: string;",
|
|
2687
|
+
"tokenType": "type"
|
|
2688
|
+
},
|
|
2689
|
+
{
|
|
2690
|
+
"content": " type: K;",
|
|
2691
|
+
"tokenType": "type"
|
|
2692
|
+
},
|
|
2693
|
+
{
|
|
2694
|
+
"content": " data: SectionDataRegistry[K];",
|
|
2695
|
+
"tokenType": "type"
|
|
2696
|
+
},
|
|
2697
|
+
{
|
|
2698
|
+
"content": " settings?: SectionSettings;",
|
|
2699
|
+
"tokenType": "type"
|
|
2700
|
+
},
|
|
2701
|
+
{
|
|
2702
|
+
"content": "}",
|
|
2703
|
+
"tokenType": "plain"
|
|
2704
|
+
},
|
|
2705
|
+
{
|
|
2706
|
+
"content": "",
|
|
2707
|
+
"tokenType": "plain"
|
|
2708
|
+
},
|
|
2709
|
+
{
|
|
2710
|
+
"content": "// Computed Union — built automatically from registry",
|
|
2711
|
+
"tokenType": "comment"
|
|
2712
|
+
},
|
|
2713
|
+
{
|
|
2714
|
+
"content": "export type Section =",
|
|
2715
|
+
"tokenType": "keyword"
|
|
2716
|
+
},
|
|
2717
|
+
{
|
|
2718
|
+
"content": " { [K in keyof SectionDataRegistry]: BaseSection<K> }",
|
|
2719
|
+
"tokenType": "type"
|
|
2720
|
+
},
|
|
2721
|
+
{
|
|
2722
|
+
"content": " [keyof SectionDataRegistry];",
|
|
2723
|
+
"tokenType": "operator"
|
|
2724
|
+
}
|
|
2725
|
+
]
|
|
2726
|
+
},
|
|
2727
|
+
"settings": {}
|
|
2728
|
+
},
|
|
2729
|
+
{
|
|
2730
|
+
"id": "product-triad",
|
|
2731
|
+
"type": "product-triad",
|
|
2732
|
+
"data": {
|
|
2733
|
+
"anchorId": "products",
|
|
2734
|
+
"label": "Product Triad",
|
|
2735
|
+
"title": "One Protocol. Three Products.",
|
|
2736
|
+
"description": "From solo developers to global enterprises — the same underlying ontology powers every tier.",
|
|
2737
|
+
"products": [
|
|
2738
|
+
{
|
|
2739
|
+
"tier": "Starter",
|
|
2740
|
+
"name": "JsonPage",
|
|
2741
|
+
"price": "NPM",
|
|
2742
|
+
"priceSuffix": "Local Install",
|
|
2743
|
+
"delivery": "Static Export · Zero Runtime",
|
|
2744
|
+
"features": [
|
|
2745
|
+
{
|
|
2746
|
+
"text": "Local Authoring SDK"
|
|
2747
|
+
},
|
|
2748
|
+
{
|
|
2749
|
+
"text": "Zero-Runtime HTML Bake"
|
|
2750
|
+
},
|
|
2751
|
+
{
|
|
2752
|
+
"text": "Pure HTML/CSS Export"
|
|
2753
|
+
},
|
|
2754
|
+
{
|
|
2755
|
+
"text": "CDN-Ready Delivery"
|
|
2756
|
+
},
|
|
2757
|
+
{
|
|
2758
|
+
"text": "Full Code Ownership"
|
|
2759
|
+
}
|
|
2760
|
+
],
|
|
2761
|
+
"featured": false
|
|
2762
|
+
},
|
|
2763
|
+
{
|
|
2764
|
+
"tier": "Professional",
|
|
2765
|
+
"name": "JsonPages",
|
|
2766
|
+
"price": "SaaS",
|
|
2767
|
+
"priceSuffix": "/month",
|
|
2768
|
+
"delivery": "Managed Cloud · Multi-Tenant",
|
|
2769
|
+
"features": [
|
|
2770
|
+
{
|
|
2771
|
+
"text": "Multi-Tenant Hosting"
|
|
2772
|
+
},
|
|
2773
|
+
{
|
|
2774
|
+
"text": "Premium Block Library"
|
|
2775
|
+
},
|
|
2776
|
+
{
|
|
2777
|
+
"text": "SchemaUI Components"
|
|
2778
|
+
},
|
|
2779
|
+
{
|
|
2780
|
+
"text": "In-Context Editing"
|
|
2781
|
+
},
|
|
2782
|
+
{
|
|
2783
|
+
"text": "AI-Native Protocol"
|
|
2784
|
+
},
|
|
2785
|
+
{
|
|
2786
|
+
"text": "Tailwind v4 & BI Engine"
|
|
2787
|
+
}
|
|
2788
|
+
],
|
|
2789
|
+
"featured": false
|
|
2790
|
+
},
|
|
2791
|
+
{
|
|
2792
|
+
"tier": "Enterprise",
|
|
2793
|
+
"name": "The Platform",
|
|
2794
|
+
"price": "Custom",
|
|
2795
|
+
"delivery": "Private Cloud · Enterprise Governance",
|
|
2796
|
+
"features": [
|
|
2797
|
+
{
|
|
2798
|
+
"text": "Private Federated Registry"
|
|
2799
|
+
},
|
|
2800
|
+
{
|
|
2801
|
+
"text": "Module Federation"
|
|
2802
|
+
},
|
|
2803
|
+
{
|
|
2804
|
+
"text": "Runtime Component Injection"
|
|
2805
|
+
},
|
|
2806
|
+
{
|
|
2807
|
+
"text": "Custom Brand Guidelines"
|
|
2808
|
+
},
|
|
2809
|
+
{
|
|
2810
|
+
"text": "Dedicated SLA & Support"
|
|
2811
|
+
},
|
|
2812
|
+
{
|
|
2813
|
+
"text": "SSO & RBAC"
|
|
2814
|
+
}
|
|
2815
|
+
],
|
|
2816
|
+
"featured": false
|
|
2817
|
+
}
|
|
2818
|
+
]
|
|
2819
|
+
},
|
|
2820
|
+
"settings": {}
|
|
2821
|
+
},
|
|
2822
|
+
{
|
|
2823
|
+
"id": "pa-ready",
|
|
2824
|
+
"type": "pa-section",
|
|
2825
|
+
"data": {
|
|
2826
|
+
"anchorId": "pa-ready",
|
|
2827
|
+
"label": "Public Sector",
|
|
2828
|
+
"title": "PA Ready — One Platform, Two Markets",
|
|
2829
|
+
"subtitle": "The Only Builder with Native Bootstrap Italia.",
|
|
2830
|
+
"paragraphs": [
|
|
2831
|
+
{
|
|
2832
|
+
"text": "By switching the rendering engine to Bootstrap Italia, System Integrators use the same high-efficiency workflow to deliver WCAG-compliant sites for Municipalities and Government bodies — without rewriting backend logic."
|
|
2833
|
+
},
|
|
2834
|
+
{
|
|
2835
|
+
"text": "The same JSON ontology drives both the Tailwind-powered private sector and the Bootstrap Italia public sector pipeline. This is not flexibility — this is Business Continuity."
|
|
2836
|
+
}
|
|
2837
|
+
],
|
|
2838
|
+
"badges": [
|
|
2839
|
+
{
|
|
2840
|
+
"label": "PNRR Ready"
|
|
2841
|
+
},
|
|
2842
|
+
{
|
|
2843
|
+
"label": "WCAG 2.1 AA"
|
|
2844
|
+
},
|
|
2845
|
+
{
|
|
2846
|
+
"label": "AgID Compliant"
|
|
2847
|
+
}
|
|
2848
|
+
],
|
|
2849
|
+
"engines": [
|
|
2850
|
+
{
|
|
2851
|
+
"label": "Tailwind v4",
|
|
2852
|
+
"variant": "tailwind"
|
|
2853
|
+
},
|
|
2854
|
+
{
|
|
2855
|
+
"label": "Bootstrap Italia",
|
|
2856
|
+
"variant": "bootstrap"
|
|
2857
|
+
}
|
|
2858
|
+
],
|
|
2859
|
+
"codeSnippet": "{\n \"type\": \"hero\",\n \"data\": { \"title\": \"...\" },\n \"settings\": { \"engine\": \"auto\" }\n}"
|
|
2860
|
+
},
|
|
2861
|
+
"settings": {}
|
|
2862
|
+
},
|
|
2863
|
+
{
|
|
2864
|
+
"id": "philosophy",
|
|
2865
|
+
"type": "philosophy",
|
|
2866
|
+
"data": {
|
|
2867
|
+
"anchorId": "philosophy",
|
|
2868
|
+
"label": "Our Philosophy",
|
|
2869
|
+
"title": "Governance Over Captivity",
|
|
2870
|
+
"quote": "We sell the infrastructure to manage UI — not the right to access the code.",
|
|
2871
|
+
"quoteHighlightWord": "manage",
|
|
2872
|
+
"description": "Unlike closed-garden platforms, JsonPages provides an Eject Button by design. The Bake Engine exports your site as pure HTML/CSS with zero backend requirements. If you leave the SaaS, the shared ontology and SDK ensure you remain fully operational and independent. We earn your loyalty through value — not lock-in."
|
|
2873
|
+
},
|
|
2874
|
+
"settings": {}
|
|
2875
|
+
},
|
|
2876
|
+
{
|
|
2877
|
+
"id": "cta-final",
|
|
2878
|
+
"type": "cta-banner",
|
|
2879
|
+
"data": {
|
|
2880
|
+
"anchorId": "start",
|
|
2881
|
+
"label": "Local Authoring Global Governance",
|
|
2882
|
+
"title": "Ready to Govern at Scale?",
|
|
2883
|
+
"description": "Whether you're building a single site or managing a portfolio of hundreds — JsonPages scales with your ambition."
|
|
2884
|
+
},
|
|
2885
|
+
"settings": {}
|
|
2886
|
+
}
|
|
2887
|
+
]
|
|
2868
2888
|
}
|
|
2869
2889
|
END_OF_FILE_CONTENT
|
|
2870
2890
|
# SKIP: src/data/pages/home.json:Zone.Identifier è un file binario e non può essere convertito in testo.
|
|
@@ -3274,6 +3294,72 @@ export const CtaSchema = z.object({
|
|
|
3274
3294
|
variant: z.enum(['primary', 'secondary']).default('primary').describe('ui:select'),
|
|
3275
3295
|
});
|
|
3276
3296
|
|
|
3297
|
+
END_OF_FILE_CONTENT
|
|
3298
|
+
echo "Creating src/lib/draftStorage.ts..."
|
|
3299
|
+
cat << 'END_OF_FILE_CONTENT' > "src/lib/draftStorage.ts"
|
|
3300
|
+
/**
|
|
3301
|
+
* Tenant draft storage — same key and shape as @jsonpages/core autosave.
|
|
3302
|
+
* Load from localStorage when present, otherwise use file-backed data.
|
|
3303
|
+
*/
|
|
3304
|
+
|
|
3305
|
+
import type { PageConfig, SiteConfig } from '@/types';
|
|
3306
|
+
|
|
3307
|
+
const DRAFT_KEY_PREFIX = 'jsonpages-draft';
|
|
3308
|
+
|
|
3309
|
+
export function getDraftStorageKey(tenantId: string, slug: string): string {
|
|
3310
|
+
return `${DRAFT_KEY_PREFIX}-${tenantId}-${slug}`;
|
|
3311
|
+
}
|
|
3312
|
+
|
|
3313
|
+
export interface StoredDraft {
|
|
3314
|
+
page?: PageConfig;
|
|
3315
|
+
site?: SiteConfig;
|
|
3316
|
+
}
|
|
3317
|
+
|
|
3318
|
+
export function readDraftFromStorage(
|
|
3319
|
+
tenantId: string,
|
|
3320
|
+
slug: string
|
|
3321
|
+
): StoredDraft | null {
|
|
3322
|
+
if (typeof window === 'undefined') return null;
|
|
3323
|
+
try {
|
|
3324
|
+
const key = getDraftStorageKey(tenantId, slug);
|
|
3325
|
+
const raw = localStorage.getItem(key);
|
|
3326
|
+
if (!raw) return null;
|
|
3327
|
+
return JSON.parse(raw) as StoredDraft;
|
|
3328
|
+
} catch {
|
|
3329
|
+
return null;
|
|
3330
|
+
}
|
|
3331
|
+
}
|
|
3332
|
+
|
|
3333
|
+
export interface HydratedData {
|
|
3334
|
+
pages: Record<string, PageConfig>;
|
|
3335
|
+
siteConfig: SiteConfig;
|
|
3336
|
+
}
|
|
3337
|
+
|
|
3338
|
+
/**
|
|
3339
|
+
* Build pages and siteConfig from localStorage when a draft exists for a slug,
|
|
3340
|
+
* otherwise use file-backed data. Uses the same storage key as Core autosave.
|
|
3341
|
+
*/
|
|
3342
|
+
export function getHydratedData(
|
|
3343
|
+
tenantId: string,
|
|
3344
|
+
filePages: Record<string, PageConfig>,
|
|
3345
|
+
fileSiteConfig: SiteConfig
|
|
3346
|
+
): HydratedData {
|
|
3347
|
+
let siteConfig = fileSiteConfig;
|
|
3348
|
+
const pages: Record<string, PageConfig> = {};
|
|
3349
|
+
|
|
3350
|
+
for (const slug of Object.keys(filePages)) {
|
|
3351
|
+
const stored = readDraftFromStorage(tenantId, slug);
|
|
3352
|
+
if (stored?.page) {
|
|
3353
|
+
pages[slug] = stored.page;
|
|
3354
|
+
if (stored?.site) siteConfig = stored.site;
|
|
3355
|
+
} else {
|
|
3356
|
+
pages[slug] = filePages[slug];
|
|
3357
|
+
}
|
|
3358
|
+
}
|
|
3359
|
+
|
|
3360
|
+
return { pages, siteConfig };
|
|
3361
|
+
}
|
|
3362
|
+
|
|
3277
3363
|
END_OF_FILE_CONTENT
|
|
3278
3364
|
echo "Creating src/lib/schemas.ts..."
|
|
3279
3365
|
cat << 'END_OF_FILE_CONTENT' > "src/lib/schemas.ts"
|
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -138,7 +138,7 @@ program
|
|
|
138
138
|
spinner.start('Installing dependencies (this may take a minute)...');
|
|
139
139
|
|
|
140
140
|
const deps = [
|
|
141
|
-
'react', 'react-dom', 'zod
|
|
141
|
+
'react', 'react-dom', 'zod', 'react-router-dom',
|
|
142
142
|
'lucide-react', 'radix-ui',
|
|
143
143
|
'tailwind-merge', 'clsx',
|
|
144
144
|
'file-saver', 'jszip',
|