mirror of
https://github.com/okieselbach/AutopilotMonitor.git
synced 2026-10-25 13:10:13 +00:00
SEO route swap: / is now the landing page, dashboard moved to /dashboard
- app/landing/page.tsx → app/page.tsx (landing page at root)
- app/page.tsx → app/dashboard/page.tsx (dashboard at /dashboard)
- app/landing/ directory deleted
- next.config.ts: 301 redirect /landing → /
- app/layout.tsx: canonical, OG, JSON-LD metadata updated to /
- All internal router.push('/') → /dashboard in subpages
- All router.push('/landing') → / in ProtectedRoute and preview
- All href='/landing' → / in PublicSiteNavbar, roadmap, privacy, terms
- robots.ts: allow / instead of /landing, disallow /dashboard
- sitemap.ts: root URL updated to /
- Navbar.tsx: suppress on pathname === '/' instead of '/landing'
- msalConfig.ts + .env.local: post-logout redirect updated to /
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -92,7 +92,7 @@ export default function AdminConfigurationPage() {
|
||||
|
||||
// Redirect if not in galactic admin mode
|
||||
if (!galacticMode) {
|
||||
router.push("/");
|
||||
router.push("/dashboard");
|
||||
}
|
||||
}, [router]);
|
||||
|
||||
@@ -640,7 +640,7 @@ export default function AdminConfigurationPage() {
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<button
|
||||
onClick={() => router.push("/")}
|
||||
onClick={() => router.push("/dashboard")}
|
||||
className="text-sm text-gray-600 hover:text-gray-900 mb-2 flex items-center"
|
||||
>
|
||||
← Back to Dashboard
|
||||
|
||||
@@ -670,7 +670,7 @@ export default function AnalyzeRulesPage() {
|
||||
<div className="max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8">
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<button onClick={() => router.push("/")} className="text-sm text-gray-600 hover:text-gray-900 mb-2 flex items-center">
|
||||
<button onClick={() => router.push("/dashboard")} className="text-sm text-gray-600 hover:text-gray-900 mb-2 flex items-center">
|
||||
← Back to Dashboard
|
||||
</button>
|
||||
<div>
|
||||
|
||||
@@ -151,7 +151,7 @@ export default function AuditPage() {
|
||||
Retry
|
||||
</button>
|
||||
<button
|
||||
onClick={() => router.push('/')}
|
||||
onClick={() => router.push('/dashboard')}
|
||||
className="w-full px-4 py-2 bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300 rounded-lg hover:bg-gray-300 dark:hover:bg-gray-600 transition-colors"
|
||||
>
|
||||
Back to Home
|
||||
@@ -171,7 +171,7 @@ export default function AuditPage() {
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<button
|
||||
onClick={() => router.push('/')}
|
||||
onClick={() => router.push('/dashboard')}
|
||||
className="text-sm text-gray-600 hover:text-gray-900 mb-2 flex items-center"
|
||||
>
|
||||
← Back to Dashboard
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -354,7 +354,7 @@ export default function FleetHealthPage() {
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<button
|
||||
onClick={() => router.push("/")}
|
||||
onClick={() => router.push("/dashboard")}
|
||||
className="text-sm text-gray-600 hover:text-gray-900 mb-2 flex items-center"
|
||||
>
|
||||
← Back to Dashboard
|
||||
|
||||
@@ -666,7 +666,7 @@ export default function GatherRulesPage() {
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<button
|
||||
onClick={() => router.push("/")}
|
||||
onClick={() => router.push("/dashboard")}
|
||||
className="text-sm text-gray-600 hover:text-gray-900 mb-2 flex items-center"
|
||||
>
|
||||
← Back to Dashboard
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
import type { Metadata } from "next";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: {
|
||||
absolute: "Autopilot Monitor – Real-Time Windows Autopilot Monitoring",
|
||||
},
|
||||
description:
|
||||
"Real-time monitoring and troubleshooting for Windows Autopilot deployments. Track every enrollment phase, detect issues automatically with Analyze Rules, and resolve failures faster.",
|
||||
keywords: [
|
||||
"Windows Autopilot monitoring",
|
||||
"Autopilot deployment visibility",
|
||||
"Intune Autopilot analytics",
|
||||
"Windows enrollment tracking",
|
||||
"Autopilot troubleshooting",
|
||||
"Autopilot real-time monitoring",
|
||||
"Autopilot Monitor",
|
||||
"Windows Autopilot dashboard",
|
||||
"Autopilot failure detection",
|
||||
"enrollment phase tracking",
|
||||
],
|
||||
openGraph: {
|
||||
title: "Autopilot Monitor – Real-Time Windows Autopilot Monitoring",
|
||||
description:
|
||||
"Real-time monitoring and troubleshooting for Windows Autopilot deployments. Track every enrollment phase, detect issues automatically, and resolve failures faster.",
|
||||
url: "https://autopilotmonitor.com/landing",
|
||||
type: "website",
|
||||
},
|
||||
twitter: {
|
||||
title: "Autopilot Monitor – Real-Time Windows Autopilot Monitoring",
|
||||
description:
|
||||
"Real-time monitoring and troubleshooting for Windows Autopilot deployments. Track every enrollment phase, detect issues automatically, and resolve failures faster.",
|
||||
},
|
||||
alternates: {
|
||||
canonical: "https://autopilotmonitor.com/landing",
|
||||
},
|
||||
};
|
||||
|
||||
const jsonLd = {
|
||||
"@context": "https://schema.org",
|
||||
"@type": "SoftwareApplication",
|
||||
name: "Autopilot Monitor",
|
||||
description:
|
||||
"Real-time monitoring and troubleshooting platform for Windows Autopilot deployments. Gives IT teams full visibility into enrollment phases, app progress, errors, and timelines.",
|
||||
applicationCategory: "BusinessApplication",
|
||||
operatingSystem: "Web",
|
||||
offers: {
|
||||
"@type": "Offer",
|
||||
price: "0",
|
||||
priceCurrency: "USD",
|
||||
},
|
||||
author: {
|
||||
"@type": "Person",
|
||||
name: "Oliver Kieselbach",
|
||||
url: "https://www.linkedin.com/in/oliver-kieselbach/",
|
||||
},
|
||||
url: "https://autopilotmonitor.com/landing",
|
||||
codeRepository: "https://github.com/okieselbach/Autopilot-Monitor",
|
||||
keywords:
|
||||
"Windows Autopilot, Intune, enrollment monitoring, autopilot troubleshooting, Windows deployment",
|
||||
};
|
||||
|
||||
export default function LandingLayout({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<>
|
||||
<script
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
|
||||
/>
|
||||
{children}
|
||||
</>
|
||||
);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -13,23 +13,26 @@ const inter = Inter({ subsets: ["latin"] });
|
||||
export const metadata: Metadata = {
|
||||
metadataBase: new URL("https://autopilotmonitor.com"),
|
||||
title: {
|
||||
absolute: "Autopilot Monitor – Real-Time Windows Autopilot Monitoring",
|
||||
default: "Autopilot Monitor",
|
||||
template: "%s | Autopilot Monitor",
|
||||
},
|
||||
description:
|
||||
"Real-time monitoring and troubleshooting for Windows Autopilot deployments. Track enrollment phases, detect issues automatically, and resolve failures faster.",
|
||||
"Real-time monitoring and troubleshooting for Windows Autopilot deployments. Track every enrollment phase, detect issues automatically with Analyze Rules, and resolve failures faster.",
|
||||
keywords: [
|
||||
"Windows Autopilot",
|
||||
"Autopilot monitoring",
|
||||
"Windows enrollment monitoring",
|
||||
"Intune Autopilot",
|
||||
"Windows Autopilot monitoring",
|
||||
"Autopilot deployment visibility",
|
||||
"Intune Autopilot analytics",
|
||||
"Windows enrollment tracking",
|
||||
"Autopilot troubleshooting",
|
||||
"Autopilot deployment",
|
||||
"Autopilot real-time monitoring",
|
||||
"Autopilot Monitor",
|
||||
"Windows Autopilot dashboard",
|
||||
"Autopilot failure detection",
|
||||
"enrollment phase tracking",
|
||||
"Windows device enrollment",
|
||||
"Autopilot analytics",
|
||||
"OOBE monitoring",
|
||||
"Autopilot ESP",
|
||||
"Windows Autopilot deployment",
|
||||
"Intune enrollment monitoring",
|
||||
],
|
||||
authors: [{ name: "Oliver Kieselbach", url: "https://www.linkedin.com/in/oliver-kieselbach/" }],
|
||||
@@ -41,13 +44,16 @@ export const metadata: Metadata = {
|
||||
siteName: "Autopilot Monitor",
|
||||
title: "Autopilot Monitor – Real-Time Windows Autopilot Monitoring",
|
||||
description:
|
||||
"Real-time monitoring and troubleshooting for Windows Autopilot deployments. Track enrollment phases, detect issues automatically, and resolve failures faster.",
|
||||
"Real-time monitoring and troubleshooting for Windows Autopilot deployments. Track every enrollment phase, detect issues automatically, and resolve failures faster.",
|
||||
},
|
||||
twitter: {
|
||||
card: "summary_large_image",
|
||||
title: "Autopilot Monitor – Real-Time Windows Autopilot Monitoring",
|
||||
description:
|
||||
"Real-time monitoring and troubleshooting for Windows Autopilot deployments. Track enrollment phases, detect issues automatically, and resolve failures faster.",
|
||||
"Real-time monitoring and troubleshooting for Windows Autopilot deployments. Track every enrollment phase, detect issues automatically, and resolve failures faster.",
|
||||
},
|
||||
alternates: {
|
||||
canonical: "https://autopilotmonitor.com",
|
||||
},
|
||||
robots: {
|
||||
index: true,
|
||||
@@ -64,6 +70,30 @@ export const metadata: Metadata = {
|
||||
},
|
||||
};
|
||||
|
||||
const jsonLd = {
|
||||
"@context": "https://schema.org",
|
||||
"@type": "SoftwareApplication",
|
||||
name: "Autopilot Monitor",
|
||||
description:
|
||||
"Real-time monitoring and troubleshooting platform for Windows Autopilot deployments. Gives IT teams full visibility into enrollment phases, app progress, errors, and timelines.",
|
||||
applicationCategory: "BusinessApplication",
|
||||
operatingSystem: "Web",
|
||||
offers: {
|
||||
"@type": "Offer",
|
||||
price: "0",
|
||||
priceCurrency: "USD",
|
||||
},
|
||||
author: {
|
||||
"@type": "Person",
|
||||
name: "Oliver Kieselbach",
|
||||
url: "https://www.linkedin.com/in/oliver-kieselbach/",
|
||||
},
|
||||
url: "https://autopilotmonitor.com",
|
||||
codeRepository: "https://github.com/okieselbach/Autopilot-Monitor",
|
||||
keywords:
|
||||
"Windows Autopilot, Intune, enrollment monitoring, autopilot troubleshooting, Windows deployment",
|
||||
};
|
||||
|
||||
export default function RootLayout({
|
||||
children,
|
||||
}: Readonly<{
|
||||
@@ -72,6 +102,10 @@ export default function RootLayout({
|
||||
return (
|
||||
<html lang="en">
|
||||
<body className={inter.className}>
|
||||
<script
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
|
||||
/>
|
||||
<ThemeProvider>
|
||||
<AuthProvider>
|
||||
<NotificationProvider>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -165,7 +165,7 @@ export default function PlatformUsageMetricsPage() {
|
||||
Retry
|
||||
</button>
|
||||
<button
|
||||
onClick={() => router.push('/')}
|
||||
onClick={() => router.push('/dashboard')}
|
||||
className="w-full px-4 py-2 bg-gray-200 text-gray-700 rounded-lg hover:bg-gray-300 transition-colors"
|
||||
>
|
||||
Back to Home
|
||||
@@ -189,7 +189,7 @@ export default function PlatformUsageMetricsPage() {
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<button
|
||||
onClick={() => router.push('/')}
|
||||
onClick={() => router.push('/dashboard')}
|
||||
className="text-sm text-gray-600 hover:text-gray-900 mb-2 flex items-center"
|
||||
>
|
||||
← Back to Dashboard
|
||||
|
||||
@@ -12,13 +12,13 @@ export default function PreviewPage() {
|
||||
useEffect(() => {
|
||||
if (!isLoading && isAuthenticated && user && !isPreviewBlocked) {
|
||||
if (user.isTenantAdmin || user.isGalacticAdmin) {
|
||||
router.push("/");
|
||||
router.push("/dashboard");
|
||||
} else {
|
||||
router.push("/progress");
|
||||
}
|
||||
}
|
||||
if (!isLoading && !isAuthenticated) {
|
||||
router.push("/landing");
|
||||
router.push("/");
|
||||
}
|
||||
}, [isAuthenticated, isLoading, user, isPreviewBlocked, router]);
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ export default function PrivacyPage() {
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-4 text-sm">
|
||||
<Link href="/landing" className="text-blue-700 hover:text-blue-800 font-medium">Landing page</Link>
|
||||
<Link href="/" className="text-blue-700 hover:text-blue-800 font-medium">Landing page</Link>
|
||||
<Link href="/docs" className="text-blue-700 hover:text-blue-800 font-medium">
|
||||
Documentation
|
||||
</Link>
|
||||
|
||||
@@ -27,7 +27,7 @@ export default function RoadmapPage() {
|
||||
|
||||
<div className="mt-10">
|
||||
<Link
|
||||
href="/landing"
|
||||
href="/"
|
||||
className="inline-flex items-center text-sm font-medium text-blue-700 hover:text-blue-800"
|
||||
>
|
||||
Landing page
|
||||
|
||||
@@ -5,9 +5,9 @@ export default function robots(): MetadataRoute.Robots {
|
||||
rules: [
|
||||
{
|
||||
userAgent: "*",
|
||||
allow: ["/landing", "/about", "/docs", "/roadmap", "/privacy", "/terms"],
|
||||
allow: ["/", "/about", "/docs", "/roadmap", "/privacy", "/terms"],
|
||||
disallow: [
|
||||
"/",
|
||||
"/dashboard",
|
||||
"/fleet-health",
|
||||
"/health-check",
|
||||
"/usage-metrics",
|
||||
|
||||
@@ -528,7 +528,7 @@ export default function SessionDetailPage() {
|
||||
<div className="max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8 flex items-center justify-between">
|
||||
<div>
|
||||
<button
|
||||
onClick={() => router.push('/')}
|
||||
onClick={() => router.push('/dashboard')}
|
||||
className="text-sm text-gray-600 hover:text-gray-900 mb-2 flex items-center"
|
||||
>
|
||||
← Back to Dashboard
|
||||
|
||||
@@ -560,7 +560,7 @@ export default function SettingsPage() {
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<button
|
||||
onClick={() => router.push("/")}
|
||||
onClick={() => router.push("/dashboard")}
|
||||
className="text-sm text-gray-600 hover:text-gray-900 mb-2 flex items-center"
|
||||
>
|
||||
← Back to Dashboard
|
||||
|
||||
@@ -5,7 +5,7 @@ const BASE_URL = "https://autopilotmonitor.com";
|
||||
export default function sitemap(): MetadataRoute.Sitemap {
|
||||
return [
|
||||
{
|
||||
url: `${BASE_URL}/landing`,
|
||||
url: `${BASE_URL}/`,
|
||||
lastModified: new Date(),
|
||||
changeFrequency: "monthly",
|
||||
priority: 1,
|
||||
|
||||
@@ -48,7 +48,7 @@ export default function TermsPage() {
|
||||
</div>
|
||||
|
||||
<div className="flex items-center gap-4 text-sm">
|
||||
<Link href="/landing" className="text-blue-700 hover:text-blue-800 font-medium">Landing page</Link>
|
||||
<Link href="/" className="text-blue-700 hover:text-blue-800 font-medium">Landing page</Link>
|
||||
<Link href="/docs" className="text-blue-700 hover:text-blue-800 font-medium">
|
||||
Documentation
|
||||
</Link>
|
||||
|
||||
@@ -156,7 +156,7 @@ export default function UsageMetricsPage() {
|
||||
Retry
|
||||
</button>
|
||||
<button
|
||||
onClick={() => router.push('/')}
|
||||
onClick={() => router.push('/dashboard')}
|
||||
className="w-full px-4 py-2 bg-gray-200 text-gray-700 rounded-lg hover:bg-gray-300 transition-colors"
|
||||
>
|
||||
Back to Home
|
||||
@@ -180,7 +180,7 @@ export default function UsageMetricsPage() {
|
||||
<div className="flex items-center justify-between">
|
||||
<div>
|
||||
<button
|
||||
onClick={() => router.push('/')}
|
||||
onClick={() => router.push('/dashboard')}
|
||||
className="text-sm text-gray-600 hover:text-gray-900 mb-2 flex items-center"
|
||||
>
|
||||
← Back to Dashboard
|
||||
|
||||
@@ -72,8 +72,8 @@ export default function Navbar() {
|
||||
return () => document.removeEventListener('mousedown', handleClickOutside);
|
||||
}, []);
|
||||
|
||||
// Don't render navbar on landing page
|
||||
if (pathname === '/landing') {
|
||||
// Don't render navbar on landing page (root route)
|
||||
if (pathname === '/') {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ export function ProtectedRoute({ children, requireGalacticAdmin = false }: Prote
|
||||
useEffect(() => {
|
||||
if (!isLoading && !isAuthenticated) {
|
||||
// Not authenticated -> redirect to landing
|
||||
router.push("/landing");
|
||||
router.push("/");
|
||||
}
|
||||
// Note: We don't automatically redirect for galactic admin check
|
||||
// Instead, we show the "Access Denied" dialog and let user click "Back to Home"
|
||||
@@ -54,7 +54,7 @@ export function ProtectedRoute({ children, requireGalacticAdmin = false }: Prote
|
||||
<h2 className="text-xl font-semibold text-gray-900 mb-2">Access Denied</h2>
|
||||
<p className="text-gray-600 mb-6">You need Galactic Admin permissions to access this page.</p>
|
||||
<button
|
||||
onClick={() => router.push("/")}
|
||||
onClick={() => router.push("/dashboard")}
|
||||
className="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors"
|
||||
>
|
||||
Back to Home
|
||||
|
||||
@@ -21,7 +21,7 @@ export function PublicSiteNavbar({ showSectionLinks }: { showSectionLinks: boole
|
||||
}`}
|
||||
>
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 flex items-center justify-between h-14">
|
||||
<Link href="/landing" className="flex items-center space-x-2.5 shrink-0">
|
||||
<Link href="/" className="flex items-center space-x-2.5 shrink-0">
|
||||
<div className="w-8 h-8 bg-gradient-to-br from-blue-600 to-indigo-600 rounded-lg flex items-center justify-center">
|
||||
<svg className="w-5 h-5 text-white" viewBox="0 0 24 24" fill="none">
|
||||
<rect x="5.0" y="12.2" width="2.8" height="7.8" rx="0.9" fill="currentColor" />
|
||||
|
||||
@@ -15,7 +15,7 @@ export const msalConfig: Configuration = {
|
||||
clientId: process.env.NEXT_PUBLIC_ENTRA_CLIENT_ID || "YOUR_CLIENT_ID_HERE",
|
||||
authority: "https://login.microsoftonline.com/organizations", // Multi-tenant
|
||||
redirectUri: process.env.NEXT_PUBLIC_ENTRA_REDIRECT_URI || "http://localhost:3000",
|
||||
postLogoutRedirectUri: process.env.NEXT_PUBLIC_ENTRA_POST_LOGOUT_REDIRECT_URI || "http://localhost:3000/landing",
|
||||
postLogoutRedirectUri: process.env.NEXT_PUBLIC_ENTRA_POST_LOGOUT_REDIRECT_URI || "http://localhost:3000",
|
||||
navigateToLoginRequestUrl: true,
|
||||
},
|
||||
cache: {
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
import type { NextConfig } from "next";
|
||||
|
||||
const nextConfig: NextConfig = {
|
||||
/* config options here */
|
||||
reactStrictMode: true,
|
||||
async redirects() {
|
||||
return [
|
||||
// Permanent redirect for old /landing URL — all SEO equity flows to /
|
||||
{ source: "/landing", destination: "/", permanent: true },
|
||||
];
|
||||
},
|
||||
};
|
||||
|
||||
export default nextConfig;
|
||||
|
||||
Reference in New Issue
Block a user