several sites converted to static site content

This commit is contained in:
Oliver Kieselbach
2026-03-04 18:54:50 +01:00
parent f7a9d38de6
commit e89f6222cd
10 changed files with 106 additions and 68 deletions
@@ -1,5 +1,3 @@
"use client";
import Link from "next/link";
import { PublicPageHeader } from "../../components/PublicPageHeader";
import { PublicSiteNavbar } from "../../components/PublicSiteNavbar";
@@ -1,56 +1,19 @@
"use client";
import { useEffect, useState } from "react";
import { PublicSiteNavbar } from "../../components/PublicSiteNavbar";
import { PublicPageHeader } from "../../components/PublicPageHeader";
import { SectionPrivatePreview } from "./sections/SectionPrivatePreview";
import { SectionOverview } from "./sections/SectionOverview";
import { SectionSetup } from "./sections/SectionSetup";
import { SectionAgentSetup } from "./sections/SectionAgentSetup";
import { SectionSettings } from "./sections/SectionSettings";
import { SectionGatherRules } from "./sections/SectionGatherRules";
import { SectionAnalyzeRules } from "./sections/SectionAnalyzeRules";
import Link from "next/link";
import { usePathname } from "next/navigation";
import { useState } from "react";
import { NAV_SECTIONS } from "./docsNavSections";
const NAV_SECTIONS = [
{ id: "private-preview", label: "Private Preview" },
{ id: "overview", label: "Overview" },
{ id: "setup", label: "Setup" },
{ id: "agent-setup", label: "Agent Setup" },
{ id: "settings", label: "Settings" },
{ id: "gather-rules", label: "Gather Rules" },
{ id: "analyze-rules", label: "Analyze Rules" },
];
const SECTION_COMPONENTS: Record<string, () => JSX.Element> = {
"private-preview": SectionPrivatePreview,
"overview": SectionOverview,
"setup": SectionSetup,
"agent-setup": SectionAgentSetup,
"settings": SectionSettings,
"gather-rules": SectionGatherRules,
"analyze-rules": SectionAnalyzeRules,
};
export default function DocsPage() {
const [activeSection, setActiveSection] = useState("overview");
export function DocsSidebar({ children }: { children: React.ReactNode }) {
const pathname = usePathname();
const [mobileSidebarOpen, setMobileSidebarOpen] = useState(false);
useEffect(() => {
const hash = window.location.hash.replace("#", "");
if (hash && NAV_SECTIONS.some((s) => s.id === hash)) {
setActiveSection(hash);
}
}, []);
const ActiveContent = SECTION_COMPONENTS[activeSection] ?? SectionOverview;
const activeSection = pathname.split("/").pop() ?? "overview";
const activeLabel = NAV_SECTIONS.find((s) => s.id === activeSection)?.label ?? "Contents";
return (
<div className="min-h-screen bg-gray-50">
<PublicSiteNavbar showSectionLinks={false} />
<PublicPageHeader title="Documentation" />
<>
{/* Mobile sidebar overlay */}
{mobileSidebarOpen && (
<div
@@ -79,16 +42,17 @@ export default function DocsPage() {
<ul className="p-3 space-y-0.5">
{NAV_SECTIONS.map((s) => (
<li key={s.id}>
<button
onClick={() => { setActiveSection(s.id); setMobileSidebarOpen(false); }}
className={`w-full text-left px-3 py-2 rounded-md text-sm transition-colors ${
<Link
href={`/docs/${s.id}`}
onClick={() => setMobileSidebarOpen(false)}
className={`block w-full text-left px-3 py-2 rounded-md text-sm transition-colors ${
activeSection === s.id
? "bg-blue-50 text-blue-700 font-semibold"
: "text-gray-600 hover:bg-gray-100 hover:text-gray-900"
}`}
>
{s.label}
</button>
</Link>
</li>
))}
</ul>
@@ -106,23 +70,23 @@ export default function DocsPage() {
<ul className="space-y-0.5">
{NAV_SECTIONS.map((s) => (
<li key={s.id}>
<button
onClick={() => setActiveSection(s.id)}
className={`w-full text-left px-3 py-2 rounded-md text-sm transition-colors ${
<Link
href={`/docs/${s.id}`}
className={`block px-3 py-2 rounded-md text-sm transition-colors ${
activeSection === s.id
? "bg-blue-50 text-blue-700 font-semibold"
: "text-gray-600 hover:bg-gray-100 hover:text-gray-900"
}`}
>
{s.label}
</button>
</Link>
</li>
))}
</ul>
</nav>
</aside>
{/* Content — only the active section is rendered */}
{/* Content */}
<main className="flex-1 min-w-0 space-y-8">
{/* Mobile: contents toggle bar */}
@@ -141,14 +105,14 @@ export default function DocsPage() {
</button>
</div>
<ActiveContent />
{children}
<div className="text-center text-sm text-gray-500 pb-4">
<p>Autopilot Monitor v1.0.0</p>
<p className="mt-1">Documentation last updated: {new Date().toLocaleDateString()}</p>
</div>
</main>
</div>
</div>
</>
);
}
@@ -0,0 +1,57 @@
import { notFound } from "next/navigation";
import type { Metadata } from "next";
import { NAV_SECTIONS, type SectionId } from "../docsNavSections";
import { SectionPrivatePreview } from "../sections/SectionPrivatePreview";
import { SectionOverview } from "../sections/SectionOverview";
import { SectionSetup } from "../sections/SectionSetup";
import { SectionAgentSetup } from "../sections/SectionAgentSetup";
import { SectionSettings } from "../sections/SectionSettings";
import { SectionGatherRules } from "../sections/SectionGatherRules";
import { SectionAnalyzeRules } from "../sections/SectionAnalyzeRules";
const SECTION_COMPONENTS: Record<SectionId, React.ComponentType> = {
"private-preview": SectionPrivatePreview,
"overview": SectionOverview,
"setup": SectionSetup,
"agent-setup": SectionAgentSetup,
"settings": SectionSettings,
"gather-rules": SectionGatherRules,
"analyze-rules": SectionAnalyzeRules,
};
export function generateStaticParams() {
return NAV_SECTIONS.map((s) => ({ section: s.id }));
}
type Props = { params: Promise<{ section: string }> };
export async function generateMetadata({ params }: Props): Promise<Metadata> {
const { section } = await params;
const nav = NAV_SECTIONS.find((s) => s.id === section);
if (!nav) return {};
return {
title: nav.label,
description: nav.description,
openGraph: {
title: `${nav.label} – Autopilot Monitor Docs`,
description: nav.description,
url: `https://autopilotmonitor.com/docs/${section}`,
},
twitter: {
title: `${nav.label} – Autopilot Monitor Docs`,
description: nav.description,
},
alternates: {
canonical: `https://autopilotmonitor.com/docs/${section}`,
},
};
}
export default async function DocsSectionPage({ params }: Props) {
const { section } = await params;
const SectionContent = SECTION_COMPONENTS[section as SectionId];
if (!SectionContent) notFound();
return <SectionContent />;
}
@@ -0,0 +1,11 @@
export const NAV_SECTIONS = [
{ id: "private-preview", label: "Private Preview", description: "Private preview access and onboarding for Autopilot Monitor." },
{ id: "overview", label: "Overview", description: "Overview of Autopilot Monitor architecture and capabilities." },
{ id: "setup", label: "Setup", description: "Step-by-step setup guide for deploying Autopilot Monitor." },
{ id: "agent-setup", label: "Agent Setup", description: "Configure and deploy the Autopilot Monitor agent via Intune." },
{ id: "settings", label: "Settings", description: "Autopilot Monitor settings and configuration options." },
{ id: "gather-rules", label: "Gather Rules", description: "Configure data gathering rules for Autopilot Monitor diagnostics." },
{ id: "analyze-rules", label: "Analyze Rules", description: "Configure analysis rules for Autopilot enrollment evaluation." },
] as const;
export type SectionId = (typeof NAV_SECTIONS)[number]["id"];
@@ -1,7 +1,13 @@
import type { Metadata } from "next";
import { PublicSiteNavbar } from "../../components/PublicSiteNavbar";
import { PublicPageHeader } from "../../components/PublicPageHeader";
import { DocsSidebar } from "./DocsSidebar";
export const metadata: Metadata = {
title: "Documentation",
title: {
template: "%s – Autopilot Monitor Docs",
default: "Documentation – Autopilot Monitor",
},
description:
"Complete setup and configuration guide for Autopilot Monitor. Learn how to deploy the bootstrapper via Intune, configure the agent, and start monitoring Windows Autopilot enrollments in real time.",
keywords: [
@@ -29,5 +35,11 @@ export const metadata: Metadata = {
};
export default function DocsLayout({ children }: { children: React.ReactNode }) {
return <>{children}</>;
return (
<div className="min-h-screen bg-gray-50">
<PublicSiteNavbar showSectionLinks={false} />
<PublicPageHeader title="Documentation" />
<DocsSidebar>{children}</DocsSidebar>
</div>
);
}
@@ -1,5 +1,3 @@
"use client";
import Link from "next/link";
import { PublicPageHeader } from "../../components/PublicPageHeader";
import { PublicSiteNavbar } from "../../components/PublicSiteNavbar";
@@ -1,5 +1,3 @@
"use client";
import Link from "next/link";
import { PublicPageHeader } from "../../components/PublicPageHeader";
import { PublicSiteNavbar } from "../../components/PublicSiteNavbar";
@@ -1,5 +1,3 @@
"use client";
import Link from "next/link";
import { PublicPageHeader } from "../../components/PublicPageHeader";
import { PublicSiteNavbar } from "../../components/PublicSiteNavbar";
@@ -6,6 +6,8 @@ const nextConfig: NextConfig = {
return [
// Permanent redirect for old /landing URL — all SEO equity flows to /
{ source: "/landing", destination: "/", permanent: true },
// Docs index redirects to default section
{ source: "/docs", destination: "/docs/overview", permanent: false },
];
},
};
File diff suppressed because one or more lines are too long