@olonjs/cli 3.0.108 → 3.0.110
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 +1535 -191
- package/assets/templates/agritourism/src_tenant.sh +1 -1
- package/assets/templates/alpha/src_tenant.sh +1535 -191
- package/package.json +1 -1
|
@@ -1607,11 +1607,9 @@ cat << 'END_OF_FILE_CONTENT' > "index.html"
|
|
|
1607
1607
|
<meta charset="UTF-8" />
|
|
1608
1608
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
1609
1609
|
<meta name="description" content="Olon — Agentic Content Infrastructure" />
|
|
1610
|
-
<link rel="
|
|
1611
|
-
<link href="https://
|
|
1612
|
-
<link href="https://
|
|
1613
|
-
<link href="https://fonts.googleapis.com/css2?family=Fraunces:ital,wght@0,300;0,500;0,700;1,300;1,500;1,700&display=swap" rel="stylesheet" />
|
|
1614
|
-
<link href="https://cdn.jsdelivr.net/npm/@fontsource-variable/merriweather@5.2.6/wdth.css" rel="stylesheet" />
|
|
1610
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
1611
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
1612
|
+
<link href="https://fonts.googleapis.com/css2?family=Geist+Mono:wght@100..900&family=Instrument+Sans:ital,wght@0,400..700;1,400..700&family=Merriweather:ital,opsz,wght@0,18..144,300..900;1,18..144,300..900&display=swap" rel="stylesheet">
|
|
1615
1613
|
<title>Olon</title>
|
|
1616
1614
|
</head>
|
|
1617
1615
|
<body>
|
|
@@ -1646,7 +1644,7 @@ cat << 'END_OF_FILE_CONTENT' > "package.json"
|
|
|
1646
1644
|
"@tiptap/extension-link": "^2.11.5",
|
|
1647
1645
|
"@tiptap/react": "^2.11.5",
|
|
1648
1646
|
"@tiptap/starter-kit": "^2.11.5",
|
|
1649
|
-
"@olonjs/core": "^1.0.
|
|
1647
|
+
"@olonjs/core": "^1.0.97",
|
|
1650
1648
|
"class-variance-authority": "^0.7.1",
|
|
1651
1649
|
"clsx": "^2.1.1",
|
|
1652
1650
|
"lucide-react": "^0.474.0",
|
|
@@ -2079,6 +2077,10 @@ const webMcpBuildState = getWebMcpBuildState();
|
|
|
2079
2077
|
for (const { slug } of targets) {
|
|
2080
2078
|
const pageConfig = webMcpBuildState.pages[slug];
|
|
2081
2079
|
if (!pageConfig) continue;
|
|
2080
|
+
|
|
2081
|
+
// Export the raw JSON data for the agentic web (so readResource works on SSG)
|
|
2082
|
+
await writeJsonTargets(`pages/${slug}.json`, pageConfig);
|
|
2083
|
+
|
|
2082
2084
|
const contract = buildPageContract({
|
|
2083
2085
|
slug,
|
|
2084
2086
|
pageConfig,
|
|
@@ -2095,6 +2097,9 @@ for (const { slug } of targets) {
|
|
|
2095
2097
|
await writeJsonTargets(buildPageManifestHref(slug).replace(/^\//, ''), pageManifest);
|
|
2096
2098
|
}
|
|
2097
2099
|
|
|
2100
|
+
// Export the site config for the agentic web
|
|
2101
|
+
await writeJsonTargets('config/site.json', webMcpBuildState.siteConfig);
|
|
2102
|
+
|
|
2098
2103
|
const mcpManifest = buildSiteManifest({
|
|
2099
2104
|
pages: webMcpBuildState.pages,
|
|
2100
2105
|
schemas: webMcpBuildState.schemas,
|
|
@@ -4134,7 +4139,7 @@ export function OlonMark({ size = 32, className }: OlonMarkProps) {
|
|
|
4134
4139
|
|
|
4135
4140
|
// Dark: nucleus = Parchment #E2D5B0 (warm, human)
|
|
4136
4141
|
// Light: nucleus = Primary #1E1814 (brand, on white bg)
|
|
4137
|
-
const nucleusFill = theme === 'dark' ? '#
|
|
4142
|
+
const nucleusFill = theme === 'dark' ? '#F4F3EF' : '#080808'
|
|
4138
4143
|
|
|
4139
4144
|
return (
|
|
4140
4145
|
<svg
|
|
@@ -4146,8 +4151,8 @@ export function OlonMark({ size = 32, className }: OlonMarkProps) {
|
|
|
4146
4151
|
>
|
|
4147
4152
|
<defs>
|
|
4148
4153
|
<linearGradient id="olon-ring" x1="0" y1="0" x2="0" y2="1">
|
|
4149
|
-
<stop offset="0%" stopColor="#
|
|
4150
|
-
<stop offset="100%" stopColor="#
|
|
4154
|
+
<stop offset="0%" stopColor="#84ABFF" />
|
|
4155
|
+
<stop offset="100%" stopColor="#0F52E0" />
|
|
4151
4156
|
</linearGradient>
|
|
4152
4157
|
</defs>
|
|
4153
4158
|
<circle cx="50" cy="50" r="38" stroke="url(#olon-ring)" strokeWidth="20" />
|
|
@@ -6048,8 +6053,8 @@ export function Header({ data, settings, menu }: HeaderViewProps) {
|
|
|
6048
6053
|
{/* Logo */}
|
|
6049
6054
|
<a href="/" className="flex items-center gap-2 shrink-0" aria-label="OlonJS home">
|
|
6050
6055
|
<OlonMark size={26} className="mb-0.5" />
|
|
6051
|
-
<span
|
|
6052
|
-
className="text-2xl text-
|
|
6056
|
+
<div className="flex items-center gap-1"><span
|
|
6057
|
+
className="text-2xl text-foreground leading-none"
|
|
6053
6058
|
style={{
|
|
6054
6059
|
fontFamily: 'var(--wordmark-font)',
|
|
6055
6060
|
letterSpacing: 'var(--wordmark-tracking)',
|
|
@@ -6058,12 +6063,9 @@ export function Header({ data, settings, menu }: HeaderViewProps) {
|
|
|
6058
6063
|
}}
|
|
6059
6064
|
>
|
|
6060
6065
|
{data.logoText}
|
|
6061
|
-
|
|
6062
|
-
|
|
6063
|
-
|
|
6064
|
-
{data.badge}
|
|
6065
|
-
</span>
|
|
6066
|
-
)}
|
|
6066
|
+
</span>
|
|
6067
|
+
<span className="text-primary-light font-mono">{data.badge}</span>
|
|
6068
|
+
</div>
|
|
6067
6069
|
</a>
|
|
6068
6070
|
|
|
6069
6071
|
{/* Desktop nav */}
|
|
@@ -6334,6 +6336,7 @@ export type HeaderSettings = z.infer<typeof HeaderSettingsSchema>;
|
|
|
6334
6336
|
|
|
6335
6337
|
END_OF_FILE_CONTENT
|
|
6336
6338
|
mkdir -p "src/components/hero"
|
|
6339
|
+
# SKIP: src/components/hero/RadialBackground - Copy.tsx:Zone.Identifier is binary and cannot be embedded as text.
|
|
6337
6340
|
echo "Creating src/components/hero/RadialBackground.tsx..."
|
|
6338
6341
|
cat << 'END_OF_FILE_CONTENT' > "src/components/hero/RadialBackground.tsx"
|
|
6339
6342
|
import { useEffect, useRef, useState } from 'react';
|
|
@@ -6420,6 +6423,93 @@ export function RadialBackground({
|
|
|
6420
6423
|
);
|
|
6421
6424
|
}
|
|
6422
6425
|
|
|
6426
|
+
END_OF_FILE_CONTENT
|
|
6427
|
+
echo "Creating src/components/hero/RadialBackground.txt..."
|
|
6428
|
+
cat << 'END_OF_FILE_CONTENT' > "src/components/hero/RadialBackground.txt"
|
|
6429
|
+
import { useEffect, useRef, useState } from 'react';
|
|
6430
|
+
import { motion } from 'motion/react';
|
|
6431
|
+
|
|
6432
|
+
// CSS var names — order matches STOPS
|
|
6433
|
+
const TOKEN_VARS = [
|
|
6434
|
+
'--background', // #0B0907 center
|
|
6435
|
+
'--background', // #130F0D
|
|
6436
|
+
'--background', // #1E1814
|
|
6437
|
+
'--background', // #2E271F
|
|
6438
|
+
'--background', // #241D17
|
|
6439
|
+
'--elevated', // #1E1814
|
|
6440
|
+
'--background', // #0B0907 outer
|
|
6441
|
+
] as const;
|
|
6442
|
+
|
|
6443
|
+
const STOPS = [0, 30, 55, 72, 84, 93, 100] as const;
|
|
6444
|
+
|
|
6445
|
+
function readTokenColors(): string[] {
|
|
6446
|
+
if (typeof document === 'undefined') return TOKEN_VARS.map(() => '#000');
|
|
6447
|
+
const s = getComputedStyle(document.documentElement);
|
|
6448
|
+
return TOKEN_VARS.map((v) => s.getPropertyValue(v).trim() || '#000');
|
|
6449
|
+
}
|
|
6450
|
+
|
|
6451
|
+
export function RadialBackground({
|
|
6452
|
+
startingGap =80,
|
|
6453
|
+
breathing = true,
|
|
6454
|
+
animationSpeed = 0.01,
|
|
6455
|
+
breathingRange = 180,
|
|
6456
|
+
topOffset = 0,
|
|
6457
|
+
}: {
|
|
6458
|
+
startingGap?: number;
|
|
6459
|
+
breathing?: boolean;
|
|
6460
|
+
animationSpeed?: number;
|
|
6461
|
+
breathingRange?: number;
|
|
6462
|
+
topOffset?: number;
|
|
6463
|
+
}) {
|
|
6464
|
+
const containerRef = useRef<HTMLDivElement | null>(null);
|
|
6465
|
+
const [colors, setColors] = useState<string[]>(() => readTokenColors());
|
|
6466
|
+
|
|
6467
|
+
// Re-read tokens when data-theme changes (dark ↔ light)
|
|
6468
|
+
useEffect(() => {
|
|
6469
|
+
setColors(readTokenColors());
|
|
6470
|
+
const observer = new MutationObserver(() => setColors(readTokenColors()));
|
|
6471
|
+
observer.observe(document.documentElement, {
|
|
6472
|
+
attributes: true,
|
|
6473
|
+
attributeFilter: ['data-theme'],
|
|
6474
|
+
});
|
|
6475
|
+
return () => observer.disconnect();
|
|
6476
|
+
}, []);
|
|
6477
|
+
|
|
6478
|
+
useEffect(() => {
|
|
6479
|
+
let animationFrame: number;
|
|
6480
|
+
let width = startingGap;
|
|
6481
|
+
let direction = 1;
|
|
6482
|
+
|
|
6483
|
+
const animate = () => {
|
|
6484
|
+
if (width >= startingGap + breathingRange) direction = -1;
|
|
6485
|
+
if (width <= startingGap - breathingRange) direction = 1;
|
|
6486
|
+
if (!breathing) direction = 0;
|
|
6487
|
+
width += direction * animationSpeed;
|
|
6488
|
+
|
|
6489
|
+
const stops = STOPS.map((s, i) => `${colors[i]} ${s}%`).join(', ');
|
|
6490
|
+
const gradient = `radial-gradient(${width}% ${width + topOffset}% at 50% 20%, ${stops})`;
|
|
6491
|
+
|
|
6492
|
+
if (containerRef.current) {
|
|
6493
|
+
containerRef.current.style.background = gradient;
|
|
6494
|
+
}
|
|
6495
|
+
animationFrame = requestAnimationFrame(animate);
|
|
6496
|
+
};
|
|
6497
|
+
|
|
6498
|
+
animationFrame = requestAnimationFrame(animate);
|
|
6499
|
+
return () => cancelAnimationFrame(animationFrame);
|
|
6500
|
+
}, [startingGap, breathing, animationSpeed, breathingRange, topOffset, colors]);
|
|
6501
|
+
|
|
6502
|
+
return (
|
|
6503
|
+
<motion.div
|
|
6504
|
+
animate={{ opacity: 1, scale: 1, transition: { duration: 2, ease: [0.25, 0.1, 0.25, 1] } }}
|
|
6505
|
+
className="absolute inset-0 overflow-hidden"
|
|
6506
|
+
initial={{ opacity: 0, scale: 1.5 }}
|
|
6507
|
+
>
|
|
6508
|
+
<div className="absolute inset-0" ref={containerRef} />
|
|
6509
|
+
</motion.div>
|
|
6510
|
+
);
|
|
6511
|
+
}
|
|
6512
|
+
|
|
6423
6513
|
END_OF_FILE_CONTENT
|
|
6424
6514
|
echo "Creating src/components/hero/View.tsx..."
|
|
6425
6515
|
cat << 'END_OF_FILE_CONTENT' > "src/components/hero/View.tsx"
|
|
@@ -6463,11 +6553,11 @@ export function Hero({ data, settings }: HeroViewProps) {
|
|
|
6463
6553
|
)}
|
|
6464
6554
|
|
|
6465
6555
|
{/* Headline */}
|
|
6466
|
-
<h1 className="font-display font-
|
|
6556
|
+
<h1 className="font-display font-bold text-7xl text-foreground leading-tight tracking-tight mb-1" data-jp-field="title">
|
|
6467
6557
|
{data.title}
|
|
6468
6558
|
</h1>
|
|
6469
6559
|
{data.titleHighlight && (
|
|
6470
|
-
<h2 className="font-display font-normal italic text-5xl md:text-6xl text-primary-light leading-tight tracking-
|
|
6560
|
+
<h2 className="font-display font-normal italic text-5xl md:text-6xl text-primary-light leading-tight tracking-tight mb-7" data-jp-field="titleHighlight">
|
|
6471
6561
|
{data.titleHighlight}
|
|
6472
6562
|
</h2>
|
|
6473
6563
|
)}
|
|
@@ -6800,6 +6890,969 @@ import { LoginSchema, LoginSettingsSchema } from './schema';
|
|
|
6800
6890
|
export type LoginData = z.infer<typeof LoginSchema>;
|
|
6801
6891
|
export type LoginSettings = z.infer<typeof LoginSettingsSchema>;
|
|
6802
6892
|
|
|
6893
|
+
END_OF_FILE_CONTENT
|
|
6894
|
+
mkdir -p "src/components/olon-architecture"
|
|
6895
|
+
echo "Creating src/components/olon-architecture/View.tsx..."
|
|
6896
|
+
cat << 'END_OF_FILE_CONTENT' > "src/components/olon-architecture/View.tsx"
|
|
6897
|
+
import type { OlonArchitectureData } from './types';
|
|
6898
|
+
|
|
6899
|
+
const ICONS: Record<string, React.ReactNode> = {
|
|
6900
|
+
mtrp: (
|
|
6901
|
+
<svg width="32" height="32" viewBox="0 0 200 200" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
6902
|
+
<defs><linearGradient id="am" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stopColor="#84ABFF"/><stop offset="1" stopColor="#0F52E0"/></linearGradient><linearGradient id="amc" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stopColor="#EEF3FF"/><stop offset="1" stopColor="#84ABFF"/></linearGradient></defs>
|
|
6903
|
+
<rect x="25" y="30" width="130" height="140" rx="10" fill="none" stroke="url(#am)" strokeWidth="7"/>
|
|
6904
|
+
<line x1="25" y1="60" x2="155" y2="60" stroke="url(#am)" strokeWidth="5"/>
|
|
6905
|
+
<path fill="none" stroke="url(#am)" strokeLinecap="round" strokeLinejoin="round" strokeWidth="4.5" d="M72,42 c-5,0 -8,2 -8,6v2c0,4 -3,5 -6,5 3,0 6,1 6,5v2c0,4 3,6 8,6"/>
|
|
6906
|
+
<path fill="none" stroke="url(#am)" strokeLinecap="round" strokeLinejoin="round" strokeWidth="4.5" d="M108,42 c5,0 8,2 8,6v2c0,4 3,5 6,5 -3,0 -6,1 -6,5v2c0,4 -3,6 -8,6"/>
|
|
6907
|
+
<circle fill="url(#am)" opacity="0.35" cx="46" cy="90" r="4.5"/>
|
|
6908
|
+
<rect fill="url(#am)" opacity="0.35" x="59" y="86.5" width="68" height="7" rx="3.5"/>
|
|
6909
|
+
<circle fill="url(#amc)" cx="46" cy="117" r="6.5"/>
|
|
6910
|
+
<rect fill="url(#amc)" x="59" y="113" width="82" height="8" rx="4"/>
|
|
6911
|
+
<circle fill="url(#am)" opacity="0.55" cx="46" cy="145" r="4.5"/>
|
|
6912
|
+
<rect fill="url(#am)" opacity="0.55" x="59" y="141.5" width="50" height="7" rx="3.5"/>
|
|
6913
|
+
<path fill="none" stroke="url(#amc)" strokeLinecap="round" strokeWidth="5" d="M192,117 h-35"/>
|
|
6914
|
+
<path fill="none" stroke="url(#amc)" strokeLinecap="round" strokeLinejoin="round" strokeWidth="5" d="M170,108 l17,9 -17,9"/>
|
|
6915
|
+
</svg>
|
|
6916
|
+
),
|
|
6917
|
+
tbp: (
|
|
6918
|
+
<svg width="32" height="32" viewBox="0 0 200 200" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
6919
|
+
<defs><linearGradient id="at" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stopColor="#84ABFF"/><stop offset="1" stopColor="#0F52E0"/></linearGradient><linearGradient id="atc" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stopColor="#EEF3FF"/><stop offset="1" stopColor="#84ABFF"/></linearGradient></defs>
|
|
6920
|
+
<rect fill="none" stroke="url(#at)" strokeWidth="5.5" strokeLinejoin="round" opacity="0.3" x="65" y="22" width="108" height="74" rx="9"/>
|
|
6921
|
+
<rect fill="none" stroke="url(#at)" strokeWidth="5.5" strokeLinejoin="round" opacity="0.6" x="46" y="50" width="108" height="74" rx="9"/>
|
|
6922
|
+
<rect fill="none" stroke="url(#at)" strokeWidth="6.5" strokeLinejoin="round" x="27" y="78" width="108" height="74" rx="9"/>
|
|
6923
|
+
<rect fill="url(#at)" opacity="0.6" x="42" y="101" width="52" height="6" rx="3"/>
|
|
6924
|
+
<rect fill="url(#atc)" x="42" y="116" width="36" height="6" rx="3"/>
|
|
6925
|
+
<circle fill="url(#at)" opacity="0.3" cx="162" cy="33" r="4"/>
|
|
6926
|
+
<circle fill="url(#at)" opacity="0.6" cx="143" cy="61" r="4"/>
|
|
6927
|
+
<circle fill="url(#atc)" cx="124" cy="89" r="5"/>
|
|
6928
|
+
</svg>
|
|
6929
|
+
),
|
|
6930
|
+
jsp: (
|
|
6931
|
+
<svg width="32" height="32" viewBox="0 0 200 200" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
6932
|
+
<defs><linearGradient id="aj" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stopColor="#84ABFF"/><stop offset="1" stopColor="#0F52E0"/></linearGradient><linearGradient id="ajc" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stopColor="#EEF3FF"/><stop offset="1" stopColor="#84ABFF"/></linearGradient></defs>
|
|
6933
|
+
<rect fill="none" stroke="url(#aj)" strokeWidth="7" strokeLinejoin="round" x="14" y="22" width="172" height="128" rx="12"/>
|
|
6934
|
+
<line x1="14" y1="52" x2="186" y2="52" stroke="url(#aj)" strokeWidth="5"/>
|
|
6935
|
+
<circle fill="url(#aj)" opacity="0.4" cx="34" cy="37" r="5"/>
|
|
6936
|
+
<circle fill="url(#aj)" opacity="0.6" cx="52" cy="37" r="5"/>
|
|
6937
|
+
<circle fill="url(#ajc)" cx="70" cy="37" r="5"/>
|
|
6938
|
+
<path fill="none" stroke="url(#ajc)" strokeLinecap="round" strokeLinejoin="round" strokeWidth="6" d="M28,75 l12,11 -12,11"/>
|
|
6939
|
+
<rect fill="url(#ajc)" x="48" y="80" width="22" height="7" rx="3.5"/>
|
|
6940
|
+
<rect fill="url(#aj)" opacity="0.7" x="28" y="106" width="88" height="6" rx="3"/>
|
|
6941
|
+
<rect fill="url(#aj)" opacity="0.5" x="28" y="121" width="62" height="6" rx="3"/>
|
|
6942
|
+
<rect fill="url(#aj)" opacity="0.35" x="28" y="136" width="76" height="6" rx="3"/>
|
|
6943
|
+
</svg>
|
|
6944
|
+
),
|
|
6945
|
+
idac: (
|
|
6946
|
+
<svg width="32" height="32" viewBox="0 0 200 200" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
6947
|
+
<defs><linearGradient id="ai" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stopColor="#84ABFF"/><stop offset="1" stopColor="#0F52E0"/></linearGradient><linearGradient id="aic" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stopColor="#EEF3FF"/><stop offset="1" stopColor="#84ABFF"/></linearGradient></defs>
|
|
6948
|
+
<rect fill="none" stroke="url(#ai)" strokeWidth="6.5" strokeLinejoin="round" x="8" y="36" width="72" height="128" rx="9"/>
|
|
6949
|
+
<rect fill="url(#ai)" opacity="0.5" x="20" y="56" width="48" height="5.5" rx="2.75"/>
|
|
6950
|
+
<rect fill="url(#aic)" x="20" y="75" width="48" height="8" rx="4"/>
|
|
6951
|
+
<rect fill="url(#ai)" opacity="0.4" x="20" y="98" width="48" height="5.5" rx="2.75"/>
|
|
6952
|
+
<path fill="none" stroke="url(#aic)" strokeLinecap="round" strokeWidth="5.5" d="M80,100 h40"/>
|
|
6953
|
+
<circle fill="url(#aic)" cx="100" cy="100" r="5.5"/>
|
|
6954
|
+
<path fill="none" stroke="url(#ai)" strokeLinecap="round" strokeWidth="4" opacity="0.4" d="M80,75 h40"/>
|
|
6955
|
+
<path fill="none" stroke="url(#ai)" strokeLinecap="round" strokeWidth="4" opacity="0.4" d="M80,125 h40"/>
|
|
6956
|
+
<rect fill="none" stroke="url(#ai)" strokeWidth="6.5" strokeLinejoin="round" x="120" y="36" width="72" height="128" rx="9"/>
|
|
6957
|
+
<rect fill="url(#ai)" opacity="0.5" x="132" y="56" width="48" height="5.5" rx="2.75"/>
|
|
6958
|
+
<rect fill="url(#aic)" x="132" y="75" width="48" height="8" rx="4"/>
|
|
6959
|
+
<rect fill="url(#ai)" opacity="0.4" x="132" y="98" width="48" height="5.5" rx="2.75"/>
|
|
6960
|
+
</svg>
|
|
6961
|
+
),
|
|
6962
|
+
bsds: (
|
|
6963
|
+
<svg width="32" height="32" viewBox="0 0 200 200" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
6964
|
+
<defs><linearGradient id="ab" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stopColor="#84ABFF"/><stop offset="1" stopColor="#0F52E0"/></linearGradient><linearGradient id="abc" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stopColor="#EEF3FF"/><stop offset="1" stopColor="#84ABFF"/></linearGradient></defs>
|
|
6965
|
+
<rect fill="none" stroke="url(#ab)" strokeWidth="8" strokeLinejoin="round" x="16" y="152" width="168" height="32" rx="8"/>
|
|
6966
|
+
<circle fill="url(#abc)" cx="100" cy="168" r="7"/>
|
|
6967
|
+
<path fill="none" stroke="url(#ab)" strokeLinecap="round" strokeWidth="5" opacity="0.5" d="M54,138 v14"/>
|
|
6968
|
+
<path fill="none" stroke="url(#ab)" strokeLinecap="round" strokeWidth="5" opacity="0.5" d="M146,138 v14"/>
|
|
6969
|
+
<rect fill="none" stroke="url(#ab)" strokeWidth="6" strokeLinejoin="round" x="16" y="68" width="76" height="70" rx="9"/>
|
|
6970
|
+
<rect fill="url(#ab)" opacity="0.55" x="28" y="84" width="42" height="6" rx="3"/>
|
|
6971
|
+
<rect fill="url(#abc)" x="28" y="112" width="32" height="6" rx="3"/>
|
|
6972
|
+
<rect fill="none" stroke="url(#ab)" strokeWidth="6" strokeLinejoin="round" x="108" y="44" width="76" height="94" rx="9"/>
|
|
6973
|
+
<rect fill="url(#ab)" opacity="0.55" x="120" y="60" width="42" height="6" rx="3"/>
|
|
6974
|
+
<rect fill="url(#abc)" x="120" y="88" width="32" height="6" rx="3"/>
|
|
6975
|
+
</svg>
|
|
6976
|
+
),
|
|
6977
|
+
pss: (
|
|
6978
|
+
<svg width="32" height="32" viewBox="0 0 200 200" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
6979
|
+
<defs><linearGradient id="ap" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stopColor="#84ABFF"/><stop offset="1" stopColor="#0F52E0"/></linearGradient><linearGradient id="apc" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stopColor="#EEF3FF"/><stop offset="1" stopColor="#84ABFF"/></linearGradient></defs>
|
|
6980
|
+
<path fill="none" stroke="url(#apc)" strokeLinecap="round" strokeWidth="5.5" d="M100,32 L52,90"/>
|
|
6981
|
+
<path fill="none" stroke="url(#ap)" strokeLinecap="round" strokeWidth="5" opacity="0.3" d="M100,32 L148,90"/>
|
|
6982
|
+
<path fill="none" stroke="url(#ap)" strokeLinecap="round" strokeWidth="4.5" opacity="0.3" d="M52,90 L22,158"/>
|
|
6983
|
+
<path fill="none" stroke="url(#apc)" strokeLinecap="round" strokeWidth="5.5" d="M52,90 L90,158"/>
|
|
6984
|
+
<path fill="none" stroke="url(#ap)" strokeLinecap="round" strokeWidth="4" opacity="0.25" d="M148,90 L170,158"/>
|
|
6985
|
+
<circle fill="url(#apc)" cx="100" cy="22" r="11"/>
|
|
6986
|
+
<circle fill="url(#apc)" cx="52" cy="90" r="10"/>
|
|
6987
|
+
<circle fill="url(#ap)" opacity="0.3" cx="148" cy="90" r="8"/>
|
|
6988
|
+
<circle fill="url(#ap)" opacity="0.3" cx="22" cy="165" r="7"/>
|
|
6989
|
+
<circle fill="url(#apc)" cx="90" cy="165" r="11"/>
|
|
6990
|
+
<rect fill="none" stroke="url(#apc)" strokeWidth="4" strokeLinejoin="round" opacity="0.5" x="76" y="151" width="28" height="28" rx="5"/>
|
|
6991
|
+
</svg>
|
|
6992
|
+
),
|
|
6993
|
+
};
|
|
6994
|
+
|
|
6995
|
+
interface Props { data: OlonArchitectureData; }
|
|
6996
|
+
|
|
6997
|
+
export function OlonArchitectureView({ data }: Props) {
|
|
6998
|
+
return (
|
|
6999
|
+
<section
|
|
7000
|
+
style={{
|
|
7001
|
+
'--local-bg': 'var(--background)',
|
|
7002
|
+
'--local-fg': 'var(--foreground)',
|
|
7003
|
+
'--local-muted': 'var(--muted-foreground)',
|
|
7004
|
+
'--local-p400': 'var(--primary)',
|
|
7005
|
+
'--local-card': 'var(--card)',
|
|
7006
|
+
'--local-border':'var(--border)',
|
|
7007
|
+
} as React.CSSProperties}
|
|
7008
|
+
className="bg-[var(--local-bg)] text-[var(--local-fg)] py-24 border-t border-[var(--local-border)]"
|
|
7009
|
+
data-jp-section-id={data.id}
|
|
7010
|
+
data-jp-section-type="olon-architecture"
|
|
7011
|
+
>
|
|
7012
|
+
<div className="max-w-6xl mx-auto px-8">
|
|
7013
|
+
<p className="text-xs font-semibold tracking-[0.12em] uppercase text-[var(--local-muted)] mb-3"
|
|
7014
|
+
data-jp-field="label">{data.label}</p>
|
|
7015
|
+
<h2 className="text-4xl font-bold tracking-[-0.03em] text-white mb-3"
|
|
7016
|
+
data-jp-field="headline">{data.headline}</h2>
|
|
7017
|
+
<p className="text-base text-[var(--local-muted)] leading-relaxed max-w-2xl mb-3"
|
|
7018
|
+
data-jp-field="body">{data.body}</p>
|
|
7019
|
+
{data.specHref && (
|
|
7020
|
+
<p className="text-sm text-[var(--local-muted)] mb-12">
|
|
7021
|
+
Full specification:{' '}
|
|
7022
|
+
<a href={data.specHref} target="_blank" rel="noopener noreferrer"
|
|
7023
|
+
className="text-[var(--local-p400)] hover:underline">
|
|
7024
|
+
olonjsSpecs_V_1_5.md ↗
|
|
7025
|
+
</a>
|
|
7026
|
+
</p>
|
|
7027
|
+
)}
|
|
7028
|
+
|
|
7029
|
+
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 border border-[var(--local-border)] rounded-2xl overflow-hidden"
|
|
7030
|
+
data-jp-array="protocols">
|
|
7031
|
+
{data.protocols.map((p) => (
|
|
7032
|
+
<div key={p.id}
|
|
7033
|
+
className="bg-[var(--local-card)] p-7 flex flex-col gap-3 border-r border-b border-[var(--local-border)] hover:bg-[var(--elevated)] transition-colors"
|
|
7034
|
+
data-jp-item-id={p.id}>
|
|
7035
|
+
<div>{ICONS[p.icon]}</div>
|
|
7036
|
+
<p className="text-[11px] font-semibold tracking-[0.1em] uppercase text-[var(--local-p400)] font-mono"
|
|
7037
|
+
data-jp-field="version">{p.acronym} · {p.version}</p>
|
|
7038
|
+
<p className="font-bold text-white text-base" data-jp-field="name">{p.name}</p>
|
|
7039
|
+
<p className="text-sm text-[var(--local-muted)] leading-relaxed flex-1"
|
|
7040
|
+
data-jp-field="desc">{p.desc}</p>
|
|
7041
|
+
<a href={p.specHref} target="_blank" rel="noopener noreferrer"
|
|
7042
|
+
className="text-xs text-[var(--local-p400)] hover:text-white transition-colors mt-auto"
|
|
7043
|
+
data-jp-field="specHref">Read spec ↗</a>
|
|
7044
|
+
</div>
|
|
7045
|
+
))}
|
|
7046
|
+
</div>
|
|
7047
|
+
</div>
|
|
7048
|
+
</section>
|
|
7049
|
+
);
|
|
7050
|
+
}
|
|
7051
|
+
|
|
7052
|
+
END_OF_FILE_CONTENT
|
|
7053
|
+
echo "Creating src/components/olon-architecture/index.ts..."
|
|
7054
|
+
cat << 'END_OF_FILE_CONTENT' > "src/components/olon-architecture/index.ts"
|
|
7055
|
+
export { OlonArchitectureView as View } from './View';
|
|
7056
|
+
export { OlonArchitectureSchema } from './schema';
|
|
7057
|
+
export type { OlonArchitectureData } from './types';
|
|
7058
|
+
|
|
7059
|
+
END_OF_FILE_CONTENT
|
|
7060
|
+
echo "Creating src/components/olon-architecture/schema.ts..."
|
|
7061
|
+
cat << 'END_OF_FILE_CONTENT' > "src/components/olon-architecture/schema.ts"
|
|
7062
|
+
import { z } from 'zod';
|
|
7063
|
+
import { BaseSectionData, BaseArrayItem } from '@/lib/base-schemas';
|
|
7064
|
+
|
|
7065
|
+
export const ProtocolSchema = BaseArrayItem.extend({
|
|
7066
|
+
version: z.string(),
|
|
7067
|
+
acronym: z.string(),
|
|
7068
|
+
name: z.string(),
|
|
7069
|
+
desc: z.string(),
|
|
7070
|
+
specHref: z.string(),
|
|
7071
|
+
icon: z.enum(['mtrp', 'tbp', 'jsp', 'idac', 'bsds', 'pss']),
|
|
7072
|
+
});
|
|
7073
|
+
|
|
7074
|
+
export const OlonArchitectureSchema = BaseSectionData.extend({
|
|
7075
|
+
label: z.string().default('Architecture'),
|
|
7076
|
+
headline: z.string().default('Six governing protocols.'),
|
|
7077
|
+
body: z.string().default(''),
|
|
7078
|
+
specHref: z.string().default(''),
|
|
7079
|
+
protocols: z.array(ProtocolSchema).min(1).max(6),
|
|
7080
|
+
});
|
|
7081
|
+
|
|
7082
|
+
export type OlonArchitectureData = z.infer<typeof OlonArchitectureSchema>;
|
|
7083
|
+
|
|
7084
|
+
END_OF_FILE_CONTENT
|
|
7085
|
+
echo "Creating src/components/olon-architecture/types.ts..."
|
|
7086
|
+
cat << 'END_OF_FILE_CONTENT' > "src/components/olon-architecture/types.ts"
|
|
7087
|
+
export type { OlonArchitectureData } from './schema';
|
|
7088
|
+
|
|
7089
|
+
END_OF_FILE_CONTENT
|
|
7090
|
+
mkdir -p "src/components/olon-example"
|
|
7091
|
+
echo "Creating src/components/olon-example/View.tsx..."
|
|
7092
|
+
cat << 'END_OF_FILE_CONTENT' > "src/components/olon-example/View.tsx"
|
|
7093
|
+
import type { OlonExampleData } from './types';
|
|
7094
|
+
|
|
7095
|
+
interface Props { data: OlonExampleData; }
|
|
7096
|
+
|
|
7097
|
+
export function OlonExampleView({ data }: Props) {
|
|
7098
|
+
return (
|
|
7099
|
+
<section
|
|
7100
|
+
style={{
|
|
7101
|
+
'--local-bg': 'var(--background)',
|
|
7102
|
+
'--local-fg': 'var(--foreground)',
|
|
7103
|
+
'--local-muted': 'var(--muted-foreground)',
|
|
7104
|
+
'--local-p400': 'var(--primary)',
|
|
7105
|
+
'--local-p300': 'var(--primary-light)',
|
|
7106
|
+
'--local-card': 'var(--card)',
|
|
7107
|
+
'--local-border':'var(--border)',
|
|
7108
|
+
} as React.CSSProperties}
|
|
7109
|
+
className="bg-[var(--local-bg)] text-[var(--local-fg)] py-24 border-t border-[var(--local-border)]"
|
|
7110
|
+
data-jp-section-id={data.id}
|
|
7111
|
+
data-jp-section-type="olon-example"
|
|
7112
|
+
>
|
|
7113
|
+
<div className="max-w-6xl mx-auto px-8">
|
|
7114
|
+
<p className="text-xs font-semibold tracking-[0.12em] uppercase text-[var(--local-muted)] mb-3"
|
|
7115
|
+
data-jp-field="label">{data.label}</p>
|
|
7116
|
+
<h2 className="text-4xl font-bold tracking-[-0.03em] text-white mb-3"
|
|
7117
|
+
data-jp-field="headline">{data.headline}</h2>
|
|
7118
|
+
<p className="text-base text-[var(--local-muted)] leading-relaxed max-w-2xl mb-12"
|
|
7119
|
+
data-jp-field="body">{data.body}</p>
|
|
7120
|
+
|
|
7121
|
+
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
7122
|
+
{data.steps.map((step) => (
|
|
7123
|
+
<div key={step.number}
|
|
7124
|
+
className="bg-[var(--local-card)] border border-[var(--local-border)] rounded-2xl overflow-hidden">
|
|
7125
|
+
{/* Step header */}
|
|
7126
|
+
<div className="px-6 py-4 border-b border-[var(--local-border)] flex items-center gap-3">
|
|
7127
|
+
<span className="w-6 h-6 rounded-full bg-[var(--local-p400)] text-white text-xs font-bold flex items-center justify-center flex-shrink-0">
|
|
7128
|
+
{step.number}
|
|
7129
|
+
</span>
|
|
7130
|
+
<span className="font-semibold text-white text-sm">{step.title}</span>
|
|
7131
|
+
<span className="ml-auto text-xs text-[var(--local-muted)]">{step.meta}</span>
|
|
7132
|
+
</div>
|
|
7133
|
+
{/* Code block */}
|
|
7134
|
+
<pre className="p-6 font-mono text-xs leading-relaxed bg-[#080E14] text-[var(--local-fg)] overflow-x-auto whitespace-pre-wrap min-h-[200px]">
|
|
7135
|
+
{step.code}
|
|
7136
|
+
</pre>
|
|
7137
|
+
</div>
|
|
7138
|
+
))}
|
|
7139
|
+
</div>
|
|
7140
|
+
|
|
7141
|
+
{/* MCP manifest note */}
|
|
7142
|
+
{data.note && (
|
|
7143
|
+
<div className="mt-6 px-6 py-4 bg-[var(--local-card)] border border-[var(--local-border)] rounded-xl flex items-start gap-3">
|
|
7144
|
+
<svg width="18" height="18" viewBox="0 0 24 24" fill="none"
|
|
7145
|
+
stroke="currentColor" strokeWidth="2" strokeLinecap="round"
|
|
7146
|
+
className="text-[var(--local-p400)] mt-0.5 flex-shrink-0">
|
|
7147
|
+
<circle cx="12" cy="12" r="10"/>
|
|
7148
|
+
<line x1="12" y1="8" x2="12" y2="12"/>
|
|
7149
|
+
<line x1="12" y1="16" x2="12.01" y2="16"/>
|
|
7150
|
+
</svg>
|
|
7151
|
+
<p className="text-sm text-[var(--local-muted)]" data-jp-field="note">
|
|
7152
|
+
{data.note}{' '}
|
|
7153
|
+
{data.noteHref && (
|
|
7154
|
+
<code className="font-mono text-[var(--local-p300)] text-xs">{data.noteHref}</code>
|
|
7155
|
+
)}
|
|
7156
|
+
</p>
|
|
7157
|
+
</div>
|
|
7158
|
+
)}
|
|
7159
|
+
</div>
|
|
7160
|
+
</section>
|
|
7161
|
+
);
|
|
7162
|
+
}
|
|
7163
|
+
|
|
7164
|
+
END_OF_FILE_CONTENT
|
|
7165
|
+
echo "Creating src/components/olon-example/index.ts..."
|
|
7166
|
+
cat << 'END_OF_FILE_CONTENT' > "src/components/olon-example/index.ts"
|
|
7167
|
+
export { OlonExampleView as View } from './View';
|
|
7168
|
+
export { OlonExampleSchema } from './schema';
|
|
7169
|
+
export type { OlonExampleData } from './types';
|
|
7170
|
+
|
|
7171
|
+
END_OF_FILE_CONTENT
|
|
7172
|
+
echo "Creating src/components/olon-example/schema.ts..."
|
|
7173
|
+
cat << 'END_OF_FILE_CONTENT' > "src/components/olon-example/schema.ts"
|
|
7174
|
+
import { z } from 'zod';
|
|
7175
|
+
import { BaseSectionData } from '@/lib/base-schemas';
|
|
7176
|
+
|
|
7177
|
+
const StepSchema = z.object({
|
|
7178
|
+
number: z.number(),
|
|
7179
|
+
title: z.string(),
|
|
7180
|
+
meta: z.string(),
|
|
7181
|
+
code: z.string(),
|
|
7182
|
+
});
|
|
7183
|
+
|
|
7184
|
+
export const OlonExampleSchema = BaseSectionData.extend({
|
|
7185
|
+
label: z.string().default('Quick Example'),
|
|
7186
|
+
headline: z.string().default('Two steps. One contract.'),
|
|
7187
|
+
body: z.string().default(''),
|
|
7188
|
+
note: z.string().default(''),
|
|
7189
|
+
noteHref: z.string().default(''),
|
|
7190
|
+
steps: z.tuple([StepSchema, StepSchema]),
|
|
7191
|
+
});
|
|
7192
|
+
|
|
7193
|
+
export type OlonExampleData = z.infer<typeof OlonExampleSchema>;
|
|
7194
|
+
|
|
7195
|
+
END_OF_FILE_CONTENT
|
|
7196
|
+
echo "Creating src/components/olon-example/types.ts..."
|
|
7197
|
+
cat << 'END_OF_FILE_CONTENT' > "src/components/olon-example/types.ts"
|
|
7198
|
+
export type { OlonExampleData } from './schema';
|
|
7199
|
+
|
|
7200
|
+
END_OF_FILE_CONTENT
|
|
7201
|
+
mkdir -p "src/components/olon-getstarted"
|
|
7202
|
+
echo "Creating src/components/olon-getstarted/View.tsx..."
|
|
7203
|
+
cat << 'END_OF_FILE_CONTENT' > "src/components/olon-getstarted/View.tsx"
|
|
7204
|
+
import type { OlonGetStartedData } from './types';
|
|
7205
|
+
import { Button } from '@/components/ui/button';
|
|
7206
|
+
|
|
7207
|
+
const BADGE_STYLES: Record<string, string> = {
|
|
7208
|
+
oss: 'bg-blue-500/15 text-blue-400 border border-blue-500/30',
|
|
7209
|
+
cli: 'bg-primary/10 text-primary border border-primary/20',
|
|
7210
|
+
deploy: 'bg-muted text-muted-foreground border border-border',
|
|
7211
|
+
};
|
|
7212
|
+
|
|
7213
|
+
interface Props { data: OlonGetStartedData; }
|
|
7214
|
+
|
|
7215
|
+
export function OlonGetStartedView({ data }: Props) {
|
|
7216
|
+
return (
|
|
7217
|
+
<section
|
|
7218
|
+
style={{
|
|
7219
|
+
'--local-bg': 'var(--background)',
|
|
7220
|
+
'--local-fg': 'var(--foreground)',
|
|
7221
|
+
'--local-muted': 'var(--muted-foreground)',
|
|
7222
|
+
'--local-p400': 'var(--primary)',
|
|
7223
|
+
'--local-p300': 'var(--primary-light)',
|
|
7224
|
+
'--local-card': 'var(--card)',
|
|
7225
|
+
'--local-border':'var(--border)',
|
|
7226
|
+
} as React.CSSProperties}
|
|
7227
|
+
className="bg-[var(--local-bg)] text-[var(--local-fg)] py-24 border-t border-[var(--local-border)]"
|
|
7228
|
+
data-jp-section-id={data.id}
|
|
7229
|
+
data-jp-section-type="olon-getstarted"
|
|
7230
|
+
>
|
|
7231
|
+
<div className="max-w-6xl mx-auto px-8">
|
|
7232
|
+
<p className="text-xs font-semibold tracking-[0.12em] uppercase text-[var(--local-muted)] mb-3"
|
|
7233
|
+
data-jp-field="label">{data.label}</p>
|
|
7234
|
+
<h2 className="text-4xl font-bold tracking-[-0.03em] text-white mb-3"
|
|
7235
|
+
data-jp-field="headline">{data.headline}</h2>
|
|
7236
|
+
<p className="text-base text-[var(--local-muted)] leading-relaxed max-w-2xl mb-12"
|
|
7237
|
+
data-jp-field="body">{data.body}</p>
|
|
7238
|
+
|
|
7239
|
+
<div className="grid grid-cols-1 md:grid-cols-3 border border-[var(--local-border)] rounded-2xl overflow-hidden"
|
|
7240
|
+
data-jp-array="cards">
|
|
7241
|
+
{data.cards.map((card) => (
|
|
7242
|
+
<div key={card.id}
|
|
7243
|
+
className="bg-[var(--local-card)] p-8 flex flex-col gap-4 border-r last:border-r-0 border-[var(--local-border)] hover:bg-[var(--elevated)] transition-colors"
|
|
7244
|
+
data-jp-item-id={card.id}>
|
|
7245
|
+
<span className={`text-[11px] font-bold tracking-[0.08em] uppercase px-2.5 py-0.5 rounded-full w-fit ${BADGE_STYLES[card.badgeStyle]}`}
|
|
7246
|
+
data-jp-field="badge">
|
|
7247
|
+
{card.badge}
|
|
7248
|
+
</span>
|
|
7249
|
+
<p className="font-bold text-white text-base" data-jp-field="title">{card.title}</p>
|
|
7250
|
+
<p className="text-sm text-[var(--local-muted)] leading-relaxed flex-1"
|
|
7251
|
+
data-jp-field="body">{card.body}</p>
|
|
7252
|
+
{card.code && (
|
|
7253
|
+
<code className="font-mono text-xs bg-[#080E14] border border-[var(--local-border)] rounded-lg px-4 py-3 text-[var(--local-p300)] block"
|
|
7254
|
+
data-jp-field="code">
|
|
7255
|
+
{card.code}
|
|
7256
|
+
</code>
|
|
7257
|
+
)}
|
|
7258
|
+
{card.deployHref && card.deployLabel && (
|
|
7259
|
+
<Button asChild variant="outline" size="sm" className="w-fit">
|
|
7260
|
+
<a href={card.deployHref} target="_blank" rel="noopener noreferrer">
|
|
7261
|
+
{card.deployLabel}
|
|
7262
|
+
</a>
|
|
7263
|
+
</Button>
|
|
7264
|
+
)}
|
|
7265
|
+
<a href={card.linkHref} target="_blank" rel="noopener noreferrer"
|
|
7266
|
+
className="text-sm text-[var(--local-p400)] hover:text-[var(--local-p300)] transition-colors flex items-center gap-1 mt-auto"
|
|
7267
|
+
data-jp-field="linkLabel">
|
|
7268
|
+
{card.linkLabel} ↗
|
|
7269
|
+
</a>
|
|
7270
|
+
</div>
|
|
7271
|
+
))}
|
|
7272
|
+
</div>
|
|
7273
|
+
</div>
|
|
7274
|
+
</section>
|
|
7275
|
+
);
|
|
7276
|
+
}
|
|
7277
|
+
|
|
7278
|
+
END_OF_FILE_CONTENT
|
|
7279
|
+
echo "Creating src/components/olon-getstarted/index.ts..."
|
|
7280
|
+
cat << 'END_OF_FILE_CONTENT' > "src/components/olon-getstarted/index.ts"
|
|
7281
|
+
export { OlonGetStartedView as View } from './View';
|
|
7282
|
+
export { OlonGetStartedSchema } from './schema';
|
|
7283
|
+
export type { OlonGetStartedData } from './types';
|
|
7284
|
+
|
|
7285
|
+
END_OF_FILE_CONTENT
|
|
7286
|
+
echo "Creating src/components/olon-getstarted/schema.ts..."
|
|
7287
|
+
cat << 'END_OF_FILE_CONTENT' > "src/components/olon-getstarted/schema.ts"
|
|
7288
|
+
import { z } from 'zod';
|
|
7289
|
+
import { BaseSectionData, BaseArrayItem } from '@/lib/base-schemas';
|
|
7290
|
+
|
|
7291
|
+
export const StartCardSchema = BaseArrayItem.extend({
|
|
7292
|
+
badge: z.string(),
|
|
7293
|
+
badgeStyle: z.enum(['oss', 'cli', 'deploy']),
|
|
7294
|
+
title: z.string(),
|
|
7295
|
+
body: z.string(),
|
|
7296
|
+
code: z.string().optional(),
|
|
7297
|
+
linkLabel: z.string(),
|
|
7298
|
+
linkHref: z.string(),
|
|
7299
|
+
deployLabel:z.string().optional(),
|
|
7300
|
+
deployHref: z.string().optional(),
|
|
7301
|
+
});
|
|
7302
|
+
|
|
7303
|
+
export const OlonGetStartedSchema = BaseSectionData.extend({
|
|
7304
|
+
label: z.string().default('Get Started'),
|
|
7305
|
+
headline: z.string().default('Three paths in.'),
|
|
7306
|
+
body: z.string().default(''),
|
|
7307
|
+
cards: z.array(StartCardSchema).min(1).max(3),
|
|
7308
|
+
});
|
|
7309
|
+
|
|
7310
|
+
export type OlonGetStartedData = z.infer<typeof OlonGetStartedSchema>;
|
|
7311
|
+
|
|
7312
|
+
END_OF_FILE_CONTENT
|
|
7313
|
+
echo "Creating src/components/olon-getstarted/types.ts..."
|
|
7314
|
+
cat << 'END_OF_FILE_CONTENT' > "src/components/olon-getstarted/types.ts"
|
|
7315
|
+
export type { OlonGetStartedData } from './schema';
|
|
7316
|
+
|
|
7317
|
+
END_OF_FILE_CONTENT
|
|
7318
|
+
mkdir -p "src/components/olon-hero"
|
|
7319
|
+
echo "Creating src/components/olon-hero/DawnBackground.tsx..."
|
|
7320
|
+
cat << 'END_OF_FILE_CONTENT' > "src/components/olon-hero/DawnBackground.tsx"
|
|
7321
|
+
import { useEffect, useRef } from 'react';
|
|
7322
|
+
import { motion } from 'motion/react';
|
|
7323
|
+
|
|
7324
|
+
export function DawnBackground({
|
|
7325
|
+
dawnDuration = 3.5,
|
|
7326
|
+
breathingSpeed = 0.5,
|
|
7327
|
+
breathingRange = 0.03,
|
|
7328
|
+
intensity = 0.55,
|
|
7329
|
+
}: {
|
|
7330
|
+
dawnDuration?: number;
|
|
7331
|
+
breathingSpeed?: number;
|
|
7332
|
+
breathingRange?: number;
|
|
7333
|
+
intensity?: number;
|
|
7334
|
+
}) {
|
|
7335
|
+
const containerRef = useRef<HTMLDivElement | null>(null);
|
|
7336
|
+
const canvasRef = useRef<HTMLCanvasElement | null>(null);
|
|
7337
|
+
const rafRef = useRef<number>(0);
|
|
7338
|
+
const startRef = useRef<number | null>(null);
|
|
7339
|
+
|
|
7340
|
+
useEffect(() => {
|
|
7341
|
+
const canvas = canvasRef.current;
|
|
7342
|
+
const container = containerRef.current;
|
|
7343
|
+
if (!canvas || !container) return;
|
|
7344
|
+
|
|
7345
|
+
const ctx = canvas.getContext('2d');
|
|
7346
|
+
if (!ctx) return;
|
|
7347
|
+
|
|
7348
|
+
function resize() {
|
|
7349
|
+
if (!canvas || !container) return;
|
|
7350
|
+
const dpr = window.devicePixelRatio || 1;
|
|
7351
|
+
canvas.width = container.offsetWidth * dpr;
|
|
7352
|
+
canvas.height = container.offsetHeight * dpr;
|
|
7353
|
+
}
|
|
7354
|
+
resize();
|
|
7355
|
+
|
|
7356
|
+
const ro = new ResizeObserver(resize);
|
|
7357
|
+
ro.observe(container);
|
|
7358
|
+
|
|
7359
|
+
function easeOut(t: number) {
|
|
7360
|
+
return 1 - Math.pow(1 - t, 3);
|
|
7361
|
+
}
|
|
7362
|
+
|
|
7363
|
+
function draw(ts: number) {
|
|
7364
|
+
if (!canvas || !ctx) return;
|
|
7365
|
+
if (!startRef.current) startRef.current = ts;
|
|
7366
|
+
|
|
7367
|
+
const elapsed = (ts - startRef.current) / 1000;
|
|
7368
|
+
const dawnP = Math.min(elapsed / dawnDuration, 1);
|
|
7369
|
+
const dawnE = easeOut(dawnP);
|
|
7370
|
+
const breathT = Math.max(0, elapsed - dawnDuration);
|
|
7371
|
+
const breathe = dawnP >= 1
|
|
7372
|
+
? 1 + Math.sin(breathT * breathingSpeed) * breathingRange
|
|
7373
|
+
: 1;
|
|
7374
|
+
|
|
7375
|
+
const W = canvas.width;
|
|
7376
|
+
const H = canvas.height;
|
|
7377
|
+
const masterIntensity = dawnE * intensity * breathe;
|
|
7378
|
+
|
|
7379
|
+
ctx.clearRect(0, 0, W, H);
|
|
7380
|
+
|
|
7381
|
+
// Left source — bottom left, primary blue
|
|
7382
|
+
const lx = W * 0.18;
|
|
7383
|
+
const ly = H * 0.92;
|
|
7384
|
+
const lr = W * 0.75 * breathe;
|
|
7385
|
+
const gL = ctx.createRadialGradient(lx, ly, 0, lx, ly, lr);
|
|
7386
|
+
gL.addColorStop(0.00, `rgba(15,52,224,${0.70 * masterIntensity})`);
|
|
7387
|
+
gL.addColorStop(0.20, `rgba(23,99,255,${0.60 * masterIntensity})`);
|
|
7388
|
+
gL.addColorStop(0.45, `rgba(91,142,255,${0.35 * masterIntensity})`);
|
|
7389
|
+
gL.addColorStop(0.70, `rgba(84,171,255,${0.15 * masterIntensity})`);
|
|
7390
|
+
gL.addColorStop(1.00, 'rgba(12,17,22,0)');
|
|
7391
|
+
ctx.fillStyle = gL;
|
|
7392
|
+
ctx.fillRect(0, 0, W, H);
|
|
7393
|
+
|
|
7394
|
+
// Right source — mirror
|
|
7395
|
+
const gR = ctx.createRadialGradient(W - lx, ly, 0, W - lx, ly, lr);
|
|
7396
|
+
gR.addColorStop(0.00, `rgba(15,52,224,${0.70 * masterIntensity})`);
|
|
7397
|
+
gR.addColorStop(0.20, `rgba(23,99,255,${0.60 * masterIntensity})`);
|
|
7398
|
+
gR.addColorStop(0.45, `rgba(91,142,255,${0.35 * masterIntensity})`);
|
|
7399
|
+
gR.addColorStop(0.70, `rgba(84,171,255,${0.15 * masterIntensity})`);
|
|
7400
|
+
gR.addColorStop(1.00, 'rgba(12,17,22,0)');
|
|
7401
|
+
ctx.fillStyle = gR;
|
|
7402
|
+
ctx.fillRect(0, 0, W, H);
|
|
7403
|
+
|
|
7404
|
+
// Center V tip — deep navy, very subtle
|
|
7405
|
+
const vr = W * 0.32 * breathe;
|
|
7406
|
+
const gV = ctx.createRadialGradient(W * 0.5, H * 0.72, 0, W * 0.5, H * 0.72, vr);
|
|
7407
|
+
gV.addColorStop(0.00, `rgba(9,64,184,${0.50 * masterIntensity})`);
|
|
7408
|
+
gV.addColorStop(0.40, `rgba(15,52,224,${0.25 * masterIntensity})`);
|
|
7409
|
+
gV.addColorStop(1.00, 'rgba(12,17,22,0)');
|
|
7410
|
+
ctx.fillStyle = gV;
|
|
7411
|
+
ctx.fillRect(0, 0, W, H);
|
|
7412
|
+
|
|
7413
|
+
// Top dark veil — keeps header very dark
|
|
7414
|
+
const gTop = ctx.createLinearGradient(0, 0, 0, H * 0.6);
|
|
7415
|
+
gTop.addColorStop(0, 'rgba(12,17,22,1)');
|
|
7416
|
+
gTop.addColorStop(0.55, 'rgba(12,17,22,0.85)');
|
|
7417
|
+
gTop.addColorStop(1, 'rgba(12,17,22,0)');
|
|
7418
|
+
ctx.fillStyle = gTop;
|
|
7419
|
+
ctx.fillRect(0, 0, W, H);
|
|
7420
|
+
|
|
7421
|
+
rafRef.current = requestAnimationFrame(draw);
|
|
7422
|
+
}
|
|
7423
|
+
|
|
7424
|
+
rafRef.current = requestAnimationFrame(draw);
|
|
7425
|
+
|
|
7426
|
+
return () => {
|
|
7427
|
+
cancelAnimationFrame(rafRef.current);
|
|
7428
|
+
ro.disconnect();
|
|
7429
|
+
};
|
|
7430
|
+
}, [dawnDuration, breathingSpeed, breathingRange, intensity]);
|
|
7431
|
+
|
|
7432
|
+
return (
|
|
7433
|
+
<motion.div
|
|
7434
|
+
ref={containerRef}
|
|
7435
|
+
className="absolute inset-0 overflow-hidden"
|
|
7436
|
+
animate={{ opacity: 1, transition: { duration: 0.1 } }}
|
|
7437
|
+
initial={{ opacity: 0 }}
|
|
7438
|
+
>
|
|
7439
|
+
<canvas
|
|
7440
|
+
ref={canvasRef}
|
|
7441
|
+
className="absolute inset-0 w-full h-full"
|
|
7442
|
+
/>
|
|
7443
|
+
</motion.div>
|
|
7444
|
+
);
|
|
7445
|
+
}
|
|
7446
|
+
|
|
7447
|
+
END_OF_FILE_CONTENT
|
|
7448
|
+
echo "Creating src/components/olon-hero/View.tsx..."
|
|
7449
|
+
cat << 'END_OF_FILE_CONTENT' > "src/components/olon-hero/View.tsx"
|
|
7450
|
+
import type { OlonHeroData } from './types';
|
|
7451
|
+
import { Button } from '@/components/ui/button';
|
|
7452
|
+
import { DawnBackground } from './DawnBackground';
|
|
7453
|
+
|
|
7454
|
+
interface Props {
|
|
7455
|
+
data: OlonHeroData;
|
|
7456
|
+
}
|
|
7457
|
+
|
|
7458
|
+
export function OlonHeroView({ data }: Props) {
|
|
7459
|
+
return (
|
|
7460
|
+
<section
|
|
7461
|
+
style={{
|
|
7462
|
+
'--local-bg': 'var(--background)',
|
|
7463
|
+
'--local-fg': 'var(--foreground)',
|
|
7464
|
+
'--local-muted': 'var(--muted-foreground)',
|
|
7465
|
+
'--local-primary': 'var(--primary)',
|
|
7466
|
+
'--local-p300': 'var(--primary-light)',
|
|
7467
|
+
} as React.CSSProperties}
|
|
7468
|
+
className="relative min-h-screen bg-[var(--local-bg)] text-[var(--local-fg)] pt-36 pb-24 overflow-hidden"
|
|
7469
|
+
data-jp-section-id={data.id}
|
|
7470
|
+
data-jp-section-type="olon-hero"
|
|
7471
|
+
>
|
|
7472
|
+
{/* Dawn background — absolute, behind content */}
|
|
7473
|
+
<DawnBackground />
|
|
7474
|
+
|
|
7475
|
+
{/* Content — relative, above background */}
|
|
7476
|
+
<div className="relative z-10 max-w-6xl mx-auto px-8 grid grid-cols-1 md:grid-cols-2 gap-16 items-center">
|
|
7477
|
+
{/* Left: copy */}
|
|
7478
|
+
<div className="flex flex-col gap-6">
|
|
7479
|
+
<p
|
|
7480
|
+
className="text-xs font-semibold tracking-[0.12em] uppercase text-[var(--local-muted)]"
|
|
7481
|
+
data-jp-field="eyebrow"
|
|
7482
|
+
>
|
|
7483
|
+
{data.eyebrow}
|
|
7484
|
+
</p>
|
|
7485
|
+
|
|
7486
|
+
<div>
|
|
7487
|
+
<h1
|
|
7488
|
+
className="text-5xl md:text-6xl font-bold tracking-[-0.03em] leading-[1.05] text-white"
|
|
7489
|
+
data-jp-field="headline"
|
|
7490
|
+
>
|
|
7491
|
+
{data.headline}
|
|
7492
|
+
</h1>
|
|
7493
|
+
<p
|
|
7494
|
+
className="text-4xl md:text-5xl font-semibold tracking-[-0.03em] leading-[1.1] text-[var(--local-p300)] italic mt-1"
|
|
7495
|
+
data-jp-field="subline"
|
|
7496
|
+
>
|
|
7497
|
+
{data.subline}
|
|
7498
|
+
</p>
|
|
7499
|
+
</div>
|
|
7500
|
+
|
|
7501
|
+
<p
|
|
7502
|
+
className="text-base text-[var(--local-muted)] leading-relaxed max-w-lg"
|
|
7503
|
+
data-jp-field="body"
|
|
7504
|
+
>
|
|
7505
|
+
{data.body}
|
|
7506
|
+
</p>
|
|
7507
|
+
|
|
7508
|
+
<div className="flex flex-wrap gap-3 items-center">
|
|
7509
|
+
<Button asChild size="lg" className="font-semibold">
|
|
7510
|
+
<a href={data.cta.primary.href}>{data.cta.primary.label} →</a>
|
|
7511
|
+
</Button>
|
|
7512
|
+
<Button asChild variant="outline" size="lg" className="font-semibold">
|
|
7513
|
+
<a href={data.cta.secondary.href}>{data.cta.secondary.label}</a>
|
|
7514
|
+
</Button>
|
|
7515
|
+
<a
|
|
7516
|
+
href={data.cta.ghost.href}
|
|
7517
|
+
className="text-sm text-[var(--local-muted)] hover:text-[var(--local-fg)] transition-colors flex items-center gap-1.5"
|
|
7518
|
+
>
|
|
7519
|
+
{data.cta.ghost.label}
|
|
7520
|
+
</a>
|
|
7521
|
+
</div>
|
|
7522
|
+
</div>
|
|
7523
|
+
|
|
7524
|
+
{/* Right: SVG illustration */}
|
|
7525
|
+
<div className="hidden md:flex items-center justify-center">
|
|
7526
|
+
<svg
|
|
7527
|
+
viewBox="0 0 400 400"
|
|
7528
|
+
fill="none"
|
|
7529
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
7530
|
+
className="w-full max-w-md"
|
|
7531
|
+
>
|
|
7532
|
+
<defs>
|
|
7533
|
+
<linearGradient id="hero-main" x1="0" y1="0" x2="1" y2="1">
|
|
7534
|
+
<stop offset="0%" stopColor="#84ABFF"/>
|
|
7535
|
+
<stop offset="60%" stopColor="#1763FF"/>
|
|
7536
|
+
<stop offset="100%" stopColor="#0F52E0"/>
|
|
7537
|
+
</linearGradient>
|
|
7538
|
+
<linearGradient id="hero-accent" x1="0" y1="0" x2="0" y2="1">
|
|
7539
|
+
<stop offset="0%" stopColor="#EEF3FF"/>
|
|
7540
|
+
<stop offset="100%" stopColor="#84ABFF"/>
|
|
7541
|
+
</linearGradient>
|
|
7542
|
+
<linearGradient id="hero-glow" x1="0" y1="0" x2="0" y2="1">
|
|
7543
|
+
<stop offset="0%" stopColor="#1763FF" stopOpacity="0.3"/>
|
|
7544
|
+
<stop offset="100%" stopColor="#1763FF" stopOpacity="0"/>
|
|
7545
|
+
</linearGradient>
|
|
7546
|
+
<filter id="glow">
|
|
7547
|
+
<feGaussianBlur stdDeviation="8" result="blur"/>
|
|
7548
|
+
<feComposite in="SourceGraphic" in2="blur" operator="over"/>
|
|
7549
|
+
</filter>
|
|
7550
|
+
</defs>
|
|
7551
|
+
<circle cx="200" cy="200" r="160" fill="url(#hero-glow)" opacity="0.4"/>
|
|
7552
|
+
<rect x="90" y="90" width="220" height="220" rx="28" fill="none" stroke="url(#hero-main)" strokeWidth="14"/>
|
|
7553
|
+
{/* Left pins */}
|
|
7554
|
+
<line x1="16" y1="148" x2="90" y2="148" stroke="url(#hero-main)" strokeWidth="10" strokeLinecap="round"/>
|
|
7555
|
+
<line x1="16" y1="200" x2="90" y2="200" stroke="url(#hero-main)" strokeWidth="10" strokeLinecap="round"/>
|
|
7556
|
+
<line x1="16" y1="252" x2="90" y2="252" stroke="url(#hero-main)" strokeWidth="10" strokeLinecap="round"/>
|
|
7557
|
+
{/* Right pins */}
|
|
7558
|
+
<line x1="310" y1="148" x2="384" y2="148" stroke="url(#hero-main)" strokeWidth="10" strokeLinecap="round"/>
|
|
7559
|
+
<line x1="310" y1="200" x2="384" y2="200" stroke="url(#hero-main)" strokeWidth="10" strokeLinecap="round"/>
|
|
7560
|
+
<line x1="310" y1="252" x2="384" y2="252" stroke="url(#hero-main)" strokeWidth="10" strokeLinecap="round"/>
|
|
7561
|
+
{/* Top pins */}
|
|
7562
|
+
<line x1="148" y1="16" x2="148" y2="90" stroke="url(#hero-main)" strokeWidth="10" strokeLinecap="round"/>
|
|
7563
|
+
<line x1="200" y1="16" x2="200" y2="90" stroke="url(#hero-main)" strokeWidth="10" strokeLinecap="round"/>
|
|
7564
|
+
<line x1="252" y1="16" x2="252" y2="90" stroke="url(#hero-main)" strokeWidth="10" strokeLinecap="round"/>
|
|
7565
|
+
{/* Bottom pins */}
|
|
7566
|
+
<line x1="148" y1="310" x2="148" y2="384" stroke="url(#hero-main)" strokeWidth="10" strokeLinecap="round"/>
|
|
7567
|
+
<line x1="200" y1="310" x2="200" y2="384" stroke="url(#hero-main)" strokeWidth="10" strokeLinecap="round"/>
|
|
7568
|
+
<line x1="252" y1="310" x2="252" y2="384" stroke="url(#hero-main)" strokeWidth="10" strokeLinecap="round"/>
|
|
7569
|
+
{/* Corner nodes */}
|
|
7570
|
+
<circle cx="148" cy="148" r="13" fill="url(#hero-main)"/>
|
|
7571
|
+
<circle cx="252" cy="148" r="13" fill="url(#hero-main)"/>
|
|
7572
|
+
<circle cx="148" cy="252" r="13" fill="url(#hero-main)"/>
|
|
7573
|
+
<circle cx="252" cy="252" r="13" fill="url(#hero-main)"/>
|
|
7574
|
+
{/* Connection lines */}
|
|
7575
|
+
<line x1="148" y1="148" x2="200" y2="200" stroke="#84ABFF" strokeWidth="2.5" opacity="0.35"/>
|
|
7576
|
+
<line x1="252" y1="148" x2="200" y2="200" stroke="#84ABFF" strokeWidth="2.5" opacity="0.35"/>
|
|
7577
|
+
<line x1="148" y1="252" x2="200" y2="200" stroke="#84ABFF" strokeWidth="2.5" opacity="0.35"/>
|
|
7578
|
+
<line x1="252" y1="252" x2="200" y2="200" stroke="#84ABFF" strokeWidth="2.5" opacity="0.35"/>
|
|
7579
|
+
{/* Center node */}
|
|
7580
|
+
<circle cx="200" cy="200" r="18" fill="url(#hero-accent)" filter="url(#glow)"/>
|
|
7581
|
+
</svg>
|
|
7582
|
+
</div>
|
|
7583
|
+
</div>
|
|
7584
|
+
</section>
|
|
7585
|
+
);
|
|
7586
|
+
}
|
|
7587
|
+
|
|
7588
|
+
END_OF_FILE_CONTENT
|
|
7589
|
+
echo "Creating src/components/olon-hero/View_.tsx..."
|
|
7590
|
+
cat << 'END_OF_FILE_CONTENT' > "src/components/olon-hero/View_.tsx"
|
|
7591
|
+
import type { OlonHeroData } from './types';
|
|
7592
|
+
import { Button } from '@/components/ui/button';
|
|
7593
|
+
|
|
7594
|
+
interface Props {
|
|
7595
|
+
data: OlonHeroData;
|
|
7596
|
+
}
|
|
7597
|
+
|
|
7598
|
+
export function OlonHeroView({ data }: Props) {
|
|
7599
|
+
return (
|
|
7600
|
+
<section
|
|
7601
|
+
style={{
|
|
7602
|
+
'--local-bg': 'var(--background)',
|
|
7603
|
+
'--local-fg': 'var(--foreground)',
|
|
7604
|
+
'--local-muted': 'var(--muted-foreground)',
|
|
7605
|
+
'--local-primary': 'var(--primary)',
|
|
7606
|
+
'--local-p300': 'var(--primary-light)',
|
|
7607
|
+
} as React.CSSProperties}
|
|
7608
|
+
className="min-h-screen bg-[var(--local-bg)] text-[var(--local-fg)] pt-36 pb-24"
|
|
7609
|
+
data-jp-section-id={data.id}
|
|
7610
|
+
data-jp-section-type="olon-hero"
|
|
7611
|
+
>
|
|
7612
|
+
<div className="max-w-6xl mx-auto px-8 grid grid-cols-1 md:grid-cols-2 gap-16 items-center">
|
|
7613
|
+
{/* Left: copy */}
|
|
7614
|
+
<div className="flex flex-col gap-6">
|
|
7615
|
+
<p className="text-xs font-semibold tracking-[0.12em] uppercase text-[var(--local-muted)]"
|
|
7616
|
+
data-jp-field="eyebrow">
|
|
7617
|
+
{data.eyebrow}
|
|
7618
|
+
</p>
|
|
7619
|
+
|
|
7620
|
+
<div>
|
|
7621
|
+
<h1 className="text-5xl md:text-6xl font-bold tracking-[-0.03em] leading-[1.05] text-white"
|
|
7622
|
+
data-jp-field="headline">
|
|
7623
|
+
{data.headline}
|
|
7624
|
+
</h1>
|
|
7625
|
+
<p className="text-4xl md:text-5xl font-semibold tracking-[-0.03em] leading-[1.1] text-[var(--local-p300)] italic mt-1"
|
|
7626
|
+
data-jp-field="subline">
|
|
7627
|
+
{data.subline}
|
|
7628
|
+
</p>
|
|
7629
|
+
</div>
|
|
7630
|
+
|
|
7631
|
+
<p className="text-base text-[var(--local-muted)] leading-relaxed max-w-lg"
|
|
7632
|
+
data-jp-field="body">
|
|
7633
|
+
{data.body}
|
|
7634
|
+
</p>
|
|
7635
|
+
|
|
7636
|
+
<div className="flex flex-wrap gap-3 items-center">
|
|
7637
|
+
<Button asChild size="lg" className="font-semibold">
|
|
7638
|
+
<a href={data.cta.primary.href}>{data.cta.primary.label} →</a>
|
|
7639
|
+
</Button>
|
|
7640
|
+
<Button asChild variant="outline" size="lg" className="font-semibold">
|
|
7641
|
+
<a href={data.cta.secondary.href}>{data.cta.secondary.label}</a>
|
|
7642
|
+
</Button>
|
|
7643
|
+
<a href={data.cta.ghost.href}
|
|
7644
|
+
className="text-sm text-[var(--local-muted)] hover:text-[var(--local-fg)] transition-colors flex items-center gap-1.5">
|
|
7645
|
+
{data.cta.ghost.label}
|
|
7646
|
+
</a>
|
|
7647
|
+
</div>
|
|
7648
|
+
</div>
|
|
7649
|
+
|
|
7650
|
+
{/* Right: SVG illustration */}
|
|
7651
|
+
<div className="hidden md:flex items-center justify-center">
|
|
7652
|
+
<svg viewBox="0 0 400 400" fill="none" xmlns="http://www.w3.org/2000/svg" className="w-full max-w-md">
|
|
7653
|
+
<defs>
|
|
7654
|
+
<linearGradient id="hero-main" x1="0" y1="0" x2="1" y2="1">
|
|
7655
|
+
<stop offset="0%" stopColor="#84ABFF"/>
|
|
7656
|
+
<stop offset="60%" stopColor="#1763FF"/>
|
|
7657
|
+
<stop offset="100%" stopColor="#0F52E0"/>
|
|
7658
|
+
</linearGradient>
|
|
7659
|
+
<linearGradient id="hero-accent" x1="0" y1="0" x2="0" y2="1">
|
|
7660
|
+
<stop offset="0%" stopColor="#EEF3FF"/>
|
|
7661
|
+
<stop offset="100%" stopColor="#84ABFF"/>
|
|
7662
|
+
</linearGradient>
|
|
7663
|
+
<linearGradient id="hero-glow" x1="0" y1="0" x2="0" y2="1">
|
|
7664
|
+
<stop offset="0%" stopColor="#1763FF" stopOpacity="0.3"/>
|
|
7665
|
+
<stop offset="100%" stopColor="#1763FF" stopOpacity="0"/>
|
|
7666
|
+
</linearGradient>
|
|
7667
|
+
<filter id="glow"><feGaussianBlur stdDeviation="8" result="blur"/><feComposite in="SourceGraphic" in2="blur" operator="over"/></filter>
|
|
7668
|
+
</defs>
|
|
7669
|
+
<circle cx="200" cy="200" r="160" fill="url(#hero-glow)" opacity="0.4"/>
|
|
7670
|
+
<rect x="90" y="90" width="220" height="220" rx="28" fill="none" stroke="url(#hero-main)" strokeWidth="14"/>
|
|
7671
|
+
<line x1="16" y1="148" x2="90" y2="148" stroke="url(#hero-main)" strokeWidth="10" strokeLinecap="round"/>
|
|
7672
|
+
<line x1="16" y1="200" x2="90" y2="200" stroke="url(#hero-main)" strokeWidth="10" strokeLinecap="round"/>
|
|
7673
|
+
<line x1="16" y1="252" x2="90" y2="252" stroke="url(#hero-main)" strokeWidth="10" strokeLinecap="round"/>
|
|
7674
|
+
<line x1="310" y1="148" x2="384" y2="148" stroke="url(#hero-main)" strokeWidth="10" strokeLinecap="round"/>
|
|
7675
|
+
<line x1="310" y1="200" x2="384" y2="200" stroke="url(#hero-main)" strokeWidth="10" strokeLinecap="round"/>
|
|
7676
|
+
<line x1="310" y1="252" x2="384" y2="252" stroke="url(#hero-main)" strokeWidth="10" strokeLinecap="round"/>
|
|
7677
|
+
<line x1="148" y1="16" x2="148" y2="90" stroke="url(#hero-main)" strokeWidth="10" strokeLinecap="round"/>
|
|
7678
|
+
<line x1="200" y1="16" x2="200" y2="90" stroke="url(#hero-main)" strokeWidth="10" strokeLinecap="round"/>
|
|
7679
|
+
<line x1="252" y1="16" x2="252" y2="90" stroke="url(#hero-main)" strokeWidth="10" strokeLinecap="round"/>
|
|
7680
|
+
<line x1="148" y1="310" x2="148" y2="384" stroke="url(#hero-main)" strokeWidth="10" strokeLinecap="round"/>
|
|
7681
|
+
<line x1="200" y1="310" x2="200" y2="384" stroke="url(#hero-main)" strokeWidth="10" strokeLinecap="round"/>
|
|
7682
|
+
<line x1="252" y1="310" x2="252" y2="384" stroke="url(#hero-main)" strokeWidth="10" strokeLinecap="round"/>
|
|
7683
|
+
<circle cx="148" cy="148" r="13" fill="url(#hero-main)"/>
|
|
7684
|
+
<circle cx="252" cy="148" r="13" fill="url(#hero-main)"/>
|
|
7685
|
+
<circle cx="148" cy="252" r="13" fill="url(#hero-main)"/>
|
|
7686
|
+
<circle cx="252" cy="252" r="13" fill="url(#hero-main)"/>
|
|
7687
|
+
<line x1="148" y1="148" x2="200" y2="200" stroke="#84ABFF" strokeWidth="2.5" opacity="0.35"/>
|
|
7688
|
+
<line x1="252" y1="148" x2="200" y2="200" stroke="#84ABFF" strokeWidth="2.5" opacity="0.35"/>
|
|
7689
|
+
<line x1="148" y1="252" x2="200" y2="200" stroke="#84ABFF" strokeWidth="2.5" opacity="0.35"/>
|
|
7690
|
+
<line x1="252" y1="252" x2="200" y2="200" stroke="#84ABFF" strokeWidth="2.5" opacity="0.35"/>
|
|
7691
|
+
<circle cx="200" cy="200" r="18" fill="url(#hero-accent)" filter="url(#glow)"/>
|
|
7692
|
+
</svg>
|
|
7693
|
+
</div>
|
|
7694
|
+
</div>
|
|
7695
|
+
</section>
|
|
7696
|
+
);
|
|
7697
|
+
}
|
|
7698
|
+
|
|
7699
|
+
END_OF_FILE_CONTENT
|
|
7700
|
+
echo "Creating src/components/olon-hero/index.ts..."
|
|
7701
|
+
cat << 'END_OF_FILE_CONTENT' > "src/components/olon-hero/index.ts"
|
|
7702
|
+
export { OlonHeroView as View } from './View';
|
|
7703
|
+
export { OlonHeroSchema } from './schema';
|
|
7704
|
+
export type { OlonHeroData } from './types';
|
|
7705
|
+
|
|
7706
|
+
END_OF_FILE_CONTENT
|
|
7707
|
+
echo "Creating src/components/olon-hero/schema.ts..."
|
|
7708
|
+
cat << 'END_OF_FILE_CONTENT' > "src/components/olon-hero/schema.ts"
|
|
7709
|
+
import { z } from 'zod';
|
|
7710
|
+
import { BaseSectionData } from '@/lib/base-schemas';
|
|
7711
|
+
|
|
7712
|
+
export const OlonHeroSchema = BaseSectionData.extend({
|
|
7713
|
+
eyebrow: z.string().default('CONTRACT LAYER · V1.5 · OPEN CORE'),
|
|
7714
|
+
headline: z.string().default('Contract Layer'),
|
|
7715
|
+
subline: z.string().default('for the agentic web.'),
|
|
7716
|
+
body: z.string().default(''),
|
|
7717
|
+
cta: z.object({
|
|
7718
|
+
primary: z.object({ label: z.string(), href: z.string() }),
|
|
7719
|
+
secondary: z.object({ label: z.string(), href: z.string() }),
|
|
7720
|
+
ghost: z.object({ label: z.string(), href: z.string() }),
|
|
7721
|
+
}),
|
|
7722
|
+
});
|
|
7723
|
+
|
|
7724
|
+
export type OlonHeroData = z.infer<typeof OlonHeroSchema>;
|
|
7725
|
+
|
|
7726
|
+
END_OF_FILE_CONTENT
|
|
7727
|
+
echo "Creating src/components/olon-hero/types.ts..."
|
|
7728
|
+
cat << 'END_OF_FILE_CONTENT' > "src/components/olon-hero/types.ts"
|
|
7729
|
+
export type { OlonHeroData } from './schema';
|
|
7730
|
+
|
|
7731
|
+
END_OF_FILE_CONTENT
|
|
7732
|
+
mkdir -p "src/components/olon-why"
|
|
7733
|
+
echo "Creating src/components/olon-why/View.tsx..."
|
|
7734
|
+
cat << 'END_OF_FILE_CONTENT' > "src/components/olon-why/View.tsx"
|
|
7735
|
+
import type { OlonWhyData } from './types';
|
|
7736
|
+
|
|
7737
|
+
const ICONS = {
|
|
7738
|
+
contract: (
|
|
7739
|
+
<svg width="36" height="36" viewBox="0 0 200 200" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
7740
|
+
<defs>
|
|
7741
|
+
<linearGradient id="w1" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stopColor="#84ABFF"/><stop offset="1" stopColor="#0F52E0"/></linearGradient>
|
|
7742
|
+
</defs>
|
|
7743
|
+
<rect x="20" y="20" width="160" height="160" rx="16" fill="none" stroke="url(#w1)" strokeWidth="10"/>
|
|
7744
|
+
<line x1="20" y1="70" x2="180" y2="70" stroke="url(#w1)" strokeWidth="7"/>
|
|
7745
|
+
<rect x="40" y="100" width="60" height="8" rx="4" fill="url(#w1)" opacity="0.4"/>
|
|
7746
|
+
<rect x="40" y="118" width="90" height="8" rx="4" fill="url(#w1)" opacity="0.7"/>
|
|
7747
|
+
<rect x="40" y="136" width="72" height="8" rx="4" fill="url(#w1)" opacity="0.5"/>
|
|
7748
|
+
</svg>
|
|
7749
|
+
),
|
|
7750
|
+
holon: (
|
|
7751
|
+
<svg width="36" height="36" viewBox="0 0 200 200" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
7752
|
+
<defs>
|
|
7753
|
+
<linearGradient id="w2" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stopColor="#84ABFF"/><stop offset="1" stopColor="#0F52E0"/></linearGradient>
|
|
7754
|
+
<linearGradient id="w2a" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stopColor="#EEF3FF"/><stop offset="1" stopColor="#84ABFF"/></linearGradient>
|
|
7755
|
+
</defs>
|
|
7756
|
+
<circle cx="100" cy="100" r="75" fill="none" stroke="url(#w2)" strokeWidth="10"/>
|
|
7757
|
+
<circle cx="100" cy="100" r="28" fill="url(#w2a)"/>
|
|
7758
|
+
</svg>
|
|
7759
|
+
),
|
|
7760
|
+
generated: (
|
|
7761
|
+
<svg width="36" height="36" viewBox="0 0 200 200" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
7762
|
+
<defs>
|
|
7763
|
+
<linearGradient id="w3" x1="0" y1="0" x2="1" y2="1"><stop offset="0" stopColor="#84ABFF"/><stop offset="1" stopColor="#0F52E0"/></linearGradient>
|
|
7764
|
+
</defs>
|
|
7765
|
+
<circle cx="100" cy="40" r="14" fill="url(#w3)"/>
|
|
7766
|
+
<circle cx="50" cy="110" r="12" fill="url(#w3)" opacity="0.6"/>
|
|
7767
|
+
<circle cx="150" cy="110" r="12" fill="url(#w3)" opacity="0.6"/>
|
|
7768
|
+
<circle cx="80" cy="175" r="10" fill="url(#w3)" opacity="0.35"/>
|
|
7769
|
+
<circle cx="130" cy="175" r="14" fill="url(#w3)"/>
|
|
7770
|
+
<line x1="100" y1="54" x2="54" y2="98" stroke="url(#w3)" strokeWidth="5" strokeLinecap="round"/>
|
|
7771
|
+
<line x1="100" y1="54" x2="146" y2="98" stroke="url(#w3)" strokeWidth="5" strokeLinecap="round" opacity="0.4"/>
|
|
7772
|
+
<line x1="54" y1="122" x2="82" y2="165" stroke="url(#w3)" strokeWidth="4" strokeLinecap="round" opacity="0.35"/>
|
|
7773
|
+
<line x1="146" y1="122" x2="128" y2="165" stroke="url(#w3)" strokeWidth="5" strokeLinecap="round"/>
|
|
7774
|
+
</svg>
|
|
7775
|
+
),
|
|
7776
|
+
};
|
|
7777
|
+
|
|
7778
|
+
interface Props { data: OlonWhyData; }
|
|
7779
|
+
|
|
7780
|
+
export function OlonWhyView({ data }: Props) {
|
|
7781
|
+
return (
|
|
7782
|
+
<section
|
|
7783
|
+
style={{
|
|
7784
|
+
'--local-bg': 'var(--background)',
|
|
7785
|
+
'--local-fg': 'var(--foreground)',
|
|
7786
|
+
'--local-muted': 'var(--muted-foreground)',
|
|
7787
|
+
'--local-p300': 'var(--primary-light)',
|
|
7788
|
+
'--local-card': 'var(--card)',
|
|
7789
|
+
'--local-border':'var(--border)',
|
|
7790
|
+
} as React.CSSProperties}
|
|
7791
|
+
className="bg-[var(--local-bg)] text-[var(--local-fg)] py-24 border-t border-[var(--local-border)]"
|
|
7792
|
+
data-jp-section-id={data.id}
|
|
7793
|
+
data-jp-section-type="olon-why"
|
|
7794
|
+
>
|
|
7795
|
+
<div className="max-w-6xl mx-auto px-8">
|
|
7796
|
+
<p className="text-xs font-semibold tracking-[0.12em] uppercase text-[var(--local-muted)] mb-3"
|
|
7797
|
+
data-jp-field="label">{data.label}</p>
|
|
7798
|
+
<h2 className="text-4xl font-bold tracking-[-0.03em] text-white leading-tight"
|
|
7799
|
+
data-jp-field="headline">{data.headline}</h2>
|
|
7800
|
+
<p className="text-3xl font-semibold tracking-[-0.03em] text-[var(--local-p300)] leading-tight mb-4"
|
|
7801
|
+
data-jp-field="subline">{data.subline}</p>
|
|
7802
|
+
<p className="text-base text-[var(--local-muted)] leading-relaxed max-w-2xl mb-12"
|
|
7803
|
+
data-jp-field="body">{data.body}</p>
|
|
7804
|
+
|
|
7805
|
+
<div className="grid grid-cols-1 md:grid-cols-3 border border-[var(--local-border)] rounded-2xl overflow-hidden"
|
|
7806
|
+
data-jp-array="pillars">
|
|
7807
|
+
{data.pillars.map((pillar) => (
|
|
7808
|
+
<div key={pillar.id}
|
|
7809
|
+
className="bg-[var(--local-card)] p-8 flex flex-col gap-4 border-r last:border-r-0 border-[var(--local-border)]"
|
|
7810
|
+
data-jp-item-id={pillar.id}>
|
|
7811
|
+
<div>{ICONS[pillar.icon]}</div>
|
|
7812
|
+
<div className="font-bold text-white" data-jp-field="title">{pillar.title}</div>
|
|
7813
|
+
<div className="text-sm text-[var(--local-muted)] leading-relaxed" data-jp-field="body">{pillar.body}</div>
|
|
7814
|
+
</div>
|
|
7815
|
+
))}
|
|
7816
|
+
</div>
|
|
7817
|
+
</div>
|
|
7818
|
+
</section>
|
|
7819
|
+
);
|
|
7820
|
+
}
|
|
7821
|
+
|
|
7822
|
+
END_OF_FILE_CONTENT
|
|
7823
|
+
echo "Creating src/components/olon-why/index.ts..."
|
|
7824
|
+
cat << 'END_OF_FILE_CONTENT' > "src/components/olon-why/index.ts"
|
|
7825
|
+
export { OlonWhyView as View } from './View';
|
|
7826
|
+
export { OlonWhySchema } from './schema';
|
|
7827
|
+
export type { OlonWhyData } from './types';
|
|
7828
|
+
|
|
7829
|
+
END_OF_FILE_CONTENT
|
|
7830
|
+
echo "Creating src/components/olon-why/schema.ts..."
|
|
7831
|
+
cat << 'END_OF_FILE_CONTENT' > "src/components/olon-why/schema.ts"
|
|
7832
|
+
import { z } from 'zod';
|
|
7833
|
+
import { BaseSectionData, BaseArrayItem } from '@/lib/base-schemas';
|
|
7834
|
+
|
|
7835
|
+
export const PillarSchema = BaseArrayItem.extend({
|
|
7836
|
+
title: z.string(),
|
|
7837
|
+
body: z.string(),
|
|
7838
|
+
icon: z.enum(['contract', 'holon', 'generated']),
|
|
7839
|
+
});
|
|
7840
|
+
|
|
7841
|
+
export const OlonWhySchema = BaseSectionData.extend({
|
|
7842
|
+
label: z.string().default('Why OlonJS'),
|
|
7843
|
+
headline: z.string().default('A Meaningful Web'),
|
|
7844
|
+
subline: z.string().default('Whole in itself, part of something greater.'),
|
|
7845
|
+
body: z.string().default(''),
|
|
7846
|
+
pillars: z.array(PillarSchema).min(1).max(3),
|
|
7847
|
+
});
|
|
7848
|
+
|
|
7849
|
+
export type OlonWhyData = z.infer<typeof OlonWhySchema>;
|
|
7850
|
+
|
|
7851
|
+
END_OF_FILE_CONTENT
|
|
7852
|
+
echo "Creating src/components/olon-why/types.ts..."
|
|
7853
|
+
cat << 'END_OF_FILE_CONTENT' > "src/components/olon-why/types.ts"
|
|
7854
|
+
export type { OlonWhyData } from './schema';
|
|
7855
|
+
|
|
6803
7856
|
END_OF_FILE_CONTENT
|
|
6804
7857
|
mkdir -p "src/components/page-hero"
|
|
6805
7858
|
echo "Creating src/components/page-hero/View.tsx..."
|
|
@@ -10046,8 +11099,37 @@ cat << 'END_OF_FILE_CONTENT' > "src/data/config/menu.json"
|
|
|
10046
11099
|
{
|
|
10047
11100
|
"main": [
|
|
10048
11101
|
{
|
|
10049
|
-
"label": "
|
|
10050
|
-
"href": "
|
|
11102
|
+
"label": "Why",
|
|
11103
|
+
"href": "#Why"
|
|
11104
|
+
|
|
11105
|
+
},
|
|
11106
|
+
{
|
|
11107
|
+
"label": "Architecture",
|
|
11108
|
+
"href": "#Architecture"
|
|
11109
|
+
},
|
|
11110
|
+
{
|
|
11111
|
+
"label": "Example",
|
|
11112
|
+
"href": "#Example"
|
|
11113
|
+
},
|
|
11114
|
+
{
|
|
11115
|
+
"label": "Get started",
|
|
11116
|
+
"href": "#Getstarted"
|
|
11117
|
+
},
|
|
11118
|
+
{
|
|
11119
|
+
"label": "GitHub",
|
|
11120
|
+
"href": "https://github.com/olonjs/core"
|
|
11121
|
+
}
|
|
11122
|
+
]
|
|
11123
|
+
}
|
|
11124
|
+
END_OF_FILE_CONTENT
|
|
11125
|
+
# SKIP: src/data/config/menu.json:Zone.Identifier is binary and cannot be embedded as text.
|
|
11126
|
+
echo "Creating src/data/config/menu_example_for_schema.json..."
|
|
11127
|
+
cat << 'END_OF_FILE_CONTENT' > "src/data/config/menu_example_for_schema.json"
|
|
11128
|
+
{
|
|
11129
|
+
"main": [
|
|
11130
|
+
{
|
|
11131
|
+
"label": "Why",
|
|
11132
|
+
"href": "/why",
|
|
10051
11133
|
"children": [
|
|
10052
11134
|
{
|
|
10053
11135
|
"label": "Overview",
|
|
@@ -10086,7 +11168,6 @@ cat << 'END_OF_FILE_CONTENT' > "src/data/config/menu.json"
|
|
|
10086
11168
|
]
|
|
10087
11169
|
}
|
|
10088
11170
|
END_OF_FILE_CONTENT
|
|
10089
|
-
# SKIP: src/data/config/menu.json:Zone.Identifier is binary and cannot be embedded as text.
|
|
10090
11171
|
echo "Creating src/data/config/site.json..."
|
|
10091
11172
|
cat << 'END_OF_FILE_CONTENT' > "src/data/config/site.json"
|
|
10092
11173
|
{
|
|
@@ -10109,36 +11190,47 @@ cat << 'END_OF_FILE_CONTENT' > "src/data/config/site.json"
|
|
|
10109
11190
|
"type": "header",
|
|
10110
11191
|
"data": {
|
|
10111
11192
|
"logoText": "Olon",
|
|
10112
|
-
"badge": "",
|
|
10113
|
-
"links":
|
|
10114
|
-
|
|
10115
|
-
|
|
10116
|
-
|
|
10117
|
-
|
|
10118
|
-
|
|
11193
|
+
"badge": "JS",
|
|
11194
|
+
"links": [
|
|
11195
|
+
{
|
|
11196
|
+
"label": "Why",
|
|
11197
|
+
"href": "#Why"
|
|
11198
|
+
},
|
|
11199
|
+
{
|
|
11200
|
+
"label": "Architecture",
|
|
11201
|
+
"href": "#Architecture"
|
|
11202
|
+
},
|
|
11203
|
+
{
|
|
11204
|
+
"label": "Example",
|
|
11205
|
+
"href": "#Example"
|
|
11206
|
+
},
|
|
11207
|
+
{
|
|
11208
|
+
"label": "Get started",
|
|
11209
|
+
"href": "#Getstarted"
|
|
11210
|
+
},
|
|
11211
|
+
{
|
|
11212
|
+
"label": "GitHub",
|
|
11213
|
+
"href": "https://github.com/olonjs/core"
|
|
11214
|
+
}
|
|
11215
|
+
],
|
|
11216
|
+
"ctaLabel": "",
|
|
11217
|
+
"ctaHref": "",
|
|
11218
|
+
"signinHref": ""
|
|
10119
11219
|
}
|
|
10120
11220
|
},
|
|
10121
11221
|
"footer": {
|
|
10122
11222
|
"id": "global-footer",
|
|
10123
11223
|
"type": "footer",
|
|
10124
11224
|
"data": {
|
|
10125
|
-
"brandText": "
|
|
10126
|
-
"copyright": "©
|
|
11225
|
+
"brandText": "OlonJS",
|
|
11226
|
+
"copyright": "© 2026 OlonJS · v1.5 · Guido Serio",
|
|
10127
11227
|
"links": [
|
|
10128
11228
|
{
|
|
10129
11229
|
"label": "GitHub",
|
|
10130
|
-
"href": "
|
|
10131
|
-
},
|
|
10132
|
-
{
|
|
10133
|
-
"label": "Privacy",
|
|
10134
|
-
"href": "#"
|
|
10135
|
-
},
|
|
10136
|
-
{
|
|
10137
|
-
"label": "Terms",
|
|
10138
|
-
"href": "#"
|
|
11230
|
+
"href": "https://github.com/olonjs/core"
|
|
10139
11231
|
}
|
|
10140
11232
|
],
|
|
10141
|
-
"designSystemHref": "
|
|
11233
|
+
"designSystemHref": ""
|
|
10142
11234
|
},
|
|
10143
11235
|
"settings": {
|
|
10144
11236
|
"showLogo": true
|
|
@@ -10153,168 +11245,162 @@ cat << 'END_OF_FILE_CONTENT' > "src/data/config/theme.json"
|
|
|
10153
11245
|
"name": "Olon",
|
|
10154
11246
|
"tokens": {
|
|
10155
11247
|
"colors": {
|
|
10156
|
-
"background": "
|
|
10157
|
-
"card": "
|
|
10158
|
-
"elevated": "#
|
|
10159
|
-
"overlay": "#
|
|
10160
|
-
"popover": "
|
|
10161
|
-
"popover-foreground": "
|
|
10162
|
-
"foreground": "
|
|
10163
|
-
"card-foreground": "
|
|
10164
|
-
"muted-foreground": "
|
|
10165
|
-
"placeholder": "#
|
|
10166
|
-
"primary": "
|
|
10167
|
-
"primary-foreground": "
|
|
10168
|
-
"primary-light": "#
|
|
10169
|
-
"primary-dark": "#
|
|
10170
|
-
"primary-50": "#
|
|
10171
|
-
"primary-100": "#
|
|
10172
|
-
"primary-200": "#
|
|
10173
|
-
"primary-300": "#
|
|
10174
|
-
"primary-400": "#
|
|
10175
|
-
"primary-500": "#
|
|
10176
|
-
"primary-600": "#
|
|
10177
|
-
"primary-700": "#
|
|
10178
|
-
"primary-800": "#
|
|
10179
|
-
"primary-900": "#
|
|
10180
|
-
"accent": "
|
|
10181
|
-
"accent-foreground": "
|
|
10182
|
-
"secondary": "
|
|
10183
|
-
"secondary-foreground": "
|
|
10184
|
-
"muted": "
|
|
10185
|
-
"border": "
|
|
10186
|
-
"border-strong": "#
|
|
10187
|
-
"input": "
|
|
10188
|
-
"ring": "
|
|
10189
|
-
"destructive": "
|
|
10190
|
-
"destructive-foreground": "
|
|
10191
|
-
"destructive-border": "#
|
|
10192
|
-
"destructive-ring": "#
|
|
10193
|
-
"success": "
|
|
10194
|
-
"success-foreground": "
|
|
10195
|
-
"success-border": "#
|
|
10196
|
-
"success-indicator": "#
|
|
10197
|
-
"warning": "
|
|
10198
|
-
"warning-foreground": "
|
|
10199
|
-
"warning-border": "#
|
|
10200
|
-
"info": "
|
|
10201
|
-
"info-foreground": "
|
|
10202
|
-
"info-border": "#
|
|
11248
|
+
"background": "hsl(215 28% 7%)",
|
|
11249
|
+
"card": "hsl(218 44% 9%)",
|
|
11250
|
+
"elevated": "#141B24",
|
|
11251
|
+
"overlay": "#1C2433",
|
|
11252
|
+
"popover": "hsl(218 44% 9%)",
|
|
11253
|
+
"popover-foreground": "hsl(214 33% 84%)",
|
|
11254
|
+
"foreground": "hsl(214 33% 84%)",
|
|
11255
|
+
"card-foreground": "hsl(214 33% 84%)",
|
|
11256
|
+
"muted-foreground": "hsl(215 23% 57%)",
|
|
11257
|
+
"placeholder": "#4A5C78",
|
|
11258
|
+
"primary": "hsl(222 100% 54%)",
|
|
11259
|
+
"primary-foreground": "hsl(0 0% 100%)",
|
|
11260
|
+
"primary-light": "#84ABFF",
|
|
11261
|
+
"primary-dark": "#0F52E0",
|
|
11262
|
+
"primary-50": "#EEF3FF",
|
|
11263
|
+
"primary-100": "#D6E4FF",
|
|
11264
|
+
"primary-200": "#ADC8FF",
|
|
11265
|
+
"primary-300": "#84ABFF",
|
|
11266
|
+
"primary-400": "#5B8EFF",
|
|
11267
|
+
"primary-500": "#1763FF",
|
|
11268
|
+
"primary-600": "#0F52E0",
|
|
11269
|
+
"primary-700": "#0940B8",
|
|
11270
|
+
"primary-800": "#063090",
|
|
11271
|
+
"primary-900": "#031E68",
|
|
11272
|
+
"accent": "hsl(216 28% 15%)",
|
|
11273
|
+
"accent-foreground": "hsl(214 33% 84%)",
|
|
11274
|
+
"secondary": "hsl(217 30% 11%)",
|
|
11275
|
+
"secondary-foreground": "hsl(214 33% 84%)",
|
|
11276
|
+
"muted": "hsl(217 30% 11%)",
|
|
11277
|
+
"border": "hsl(216 27% 21%)",
|
|
11278
|
+
"border-strong": "#2F3D55",
|
|
11279
|
+
"input": "hsl(216 27% 21%)",
|
|
11280
|
+
"ring": "hsl(222 100% 54%)",
|
|
11281
|
+
"destructive": "hsl(0 40% 46%)",
|
|
11282
|
+
"destructive-foreground": "hsl(210 58% 93%)",
|
|
11283
|
+
"destructive-border": "#7F2626",
|
|
11284
|
+
"destructive-ring": "#E06060",
|
|
11285
|
+
"success": "hsl(152 83% 26%)",
|
|
11286
|
+
"success-foreground": "hsl(210 58% 93%)",
|
|
11287
|
+
"success-border": "#1DB87A",
|
|
11288
|
+
"success-indicator": "#1DB87A",
|
|
11289
|
+
"warning": "hsl(46 100% 21%)",
|
|
11290
|
+
"warning-foreground": "hsl(210 58% 93%)",
|
|
11291
|
+
"warning-border": "#C49A00",
|
|
11292
|
+
"info": "hsl(214 100% 40%)",
|
|
11293
|
+
"info-foreground": "hsl(210 58% 93%)",
|
|
11294
|
+
"info-border": "#4D9FE0"
|
|
10203
11295
|
},
|
|
10204
11296
|
"modes": {
|
|
10205
11297
|
"light": {
|
|
10206
11298
|
"colors": {
|
|
10207
|
-
"background": "
|
|
10208
|
-
"card": "
|
|
10209
|
-
"elevated": "#
|
|
10210
|
-
"overlay": "#
|
|
10211
|
-
"popover": "
|
|
10212
|
-
"popover-foreground": "
|
|
10213
|
-
"foreground": "
|
|
10214
|
-
"card-foreground": "
|
|
10215
|
-
"muted-foreground": "
|
|
10216
|
-
"placeholder": "#
|
|
10217
|
-
"primary": "
|
|
10218
|
-
"primary-foreground": "
|
|
10219
|
-
"primary-light": "#
|
|
10220
|
-
"primary-dark": "#
|
|
10221
|
-
"primary-50": "#
|
|
10222
|
-
"primary-100": "#
|
|
10223
|
-
"primary-200": "#
|
|
10224
|
-
"primary-300": "#
|
|
10225
|
-
"primary-400": "#
|
|
10226
|
-
"primary-500": "#
|
|
10227
|
-
"primary-600": "#
|
|
10228
|
-
"primary-700": "#
|
|
10229
|
-
"primary-800": "#
|
|
10230
|
-
"primary-900": "#
|
|
10231
|
-
"accent": "
|
|
10232
|
-
"accent-foreground": "
|
|
10233
|
-
"secondary": "
|
|
10234
|
-
"secondary-foreground": "
|
|
10235
|
-
"muted": "
|
|
10236
|
-
"border": "
|
|
10237
|
-
"border-strong": "#
|
|
10238
|
-
"input": "
|
|
10239
|
-
"ring": "
|
|
10240
|
-
"destructive": "
|
|
10241
|
-
"destructive-foreground": "
|
|
11299
|
+
"background": "hsl(0 0% 96%)",
|
|
11300
|
+
"card": "hsl(0 0% 100%)",
|
|
11301
|
+
"elevated": "#F4F3EF",
|
|
11302
|
+
"overlay": "#E5E3DC",
|
|
11303
|
+
"popover": "hsl(0 0% 100%)",
|
|
11304
|
+
"popover-foreground": "hsl(0 0% 3%)",
|
|
11305
|
+
"foreground": "hsl(0 0% 3%)",
|
|
11306
|
+
"card-foreground": "hsl(0 0% 3%)",
|
|
11307
|
+
"muted-foreground": "hsl(0 0% 42%)",
|
|
11308
|
+
"placeholder": "#B4B2AD",
|
|
11309
|
+
"primary": "hsl(222 100% 54%)",
|
|
11310
|
+
"primary-foreground": "hsl(0 0% 100%)",
|
|
11311
|
+
"primary-light": "#5B8EFF",
|
|
11312
|
+
"primary-dark": "#0F52E0",
|
|
11313
|
+
"primary-50": "#EEF3FF",
|
|
11314
|
+
"primary-100": "#D6E4FF",
|
|
11315
|
+
"primary-200": "#ADC8FF",
|
|
11316
|
+
"primary-300": "#84ABFF",
|
|
11317
|
+
"primary-400": "#5B8EFF",
|
|
11318
|
+
"primary-500": "#1763FF",
|
|
11319
|
+
"primary-600": "#0F52E0",
|
|
11320
|
+
"primary-700": "#0940B8",
|
|
11321
|
+
"primary-800": "#063090",
|
|
11322
|
+
"primary-900": "#031E68",
|
|
11323
|
+
"accent": "hsl(222 100% 92%)",
|
|
11324
|
+
"accent-foreground": "hsl(222 100% 54%)",
|
|
11325
|
+
"secondary": "hsl(0 0% 92%)",
|
|
11326
|
+
"secondary-foreground": "hsl(0 0% 3%)",
|
|
11327
|
+
"muted": "hsl(0 0% 92%)",
|
|
11328
|
+
"border": "hsl(0 0% 84%)",
|
|
11329
|
+
"border-strong": "#B4B2AD",
|
|
11330
|
+
"input": "hsl(0 0% 84%)",
|
|
11331
|
+
"ring": "hsl(222 100% 54%)",
|
|
11332
|
+
"destructive": "hsl(0 72% 51%)",
|
|
11333
|
+
"destructive-foreground": "hsl(0 0% 100%)",
|
|
10242
11334
|
"destructive-border": "#FECACA",
|
|
10243
11335
|
"destructive-ring": "#EF4444",
|
|
10244
|
-
"success": "
|
|
10245
|
-
"success-foreground": "
|
|
10246
|
-
"success-border": "#
|
|
10247
|
-
"success-indicator": "#
|
|
10248
|
-
"warning": "
|
|
10249
|
-
"warning-foreground": "
|
|
10250
|
-
"warning-border": "#
|
|
10251
|
-
"info": "
|
|
10252
|
-
"info-foreground": "
|
|
10253
|
-
"info-border": "#
|
|
11336
|
+
"success": "hsl(160 84% 39%)",
|
|
11337
|
+
"success-foreground": "hsl(0 0% 100%)",
|
|
11338
|
+
"success-border": "#D4F0E2",
|
|
11339
|
+
"success-indicator": "#0A7C4E",
|
|
11340
|
+
"warning": "hsl(38 92% 50%)",
|
|
11341
|
+
"warning-foreground": "hsl(0 0% 3%)",
|
|
11342
|
+
"warning-border": "#F5EAD4",
|
|
11343
|
+
"info": "hsl(222 100% 54%)",
|
|
11344
|
+
"info-foreground": "hsl(0 0% 100%)",
|
|
11345
|
+
"info-border": "#D4E5F5"
|
|
10254
11346
|
}
|
|
10255
11347
|
}
|
|
10256
11348
|
},
|
|
10257
11349
|
"typography": {
|
|
10258
11350
|
"fontFamily": {
|
|
10259
|
-
"primary": "
|
|
10260
|
-
"mono": "
|
|
10261
|
-
"display": "
|
|
11351
|
+
"primary": "\"Instrument Sans\", Helvetica, Arial, sans-serif",
|
|
11352
|
+
"mono": "\"JetBrains Mono\", \"Fira Code\", monospace",
|
|
11353
|
+
"display": "\"Instrument Sans\", Helvetica, Arial, sans-serif"
|
|
10262
11354
|
},
|
|
10263
11355
|
"wordmark": {
|
|
10264
|
-
"fontFamily": "
|
|
10265
|
-
"weight": "
|
|
10266
|
-
"width": "112"
|
|
11356
|
+
"fontFamily": "\"Instrument Sans\", Helvetica, Arial, sans-serif",
|
|
11357
|
+
"weight": "700"
|
|
10267
11358
|
},
|
|
10268
11359
|
"scale": {
|
|
10269
|
-
"xs": "
|
|
10270
|
-
"sm": "
|
|
11360
|
+
"xs": "0.75rem",
|
|
11361
|
+
"sm": "0.875rem",
|
|
10271
11362
|
"base": "1rem",
|
|
10272
|
-
"
|
|
10273
|
-
"
|
|
10274
|
-
"
|
|
10275
|
-
"
|
|
10276
|
-
"
|
|
10277
|
-
"
|
|
10278
|
-
"5xl": "2.5rem",
|
|
11363
|
+
"lg": "1.125rem",
|
|
11364
|
+
"xl": "1.25rem",
|
|
11365
|
+
"2xl": "1.5rem",
|
|
11366
|
+
"3xl": "1.875rem",
|
|
11367
|
+
"4xl": "2.25rem",
|
|
11368
|
+
"5xl": "3rem",
|
|
10279
11369
|
"6xl": "3rem",
|
|
10280
11370
|
"7xl": "4.5rem"
|
|
10281
11371
|
},
|
|
10282
11372
|
"tracking": {
|
|
10283
|
-
"tight": "-0.
|
|
10284
|
-
"display": "-0.035em",
|
|
11373
|
+
"tight": "-0.04em",
|
|
10285
11374
|
"normal": "0em",
|
|
10286
11375
|
"wide": "0.04em",
|
|
10287
|
-
"
|
|
11376
|
+
"widest": "0.14em"
|
|
10288
11377
|
},
|
|
10289
11378
|
"leading": {
|
|
10290
|
-
"none": "1",
|
|
10291
11379
|
"tight": "1.2",
|
|
10292
|
-
"
|
|
10293
|
-
"
|
|
10294
|
-
"relaxed": "1.75"
|
|
11380
|
+
"normal": "1.5",
|
|
11381
|
+
"relaxed": "1.7"
|
|
10295
11382
|
}
|
|
10296
11383
|
},
|
|
10297
11384
|
"borderRadius": {
|
|
10298
|
-
"xl": "
|
|
10299
|
-
"lg": "
|
|
10300
|
-
"md": "
|
|
10301
|
-
"sm": "
|
|
11385
|
+
"xl": "1rem",
|
|
11386
|
+
"lg": "0.75rem",
|
|
11387
|
+
"md": "0.5rem",
|
|
11388
|
+
"sm": "0.25rem",
|
|
10302
11389
|
"full": "9999px"
|
|
10303
11390
|
},
|
|
10304
11391
|
"spacing": {
|
|
10305
|
-
"container-max": "
|
|
10306
|
-
"section-y": "
|
|
10307
|
-
"header-h": "
|
|
10308
|
-
"sidebar-w": "240px"
|
|
11392
|
+
"container-max": "72rem",
|
|
11393
|
+
"section-y": "4rem",
|
|
11394
|
+
"header-h": "4rem"
|
|
10309
11395
|
},
|
|
10310
11396
|
"zIndex": {
|
|
10311
11397
|
"base": "0",
|
|
10312
11398
|
"elevated": "10",
|
|
10313
|
-
"dropdown": "
|
|
10314
|
-
"sticky": "
|
|
10315
|
-
"overlay": "
|
|
10316
|
-
"modal": "
|
|
10317
|
-
"toast": "
|
|
11399
|
+
"dropdown": "20",
|
|
11400
|
+
"sticky": "40",
|
|
11401
|
+
"overlay": "50",
|
|
11402
|
+
"modal": "60",
|
|
11403
|
+
"toast": "100"
|
|
10318
11404
|
}
|
|
10319
11405
|
}
|
|
10320
11406
|
}
|
|
@@ -10343,7 +11429,6 @@ cat << 'END_OF_FILE_CONTENT' > "src/data/pages/design-system.json"
|
|
|
10343
11429
|
"global-header": false
|
|
10344
11430
|
}
|
|
10345
11431
|
END_OF_FILE_CONTENT
|
|
10346
|
-
# SKIP: src/data/pages/design-system.json:Zone.Identifier is binary and cannot be embedded as text.
|
|
10347
11432
|
echo "Creating src/data/pages/docs.json..."
|
|
10348
11433
|
cat << 'END_OF_FILE_CONTENT' > "src/data/pages/docs.json"
|
|
10349
11434
|
{
|
|
@@ -10368,6 +11453,215 @@ cat << 'END_OF_FILE_CONTENT' > "src/data/pages/docs.json"
|
|
|
10368
11453
|
END_OF_FILE_CONTENT
|
|
10369
11454
|
echo "Creating src/data/pages/home.json..."
|
|
10370
11455
|
cat << 'END_OF_FILE_CONTENT' > "src/data/pages/home.json"
|
|
11456
|
+
{
|
|
11457
|
+
"id": "home-page",
|
|
11458
|
+
"slug": "home",
|
|
11459
|
+
"meta": {
|
|
11460
|
+
"title": "OlonJS — Contract Layer for the Agentic Web",
|
|
11461
|
+
"description": "OlonJS is a TypeScript framework for building JSON-driven websites with a deterministic data contract. Every section is typed, validated, and structurally addressable."
|
|
11462
|
+
},
|
|
11463
|
+
"sections": [
|
|
11464
|
+
{
|
|
11465
|
+
"id": "hero-main",
|
|
11466
|
+
"type": "olon-hero",
|
|
11467
|
+
"data": {
|
|
11468
|
+
"id": "hero-main",
|
|
11469
|
+
"eyebrow": "CONTRACT LAYER · V1.5 · OPEN CORE",
|
|
11470
|
+
"headline": "Contract Layer",
|
|
11471
|
+
"subline": "for the agentic web.",
|
|
11472
|
+
"body": "AI agents are becoming operational actors in commerce, marketing, and support. They need more than content — they need a contract. OlonJS is the deterministic machine contract for websites: every site typed, structured, and addressable by design. No custom glue. No fragile integrations. Just a contract any agent can read and operate.",
|
|
11473
|
+
"cta": {
|
|
11474
|
+
"primary": {
|
|
11475
|
+
"label": "Get started",
|
|
11476
|
+
"href": "#Getstarted"
|
|
11477
|
+
},
|
|
11478
|
+
"secondary": {
|
|
11479
|
+
"label": "GitHub",
|
|
11480
|
+
"href": "https://github.com/olonjs/core"
|
|
11481
|
+
},
|
|
11482
|
+
"ghost": {
|
|
11483
|
+
"label": "Explore platform",
|
|
11484
|
+
"href": "#architecture"
|
|
11485
|
+
}
|
|
11486
|
+
}
|
|
11487
|
+
}
|
|
11488
|
+
},
|
|
11489
|
+
{
|
|
11490
|
+
"id": "why-olon",
|
|
11491
|
+
"type": "olon-why",
|
|
11492
|
+
"data": {
|
|
11493
|
+
"id": "why-olon",
|
|
11494
|
+
"label": "Why OlonJS",
|
|
11495
|
+
"headline": "A Meaningful Web",
|
|
11496
|
+
"subline": "Whole in itself, part of something greater.",
|
|
11497
|
+
"body": "Most web frameworks separate concerns across layers — data, UI, validation, metadata — with no shared contract between them. OlonJS inverts this: the JSON data structure is the contract. Every layer — rendering, editing, validation, machine access — is a deterministic projection of the same typed source. The result is a site that is structurally coherent by construction, not by convention. Every site built with OlonJS is a holon: complete in itself, intelligible to the network around it. The meaningful web doesn't happen all at once. It grows one site at a time.",
|
|
11498
|
+
"pillars": [
|
|
11499
|
+
{
|
|
11500
|
+
"id": "pillar-contract",
|
|
11501
|
+
"icon": "contract",
|
|
11502
|
+
"title": "The data is the contract",
|
|
11503
|
+
"body": "One typed JSON source. Every layer — UI, editor, agent, SEO — is a projection. No translation, no drift."
|
|
11504
|
+
},
|
|
11505
|
+
{
|
|
11506
|
+
"id": "pillar-holon",
|
|
11507
|
+
"icon": "holon",
|
|
11508
|
+
"title": "Every site is a holon",
|
|
11509
|
+
"body": "Autonomous, complete, structurally intelligible. Each site is whole in itself and part of a network that understands it."
|
|
11510
|
+
},
|
|
11511
|
+
{
|
|
11512
|
+
"id": "pillar-generated",
|
|
11513
|
+
"icon": "generated",
|
|
11514
|
+
"title": "Built to be generated",
|
|
11515
|
+
"body": "Every constraint is also an instruction. The spec is precise enough for AI agents to scaffold a fully compliant tenant from scratch."
|
|
11516
|
+
}
|
|
11517
|
+
],
|
|
11518
|
+
"anchorId": "Why"
|
|
11519
|
+
}
|
|
11520
|
+
},
|
|
11521
|
+
{
|
|
11522
|
+
"id": "architecture-protocols",
|
|
11523
|
+
"type": "olon-architecture",
|
|
11524
|
+
"data": {
|
|
11525
|
+
"id": "architecture-protocols",
|
|
11526
|
+
"label": "Architecture",
|
|
11527
|
+
"headline": "Six governing protocols.",
|
|
11528
|
+
"body": "OlonJS is specified as a versioned set of architectural protocols. Each protocol is independently versioned and mandatory for compliant tenants.",
|
|
11529
|
+
"specHref": "https://github.com/olonjs/core/blob/main/specs/olonjsSpecs_V_1_5.md",
|
|
11530
|
+
"protocols": [
|
|
11531
|
+
{
|
|
11532
|
+
"id": "proto-mtrp",
|
|
11533
|
+
"icon": "mtrp",
|
|
11534
|
+
"acronym": "MTRP",
|
|
11535
|
+
"version": "v1.2",
|
|
11536
|
+
"name": "Modular Type Registry",
|
|
11537
|
+
"desc": "Core exports an empty SectionDataRegistry. Tenants extend it via module augmentation. Full TypeScript inference across all section types at compile-time, zero Core changes.",
|
|
11538
|
+
"specHref": "https://github.com/olonjs/core/blob/main/specs/olonjsSpecs_V_1_5.md#1--modular-type-registry-pattern-mtrp-v12"
|
|
11539
|
+
},
|
|
11540
|
+
{
|
|
11541
|
+
"id": "proto-tbp",
|
|
11542
|
+
"icon": "tbp",
|
|
11543
|
+
"acronym": "TBP",
|
|
11544
|
+
"version": "v1.0",
|
|
11545
|
+
"name": "Tenant Block Protocol",
|
|
11546
|
+
"desc": "Each section type is a self-contained capsule: View.tsx, schema.ts, types.ts, index.ts. Renderable, validatable, and ingestible by the engine without additional configuration.",
|
|
11547
|
+
"specHref": "https://github.com/olonjs/core/blob/main/specs/olonjsSpecs_V_1_5.md#3--tenant-block-protocol-tbp-v10"
|
|
11548
|
+
},
|
|
11549
|
+
{
|
|
11550
|
+
"id": "proto-jsp",
|
|
11551
|
+
"icon": "jsp",
|
|
11552
|
+
"acronym": "JSP",
|
|
11553
|
+
"version": "v1.8",
|
|
11554
|
+
"name": "JsonPages Site Protocol",
|
|
11555
|
+
"desc": "Deterministic file system ontology and CLI projection engine. config/ separates global governance from per-page content. Reproducible across every environment.",
|
|
11556
|
+
"specHref": "https://github.com/olonjs/core/blob/main/specs/olonjsSpecs_V_1_5.md#2--jsonpages-site-protocol-jsp-v18"
|
|
11557
|
+
},
|
|
11558
|
+
{
|
|
11559
|
+
"id": "proto-idac",
|
|
11560
|
+
"icon": "idac",
|
|
11561
|
+
"acronym": "IDAC",
|
|
11562
|
+
"version": "v1.0",
|
|
11563
|
+
"name": "ICE Data Contract",
|
|
11564
|
+
"desc": "Mandatory data-jp-* DOM attributes bind every section to its data. Any consumer that can traverse the DOM can identify and operate any content node — human or agent.",
|
|
11565
|
+
"specHref": "https://github.com/olonjs/core/blob/main/specs/olonjsSpecs_V_1_5.md"
|
|
11566
|
+
},
|
|
11567
|
+
{
|
|
11568
|
+
"id": "proto-bsds",
|
|
11569
|
+
"icon": "bsds",
|
|
11570
|
+
"acronym": "BSDS",
|
|
11571
|
+
"version": "v1.0",
|
|
11572
|
+
"name": "Base Schema Fragments",
|
|
11573
|
+
"desc": "BaseSectionData and BaseArrayItem enforce anchor IDs and stable React keys across all capsules. The foundation that doesn't move so your content never drifts.",
|
|
11574
|
+
"specHref": "https://github.com/olonjs/core/blob/main/specs/olonjsSpecs_V_1_5.md"
|
|
11575
|
+
},
|
|
11576
|
+
{
|
|
11577
|
+
"id": "proto-pss",
|
|
11578
|
+
"icon": "pss",
|
|
11579
|
+
"acronym": "PSS",
|
|
11580
|
+
"version": "v1.4",
|
|
11581
|
+
"name": "Path-Based Selection",
|
|
11582
|
+
"desc": "Every node has an address. Content selection uses strict root-to-leaf path semantics — unambiguous, stable, operable by any consumer that knows the contract.",
|
|
11583
|
+
"specHref": "https://github.com/olonjs/core/blob/main/specs/olonjsSpecs_V_1_5.md"
|
|
11584
|
+
}
|
|
11585
|
+
],
|
|
11586
|
+
"anchorId": "Architecture"
|
|
11587
|
+
}
|
|
11588
|
+
},
|
|
11589
|
+
{
|
|
11590
|
+
"id": "example-steps",
|
|
11591
|
+
"type": "olon-example",
|
|
11592
|
+
"data": {
|
|
11593
|
+
"id": "example-steps",
|
|
11594
|
+
"label": "Quick Example",
|
|
11595
|
+
"headline": "Two steps. One contract.",
|
|
11596
|
+
"body": "Scaffold a fully compliant tenant in under three minutes. Then read any page via the OlonJS protocol — from a browser, a script, or an AI agent.",
|
|
11597
|
+
"note": "Every OlonJS tenant exposes a machine-readable manifest at",
|
|
11598
|
+
"noteHref": "http://localhost:5173/mcp-manifest.json",
|
|
11599
|
+
"steps": [
|
|
11600
|
+
{
|
|
11601
|
+
"number": 1,
|
|
11602
|
+
"title": "Scaffold a tenant",
|
|
11603
|
+
"meta": "~3 min",
|
|
11604
|
+
"code": "# Install the CLI\nnpm install -g @olonjs/cli\n\n# Scaffold a new tenant\nnpx @olonjs/cli new tenant\n\n✓ Projecting infrastructure...\n✓ Projecting source (src_tenant_alpha.sh)\n✓ Resolving dependencies\n✓ Tenant scaffolded\n\nsrc/\n components/hero/\n View.tsx\n schema.ts\n types.ts\n index.ts\n data/config/\n site.json\n theme.json\n menu.json\n lib/\n schemas.ts\n base-schemas.ts"
|
|
11605
|
+
},
|
|
11606
|
+
{
|
|
11607
|
+
"number": 2,
|
|
11608
|
+
"title": "Read via OlonJS protocol",
|
|
11609
|
+
"meta": "Any consumer",
|
|
11610
|
+
"code": "// Read any page via the contract\n// Works from browser, script, or AI agent\n\nconst page = await\n navigator.modelContextProtocol\n .readResource(\n 'olon://pages/home'\n );\n\n// Returns the full typed contract\n// { slug, meta, sections: Section[] }\n// No DOM scraping. No layout knowledge.\n// Just the contract.\n\n// {\n// \"slug\": \"home\",\n// \"sections\": [\n// { \"type\": \"hero\", \"data\": {...} },\n// { \"type\": \"features\", \"data\": {...} }\n// ]\n// }"
|
|
11611
|
+
}
|
|
11612
|
+
],
|
|
11613
|
+
"anchorId": "Example"
|
|
11614
|
+
}
|
|
11615
|
+
},
|
|
11616
|
+
{
|
|
11617
|
+
"id": "getstarted-cards",
|
|
11618
|
+
"type": "olon-getstarted",
|
|
11619
|
+
"data": {
|
|
11620
|
+
"id": "getstarted-cards",
|
|
11621
|
+
"label": "Get Started",
|
|
11622
|
+
"headline": "Three paths in.",
|
|
11623
|
+
"body": "Start with the Core package, scaffold a full tenant with the CLI, or deploy a working example in one click.",
|
|
11624
|
+
"cards": [
|
|
11625
|
+
{
|
|
11626
|
+
"id": "card-core",
|
|
11627
|
+
"badge": "Open Core",
|
|
11628
|
+
"badgeStyle": "oss",
|
|
11629
|
+
"title": "Install Core",
|
|
11630
|
+
"body": "The Core package is free and open — forever. The contract, the protocols, the CLI. No lock-in on the foundation.",
|
|
11631
|
+
"code": "npm install @olonjs/core",
|
|
11632
|
+
"linkLabel": "View on GitHub",
|
|
11633
|
+
"linkHref": "https://github.com/olonjs/core"
|
|
11634
|
+
},
|
|
11635
|
+
{
|
|
11636
|
+
"id": "card-cli",
|
|
11637
|
+
"badge": "CLI",
|
|
11638
|
+
"badgeStyle": "cli",
|
|
11639
|
+
"title": "Scaffold a tenant",
|
|
11640
|
+
"body": "The CLI scaffolds a fully compliant tenant from a canonical script. Same result on every machine, every run.",
|
|
11641
|
+
"code": "npx @olonjs/cli new tenant",
|
|
11642
|
+
"linkLabel": "View on npm",
|
|
11643
|
+
"linkHref": "https://www.npmjs.com/package/@olonjs/cli"
|
|
11644
|
+
},
|
|
11645
|
+
{
|
|
11646
|
+
"id": "card-deploy",
|
|
11647
|
+
"badge": "Deploy",
|
|
11648
|
+
"badgeStyle": "deploy",
|
|
11649
|
+
"title": "Deploy a template",
|
|
11650
|
+
"body": "Clone a working OlonJS tenant and deploy it with one click. Explore the full capsule structure in a real project.",
|
|
11651
|
+
"deployLabel": "Deploy template →",
|
|
11652
|
+
"deployHref": "https://github.com/olonjs/core",
|
|
11653
|
+
"linkLabel": "View on npm",
|
|
11654
|
+
"linkHref": "https://www.npmjs.com/package/@olonjs/core"
|
|
11655
|
+
}
|
|
11656
|
+
],
|
|
11657
|
+
"anchorId": "Getstarted"
|
|
11658
|
+
}
|
|
11659
|
+
}
|
|
11660
|
+
]
|
|
11661
|
+
}
|
|
11662
|
+
END_OF_FILE_CONTENT
|
|
11663
|
+
echo "Creating src/data/pages/home_.json..."
|
|
11664
|
+
cat << 'END_OF_FILE_CONTENT' > "src/data/pages/home_.json"
|
|
10371
11665
|
{
|
|
10372
11666
|
"id": "home-page",
|
|
10373
11667
|
"slug": "home",
|
|
@@ -10381,9 +11675,9 @@ cat << 'END_OF_FILE_CONTENT' > "src/data/pages/home.json"
|
|
|
10381
11675
|
"type": "hero",
|
|
10382
11676
|
"data": {
|
|
10383
11677
|
"eyebrow": "Contract layer · v1.4 · Open Core",
|
|
10384
|
-
"title": "
|
|
11678
|
+
"title": "Contract Layer",
|
|
10385
11679
|
"titleHighlight": "for the agentic web.",
|
|
10386
|
-
"description": "
|
|
11680
|
+
"description": "OlonJS is a TypeScript framework for building JSON-driven websites with a deterministic data contract. Every section is typed, validated, and structurally addressable. Designed for reproducible tenant generation and machine-readable output.",
|
|
10387
11681
|
"ctas": [
|
|
10388
11682
|
{
|
|
10389
11683
|
"id": "cta-started",
|
|
@@ -10401,8 +11695,8 @@ cat << 'END_OF_FILE_CONTENT' > "src/data/pages/home.json"
|
|
|
10401
11695
|
"docsLabel": "Explore platform",
|
|
10402
11696
|
"docsHref": "/platform/overview",
|
|
10403
11697
|
"heroImage": {
|
|
10404
|
-
"url": "
|
|
10405
|
-
"alt": ""
|
|
11698
|
+
"url": "data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjIiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDIwMCAyMDAiIHdpZHRoPSI1MTIiIGhlaWdodD0iNTEyIj4KICA8ZGVmcz4KICAgIDxsaW5lYXJHcmFkaWVudCBpZD0iZy1tYWluIiB4Mj0iMSIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiIGdyYWRpZW50VHJhbnNmb3JtPSJtYXRyaXgoMTEwLjc5NSwxMTAuNzk1LC0xMTAuNzk1LDExMC43OTUsNDQuNjAzLDQ0LjYwMykiPgogICAgICA8c3RvcCBvZmZzZXQ9IjAiIHN0b3AtY29sb3I9IiM1QjhFRkYiLz4KICAgICAgPHN0b3Agb2Zmc2V0PSIwLjUiIHN0b3AtY29sb3I9IiMwRjUyRTAiLz4KICAgICAgPHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjMDYzMDkwIi8+CiAgICA8L2xpbmVhckdyYWRpZW50PgogICAgPGxpbmVhckdyYWRpZW50IGlkPSJnLWFjY2VudCIgeDE9IjAiIHkxPSIwIiB4Mj0iMCIgeTI9IjEiPgogICAgICA8c3RvcCBvZmZzZXQ9IjAiIHN0b3AtY29sb3I9IiNBREM4RkYiLz4KICAgICAgPHN0b3Agb2Zmc2V0PSIxIiBzdG9wLWNvbG9yPSIjNUI4RUZGIi8+CiAgICA8L2xpbmVhckdyYWRpZW50PgogIDwvZGVmcz4KICA8IS0tIENoaXAgYm9yZGVyIC0tPgogIDxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0idXJsKCNnLW1haW4pIiBzdHJva2Utd2lkdGg9IjgiCiAgICBkPSJtNTkuMzggNDQuNmg4MS4yNGM4LjE2IDAgMTQuNzggNi42MiAxNC43OCAxNC43OHY4MS4yNGMwIDguMTYtNi42MiAxNC43OC0xNC43OCAxNC43OGgtODEuMjRjLTguMTYgMC0xNC43OC02LjYyLTE0Ljc4LTE0Ljc4di04MS4yNGMwLTguMTYgNi42Mi0xNC43OCAxNC43OC0xNC43OHoiLz4KICA8IS0tIExlZnQgcGlucyAtLT4KICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InVybCgjZy1tYWluKSIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2Utd2lkdGg9IjYiIGQ9Im03LjY3IDcyLjNoMzYuOTMiLz4KICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InVybCgjZy1tYWluKSIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2Utd2lkdGg9IjYiIGQ9Im03LjY3IDEwMGgzNi45MyIvPgogIDxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0idXJsKCNnLW1haW4pIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS13aWR0aD0iNiIgZD0ibTcuNjcgMTI3LjdoMzYuOTMiLz4KICA8IS0tIFJpZ2h0IHBpbnMgLS0+CiAgPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJ1cmwoI2ctbWFpbikiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSI2IiBkPSJtMTU1LjQgNzIuM2gzNi45MyIvPgogIDxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0idXJsKCNnLW1haW4pIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS13aWR0aD0iNiIgZD0ibTE1NS40IDEwMGgzNi45MyIvPgogIDxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0idXJsKCNnLW1haW4pIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS13aWR0aD0iNiIgZD0ibTE1NS40IDEyNy43aDM2LjkzIi8+CiAgPCEtLSBUb3AgcGlucyAtLT4KICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InVybCgjZy1tYWluKSIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2Utd2lkdGg9IjYiIGQ9Im03Mi4zIDcuNjd2MzYuOTMiLz4KICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InVybCgjZy1tYWluKSIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2Utd2lkdGg9IjYiIGQ9Im0xMDAgNy42N3YzNi45MyIvPgogIDxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0idXJsKCNnLW1haW4pIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS13aWR0aD0iNiIgZD0ibTEyNy43IDcuNjd2MzYuOTMiLz4KICA8IS0tIEJvdHRvbSBwaW5zIC0tPgogIDxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0idXJsKCNnLW1haW4pIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS13aWR0aD0iNiIgZD0ibTcyLjMgMTU1LjR2MzYuOTMiLz4KICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InVybCgjZy1tYWluKSIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2Utd2lkdGg9IjYiIGQ9Im0xMDAgMTU1LjR2MzYuOTMiLz4KICA8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9InVybCgjZy1tYWluKSIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiBzdHJva2Utd2lkdGg9IjYiIGQ9Im0xMjcuNyAxNTUuNHYzNi45MyIvPgogIDwhLS0gQ29ybmVyIG5vZGVzIC0tPgogIDxjaXJjbGUgZmlsbD0idXJsKCNnLW1haW4pIiBjeD0iNzIuMyIgY3k9IjcyLjMiIHI9IjcuMzkiLz4KICA8Y2lyY2xlIGZpbGw9InVybCgjZy1tYWluKSIgY3g9IjEyNy43IiBjeT0iNzIuMyIgcj0iNy4zOSIvPgogIDxjaXJjbGUgZmlsbD0idXJsKCNnLW1haW4pIiBjeD0iNzIuMyIgY3k9IjEyNy43IiByPSI3LjM5Ii8+CiAgPGNpcmNsZSBmaWxsPSJ1cmwoI2ctbWFpbikiIGN4PSIxMjcuNyIgY3k9IjEyNy43IiByPSI3LjM5Ii8+CiAgPCEtLSBDZW50ZXIgbm9kZSDigJQgYWNjZW50IC0tPgogIDxjaXJjbGUgZmlsbD0idXJsKCNnLWFjY2VudCkiIGN4PSIxMDAiIGN5PSIxMDAiIHI9IjkuMjMiLz4KICA8IS0tIENvbm5lY3Rpb24gbGluZXMgLS0+CiAgPHBhdGggb3BhY2l0eT0iMC4zIiBmaWxsPSJub25lIiBzdHJva2U9IiM1QjhFRkYiIHN0cm9rZS13aWR0aD0iMiIgZD0ibTcyLjMgNzIuM2wyNy43IDI3LjciLz4KICA8cGF0aCBvcGFjaXR5PSIwLjMiIGZpbGw9Im5vbmUiIHN0cm9rZT0iIzVCOEVGRiIgc3Ryb2tlLXdpZHRoPSIyIiBkPSJtMTI3LjcgNzIuM2wtMjcuNyAyNy43Ii8+CiAgPHBhdGggb3BhY2l0eT0iMC4zIiBmaWxsPSJub25lIiBzdHJva2U9IiM1QjhFRkYiIHN0cm9rZS13aWR0aD0iMiIgZD0ibTcyLjMgMTI3LjdsMjcuNy0yNy43Ii8+CiAgPHBhdGggb3BhY2l0eT0iMC4zIiBmaWxsPSJub25lIiBzdHJva2U9IiM1QjhFRkYiIHN0cm9rZS13aWR0aD0iMiIgZD0ibTEyNy43IDEyNy43bC0yNy43LTI3LjciLz4KPC9zdmc+Cg==",
|
|
11699
|
+
"alt": "icon-ai-specs.svg"
|
|
10406
11700
|
}
|
|
10407
11701
|
},
|
|
10408
11702
|
"settings": {
|
|
@@ -10414,9 +11708,9 @@ cat << 'END_OF_FILE_CONTENT' > "src/data/pages/home.json"
|
|
|
10414
11708
|
"type": "feature-grid",
|
|
10415
11709
|
"data": {
|
|
10416
11710
|
"label": "Why OlonJS",
|
|
10417
|
-
"sectionTitle": "A
|
|
10418
|
-
"sectionTitleItalic": "part of something greater.",
|
|
10419
|
-
"sectionLead": "
|
|
11711
|
+
"sectionTitle": "A Meaningful Web",
|
|
11712
|
+
"sectionTitleItalic": "Whole in itself, part of something greater.",
|
|
11713
|
+
"sectionLead": "Most web frameworks separate concerns across layers — data, UI, validation, metadata — with no shared contract between them. OlonJS inverts this: the JSON data structure is the contract. Every layer — rendering, editing, validation, machine access — is a deterministic projection of the same typed source. The result is a site that is structurally coherent by construction, not by convention.",
|
|
10420
11714
|
"cards": [
|
|
10421
11715
|
{
|
|
10422
11716
|
"id": "card-endpoints",
|
|
@@ -10424,8 +11718,8 @@ cat << 'END_OF_FILE_CONTENT' > "src/data/pages/home.json"
|
|
|
10424
11718
|
"url": "/icons/features/icon-json-files.svg",
|
|
10425
11719
|
"alt": "JSON files icon"
|
|
10426
11720
|
},
|
|
10427
|
-
"title": "
|
|
10428
|
-
"description": "
|
|
11721
|
+
"title": "Modular Type Registry",
|
|
11722
|
+
"description": "Core exports an empty SectionDataRegistry. Tenants extend it via module augmentation — no Core changes required. Full TypeScript inference across all section types at compile-time."
|
|
10429
11723
|
},
|
|
10430
11724
|
{
|
|
10431
11725
|
"id": "card-schema",
|
|
@@ -10433,8 +11727,8 @@ cat << 'END_OF_FILE_CONTENT' > "src/data/pages/home.json"
|
|
|
10433
11727
|
"url": "/icons/features/icon-zod-schemas.svg",
|
|
10434
11728
|
"alt": "Zod schemas icon"
|
|
10435
11729
|
},
|
|
10436
|
-
"title": "
|
|
10437
|
-
"description": "
|
|
11730
|
+
"title": "Tenant Block Protocol",
|
|
11731
|
+
"description": "Each section type lives in a self-contained capsule: View.tsx, schema.ts, types.ts, index.ts. The capsule is the unit of extension — renderable, validatable, and ingestible by the engine without additional configuration."
|
|
10438
11732
|
},
|
|
10439
11733
|
{
|
|
10440
11734
|
"id": "card-ai",
|
|
@@ -10442,8 +11736,8 @@ cat << 'END_OF_FILE_CONTENT' > "src/data/pages/home.json"
|
|
|
10442
11736
|
"url": "/icons/features/icon-ai-specs.svg",
|
|
10443
11737
|
"alt": "AI specs icon"
|
|
10444
11738
|
},
|
|
10445
|
-
"title": "
|
|
10446
|
-
"description": "
|
|
11739
|
+
"title": "Deterministic CLI",
|
|
11740
|
+
"description": "@olonjs/cli scaffolds new tenants from a canonical script. Infrastructure, source structure, and dependencies are projected deterministically. Output is reproducible across environments"
|
|
10447
11741
|
},
|
|
10448
11742
|
{
|
|
10449
11743
|
"id": "card-multitenant",
|
|
@@ -10451,8 +11745,8 @@ cat << 'END_OF_FILE_CONTENT' > "src/data/pages/home.json"
|
|
|
10451
11745
|
"url": "/icons/features/icon-own-data.svg",
|
|
10452
11746
|
"alt": "Own data icon"
|
|
10453
11747
|
},
|
|
10454
|
-
"title": "
|
|
10455
|
-
"description": "
|
|
11748
|
+
"title": "ICE Data Contract",
|
|
11749
|
+
"description": "Mandatory data-jp-* DOM attributes bind rendered sections to their data contract. The binding is structural, not UI-dependent — any consumer that can traverse the DOM can identify and address any content node."
|
|
10456
11750
|
},
|
|
10457
11751
|
{
|
|
10458
11752
|
"id": "card-governance",
|
|
@@ -10460,8 +11754,8 @@ cat << 'END_OF_FILE_CONTENT' > "src/data/pages/home.json"
|
|
|
10460
11754
|
"url": "/icons/features/icon-governance.svg",
|
|
10461
11755
|
"alt": "Governance icon"
|
|
10462
11756
|
},
|
|
10463
|
-
"title": "
|
|
10464
|
-
"description": "
|
|
11757
|
+
"title": "Base Schema Fragments",
|
|
11758
|
+
"description": "BaseSectionData and BaseArrayItem are the required base types for all section data schemas and array items. They enforce anchor IDs and stable React keys across all capsules."
|
|
10465
11759
|
},
|
|
10466
11760
|
{
|
|
10467
11761
|
"id": "card-deploy",
|
|
@@ -10469,8 +11763,8 @@ cat << 'END_OF_FILE_CONTENT' > "src/data/pages/home.json"
|
|
|
10469
11763
|
"url": "/icons/features/icon-clean-commits.svg",
|
|
10470
11764
|
"alt": "Clean commits icon"
|
|
10471
11765
|
},
|
|
10472
|
-
"title": "
|
|
10473
|
-
"description": "
|
|
11766
|
+
"title": "Path-Based Selection",
|
|
11767
|
+
"description": "Content selection uses strict root-to-leaf path semantics. Each segment identifies a node unambiguously. The flat itemField/itemId protocol is removed in v1.3+."
|
|
10474
11768
|
}
|
|
10475
11769
|
],
|
|
10476
11770
|
"proofStatement": "Working end-to-end with production routing parity.",
|
|
@@ -10550,7 +11844,6 @@ cat << 'END_OF_FILE_CONTENT' > "src/data/pages/home.json"
|
|
|
10550
11844
|
}
|
|
10551
11845
|
END_OF_FILE_CONTENT
|
|
10552
11846
|
mkdir -p "src/data/pages/platform"
|
|
10553
|
-
# SKIP: src/data/pages/platform.json:Zone.Identifier is binary and cannot be embedded as text.
|
|
10554
11847
|
echo "Creating src/data/pages/platform/overview.json..."
|
|
10555
11848
|
cat << 'END_OF_FILE_CONTENT' > "src/data/pages/platform/overview.json"
|
|
10556
11849
|
{
|
|
@@ -12042,6 +13335,13 @@ import { CloudAiNativeGridView } from '@/components/cloud-ai-native-grid';
|
|
|
12042
13335
|
import { PageHero } from '@/components/page-hero';
|
|
12043
13336
|
import { Tiptap } from '@/components/tiptap';
|
|
12044
13337
|
|
|
13338
|
+
|
|
13339
|
+
import { View as OlonHeroView } from '@/components/olon-hero';
|
|
13340
|
+
import { View as OlonWhyView } from '@/components/olon-why';
|
|
13341
|
+
import { View as OlonArchitectureView } from '@/components/olon-architecture';
|
|
13342
|
+
import { View as OlonExampleView } from '@/components/olon-example';
|
|
13343
|
+
import { View as OlonGetStartedView } from '@/components/olon-getstarted';
|
|
13344
|
+
|
|
12045
13345
|
export const ComponentRegistry: {
|
|
12046
13346
|
[K in SectionType]: React.FC<SectionComponentPropsMap[K]>;
|
|
12047
13347
|
} = {
|
|
@@ -12055,6 +13355,13 @@ export const ComponentRegistry: {
|
|
|
12055
13355
|
'cloud-ai-native-grid': CloudAiNativeGridView as React.FC<SectionComponentPropsMap['cloud-ai-native-grid']>,
|
|
12056
13356
|
'page-hero': PageHero as React.FC<SectionComponentPropsMap['page-hero']>,
|
|
12057
13357
|
'tiptap': Tiptap as React.FC<SectionComponentPropsMap['tiptap']>,
|
|
13358
|
+
|
|
13359
|
+
|
|
13360
|
+
'olon-hero': OlonHeroView,
|
|
13361
|
+
'olon-why': OlonWhyView,
|
|
13362
|
+
'olon-architecture': OlonArchitectureView,
|
|
13363
|
+
'olon-example': OlonExampleView,
|
|
13364
|
+
'olon-getstarted': OlonGetStartedView,
|
|
12058
13365
|
};
|
|
12059
13366
|
|
|
12060
13367
|
END_OF_FILE_CONTENT
|
|
@@ -12175,6 +13482,7 @@ export const ImageSelectionSchema = z
|
|
|
12175
13482
|
* Capsules extend these for consistent anchorId, array items, and settings.
|
|
12176
13483
|
*/
|
|
12177
13484
|
export const BaseSectionData = z.object({
|
|
13485
|
+
id: z.string().optional(),
|
|
12178
13486
|
anchorId: z.string().optional().describe('ui:text'),
|
|
12179
13487
|
});
|
|
12180
13488
|
|
|
@@ -12456,6 +13764,12 @@ import { CloudAiNativeGridSchema } from '@/components/cloud-ai-native-grid';
|
|
|
12456
13764
|
import { PageHeroSchema } from '@/components/page-hero';
|
|
12457
13765
|
import { TiptapSchema } from '@/components/tiptap';
|
|
12458
13766
|
|
|
13767
|
+
import { OlonHeroSchema } from '@/components/olon-hero';
|
|
13768
|
+
import { OlonWhySchema } from '@/components/olon-why';
|
|
13769
|
+
import { OlonArchitectureSchema } from '@/components/olon-architecture';
|
|
13770
|
+
import { OlonExampleSchema } from '@/components/olon-example';
|
|
13771
|
+
import { OlonGetStartedSchema } from '@/components/olon-getstarted';
|
|
13772
|
+
|
|
12459
13773
|
export const SECTION_SCHEMAS = {
|
|
12460
13774
|
'header': HeaderSchema,
|
|
12461
13775
|
'footer': FooterSchema,
|
|
@@ -12466,7 +13780,13 @@ export const SECTION_SCHEMAS = {
|
|
|
12466
13780
|
'design-system': DesignSystemSchema,
|
|
12467
13781
|
'cloud-ai-native-grid': CloudAiNativeGridSchema,
|
|
12468
13782
|
'page-hero': PageHeroSchema,
|
|
12469
|
-
'tiptap':
|
|
13783
|
+
'tiptap': TiptapSchema,
|
|
13784
|
+
|
|
13785
|
+
'olon-hero': OlonHeroSchema,
|
|
13786
|
+
'olon-why': OlonWhySchema,
|
|
13787
|
+
'olon-architecture': OlonArchitectureSchema,
|
|
13788
|
+
'olon-example': OlonExampleSchema,
|
|
13789
|
+
'olon-getstarted': OlonGetStartedSchema,
|
|
12470
13790
|
} as const;
|
|
12471
13791
|
|
|
12472
13792
|
export type SectionType = keyof typeof SECTION_SCHEMAS;
|
|
@@ -12613,6 +13933,13 @@ import type { CloudAiNativeGridData, CloudAiNativeGridSettings } from '@/com
|
|
|
12613
13933
|
import type { PageHeroData, PageHeroSettings } from '@/components/page-hero';
|
|
12614
13934
|
import type { TiptapData, TiptapSettings } from '@/components/tiptap';
|
|
12615
13935
|
|
|
13936
|
+
|
|
13937
|
+
import type { OlonHeroData } from '@/components/olon-hero';
|
|
13938
|
+
import type { OlonWhyData } from '@/components/olon-why';
|
|
13939
|
+
import type { OlonArchitectureData } from '@/components/olon-architecture';
|
|
13940
|
+
import type { OlonExampleData } from '@/components/olon-example';
|
|
13941
|
+
import type { OlonGetStartedData } from '@/components/olon-getstarted';
|
|
13942
|
+
|
|
12616
13943
|
export type SectionComponentPropsMap = {
|
|
12617
13944
|
'header': { data: HeaderData; settings?: HeaderSettings; menu: MenuItem[] };
|
|
12618
13945
|
'footer': { data: FooterData; settings?: FooterSettings };
|
|
@@ -12624,6 +13951,13 @@ export type SectionComponentPropsMap = {
|
|
|
12624
13951
|
'cloud-ai-native-grid': { data: CloudAiNativeGridData; settings?: CloudAiNativeGridSettings };
|
|
12625
13952
|
'page-hero': { data: PageHeroData; settings?: PageHeroSettings };
|
|
12626
13953
|
'tiptap': { data: TiptapData; settings?: TiptapSettings };
|
|
13954
|
+
|
|
13955
|
+
|
|
13956
|
+
'olon-hero': { data: OlonHeroData };
|
|
13957
|
+
'olon-why': { data: OlonWhyData };
|
|
13958
|
+
'olon-architecture': { data: OlonArchitectureData };
|
|
13959
|
+
'olon-example': { data: OlonExampleData };
|
|
13960
|
+
'olon-getstarted': { data: OlonGetStartedData };
|
|
12627
13961
|
};
|
|
12628
13962
|
|
|
12629
13963
|
declare module '@olonjs/core' {
|
|
@@ -12638,6 +13972,11 @@ declare module '@olonjs/core' {
|
|
|
12638
13972
|
'cloud-ai-native-grid': CloudAiNativeGridData;
|
|
12639
13973
|
'page-hero': PageHeroData;
|
|
12640
13974
|
'tiptap': TiptapData;
|
|
13975
|
+
'olon-hero': OlonHeroData;
|
|
13976
|
+
'olon-why': OlonWhyData;
|
|
13977
|
+
'olon-architecture': OlonArchitectureData;
|
|
13978
|
+
'olon-example': OlonExampleData;
|
|
13979
|
+
'olon-getstarted': OlonGetStartedData;
|
|
12641
13980
|
}
|
|
12642
13981
|
export interface SectionSettingsRegistry {
|
|
12643
13982
|
'header': HeaderSettings;
|
|
@@ -12918,7 +14257,12 @@ export default defineConfig({
|
|
|
12918
14257
|
|
|
12919
14258
|
if (isPageJsonRequest) {
|
|
12920
14259
|
const normalizedPath = decodeURIComponent(pathname).replace(/\\/g, '/');
|
|
12921
|
-
|
|
14260
|
+
// Rimuoviamo la root folder opzionale "/pages/" introdotta per matchare la prod e il file extension
|
|
14261
|
+
const slug = normalizedPath
|
|
14262
|
+
.replace(/^\/+/, '')
|
|
14263
|
+
.replace(/^pages\//i, '')
|
|
14264
|
+
.replace(/\.json$/i, '')
|
|
14265
|
+
.replace(/^\/+|\/+$/g, '');
|
|
12922
14266
|
const candidate = path.resolve(DATA_PAGES_DIR, `${slug}.json`);
|
|
12923
14267
|
const isInsidePagesDir = candidate.startsWith(`${DATA_PAGES_DIR}${path.sep}`) || candidate === DATA_PAGES_DIR;
|
|
12924
14268
|
if (!slug || !isInsidePagesDir || !fs.existsSync(candidate) || !fs.statSync(candidate).isFile()) {
|