This is the snapshot the production landing site (nibiru-framework.com) is deployed from. Brings together the recent splash + docs migration to the v4 "Cosmos" design system, the new in-framework AI module, and the framework groundwork that backs the framework-reference extraction. What lands: - docs/: Astro + Starlight site with the v4 dark cosmic palette, GalaxyHero canvas constellation, Mission Control chat (wired to /api/oracle → api.neuronetz.ai via providers.mjs Ollama), 5-panel MMVC stage (Model · AI · Module · Controller · View), translated EN/DE/JA/ES/FR content, PWA + sitemap + llms.txt + Umami analytics. - docs/design-system/: canonical mockup bundle (source/index-v2.html for splash, source/docs-system.html + preview/ for docs, SPEC.md, tokens). - docs/scripts/extraction/framework-reference-v2.md: deep framework reference (~1.6k lines, file:line citations, every public factory and idiom — basis for the LoRA training corpus. - application/module/ai/: AI module with chat / embed / RAG / agent plugins, plus pdoQuery / httpGet / fileRead tools and Modelfile + smoke-test in training/. - application/module/users/: user / ACL / form-factory traits used as the reference plugin pattern for the framework docs. - application/settings/config/database/: schema + seed migrations including the AI module tables (200–203). - Form factory + autogenerator changes the framework-reference-v2 covers. Production secrets stay out: docs/.env, settings.production.ini and ai.production.ini are all gitignored (.example files are in tree). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
193 lines
7.2 KiB
JavaScript
193 lines
7.2 KiB
JavaScript
/* global React */
|
|
const { useState } = React;
|
|
|
|
// ============================================================
|
|
// TOP NAV
|
|
// ============================================================
|
|
function TopNav({ theme = "dark", onToggleTheme = () => {}, locale = "EN" }) {
|
|
return (
|
|
<header className="topnav">
|
|
<div className="topnav-brand">
|
|
<LotusMark />
|
|
<div className="topnav-brand-text">
|
|
<div className="topnav-brand-name">Nibiru</div>
|
|
<div className="topnav-brand-tag">Create, Invent, Impress</div>
|
|
</div>
|
|
</div>
|
|
|
|
<button className="topnav-search" aria-label="Search docs">
|
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
|
|
<circle cx="11" cy="11" r="8"/>
|
|
<path d="m21 21-4.35-4.35"/>
|
|
</svg>
|
|
<span>Search</span>
|
|
<kbd>⌘ K</kbd>
|
|
</button>
|
|
|
|
<div className="topnav-right">
|
|
<a href="#" className="topnav-icon" aria-label="GitHub">
|
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor">
|
|
<path d="M12 .5C5.65.5.5 5.65.5 12c0 5.08 3.29 9.39 7.86 10.91.58.1.79-.25.79-.56v-1.97c-3.2.69-3.87-1.54-3.87-1.54-.52-1.33-1.27-1.69-1.27-1.69-1.04-.71.08-.7.08-.7 1.15.08 1.76 1.18 1.76 1.18 1.02 1.75 2.68 1.25 3.34.96.1-.74.4-1.25.72-1.54-2.55-.29-5.24-1.28-5.24-5.69 0-1.26.45-2.29 1.18-3.1-.12-.29-.51-1.46.11-3.04 0 0 .96-.31 3.15 1.18a10.95 10.95 0 0 1 5.74 0c2.18-1.49 3.14-1.18 3.14-1.18.62 1.58.23 2.75.11 3.04.74.81 1.18 1.84 1.18 3.1 0 4.42-2.69 5.39-5.26 5.68.41.36.78 1.06.78 2.13v3.16c0 .31.21.67.8.56C20.21 21.39 23.5 17.08 23.5 12 23.5 5.65 18.35.5 12 .5Z"/>
|
|
</svg>
|
|
</a>
|
|
<button className="topnav-icon" aria-label="Toggle theme" onClick={onToggleTheme}>
|
|
{theme === "dark" ? (
|
|
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
|
|
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/>
|
|
</svg>
|
|
) : (
|
|
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
|
|
<circle cx="12" cy="12" r="4"/>
|
|
<path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41"/>
|
|
</svg>
|
|
)}
|
|
</button>
|
|
<button className="topnav-locale" aria-label="Locale">
|
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
|
|
<circle cx="12" cy="12" r="10"/>
|
|
<path d="M2 12h20M12 2a15 15 0 0 1 0 20M12 2a15 15 0 0 0 0 20"/>
|
|
</svg>
|
|
<span>{locale}</span>
|
|
<svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5">
|
|
<path d="m6 9 6 6 6-6"/>
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
</header>
|
|
);
|
|
}
|
|
|
|
function LotusMark({ size = 36 }) {
|
|
// Real Nibiru logo, sourced from window.NIBIRU_LOTUS so the bundler picks it up
|
|
// (it would miss a relative path inside a JSX template string).
|
|
const src = (typeof window !== "undefined" && window.NIBIRU_LOTUS) || "docs-system/assets/lotus.png";
|
|
return (
|
|
<img
|
|
src={src}
|
|
width={size}
|
|
height={Math.round(size * 569 / 861)}
|
|
alt="Nibiru"
|
|
className="lotus-mark"
|
|
style={{ display: "block" }}
|
|
/>
|
|
);
|
|
}
|
|
|
|
// ============================================================
|
|
// SIDEBAR
|
|
// ============================================================
|
|
function Sidebar() {
|
|
const [openSections, setOpenSections] = useState({
|
|
"get-started": true, "framework": true, "cli": false, "advanced": false,
|
|
});
|
|
const toggle = (id) => setOpenSections((s) => ({ ...s, [id]: !s[id] }));
|
|
|
|
const nav = [
|
|
{
|
|
id: "get-started", label: "Get Started",
|
|
items: [
|
|
{ label: "What is Nibiru?", active: true },
|
|
{ label: "Why Nibiru, not Laravel" },
|
|
{ label: "Installation" },
|
|
{ label: "Quick Start" },
|
|
{ label: "Project Structure" },
|
|
{ label: "Run It Locally" },
|
|
{ label: "Deployment" },
|
|
],
|
|
},
|
|
{
|
|
id: "framework", label: "The Framework",
|
|
items: [
|
|
{ label: "Architecture (MMVC)" },
|
|
{ label: "Bootstrap & Dispatcher" },
|
|
{ label: "Routing" },
|
|
{ label: "Controllers" },
|
|
{ label: "Views & Smarty" },
|
|
{ label: "Models" },
|
|
{ label: "Modules", badge: "core" },
|
|
{ label: "Forms" },
|
|
{ label: "Database & Migrations" },
|
|
{ label: "Auth" },
|
|
{ label: "Config & Settings" },
|
|
{ label: "Pagination" },
|
|
{ label: "Registry" },
|
|
],
|
|
},
|
|
{
|
|
id: "cli", label: "CLI",
|
|
items: [
|
|
{ label: "nibiru new" },
|
|
{ label: "nibiru migrate" },
|
|
{ label: "nibiru make" },
|
|
],
|
|
},
|
|
{
|
|
id: "advanced", label: "Advanced",
|
|
items: [
|
|
{ label: "Plugins" },
|
|
{ label: "Observer pattern" },
|
|
{ label: "Caching", badge: "new" },
|
|
],
|
|
},
|
|
];
|
|
|
|
return (
|
|
<aside className="sidebar">
|
|
<nav>
|
|
{nav.map((section) => (
|
|
<div key={section.id} className="sidebar-section">
|
|
<button
|
|
className="sidebar-heading"
|
|
onClick={() => toggle(section.id)}
|
|
aria-expanded={openSections[section.id]}
|
|
>
|
|
<span>{section.label}</span>
|
|
<svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5"
|
|
style={{ transform: openSections[section.id] ? "rotate(0deg)" : "rotate(-90deg)", transition: "transform 200ms" }}>
|
|
<path d="m6 9 6 6 6-6"/>
|
|
</svg>
|
|
</button>
|
|
{openSections[section.id] && (
|
|
<ul className="sidebar-list">
|
|
{section.items.map((item) => (
|
|
<li key={item.label}>
|
|
<a href="#" className={"sidebar-item" + (item.active ? " active" : "")}>
|
|
<span>{item.label}</span>
|
|
{item.badge && <span className={"sidebar-badge sidebar-badge-" + item.badge}>{item.badge}</span>}
|
|
</a>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
)}
|
|
</div>
|
|
))}
|
|
</nav>
|
|
</aside>
|
|
);
|
|
}
|
|
|
|
// ============================================================
|
|
// RIGHT TOC ("On this page")
|
|
// ============================================================
|
|
function RightTOC({ items, activeId }) {
|
|
return (
|
|
<aside className="toc">
|
|
<div className="toc-label">On this page</div>
|
|
<ul className="toc-list">
|
|
{items.map((item) => (
|
|
<li key={item.id} className={"toc-item toc-level-" + item.level}>
|
|
<a href={"#" + item.id} className={item.id === activeId ? "active" : ""}>
|
|
{item.label}
|
|
</a>
|
|
</li>
|
|
))}
|
|
</ul>
|
|
<div className="toc-edit">
|
|
<a href="#"><svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="M12 20h9M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4Z"/></svg> Edit this page</a>
|
|
</div>
|
|
</aside>
|
|
);
|
|
}
|
|
|
|
Object.assign(window, { TopNav, Sidebar, RightTOC, LotusMark });
|