diff --git a/src/app/chart/layout.tsx b/src/app/chart/layout.tsx
new file mode 100644
index 0000000..3c5d1da
--- /dev/null
+++ b/src/app/chart/layout.tsx
@@ -0,0 +1,13 @@
+import type { Metadata } from "next";
+
+export const metadata: Metadata = {
+ title: "Bar Chart",
+};
+
+export default function ChartLayout({
+ children,
+}: {
+ children: React.ReactNode;
+}) {
+ return children;
+}
diff --git a/src/app/chart/page.tsx b/src/app/chart/page.tsx
index a796bbd..2245258 100644
--- a/src/app/chart/page.tsx
+++ b/src/app/chart/page.tsx
@@ -242,6 +242,10 @@ export default function ChartPage() {
[setChartType],
);
+ useEffect(() => {
+ document.title = `${chartType === "bar" ? "Bar Chart" : "Line Chart"} | MHD`;
+ }, [chartType]);
+
// Keyboard shortcuts for chart type
useHotkey("b", () => handleChartTypeChange("bar"));
useHotkey("l", () => handleChartTypeChange("line"));
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
index 13f02ef..0c5a377 100644
--- a/src/app/layout.tsx
+++ b/src/app/layout.tsx
@@ -22,8 +22,12 @@ import { Suspense } from "react";
import InvalidURLHandler from "@/components/InvalidURLHandler";
export const metadata: Metadata = {
- title: "MHD",
- description: "MHD",
+ title: {
+ template: "%s | MHD",
+ default: "MHD",
+ },
+ description:
+ "Data visualization dashboard for Massachusetts History Society's annual contest, Massachusetts History Day.",
icons: { icon: "/favicon.png" },
};
diff --git a/src/app/map/layout.tsx b/src/app/map/layout.tsx
new file mode 100644
index 0000000..4c4e8b3
--- /dev/null
+++ b/src/app/map/layout.tsx
@@ -0,0 +1,9 @@
+import type { Metadata } from "next";
+
+export const metadata: Metadata = {
+ title: "Heatmap",
+};
+
+export default function MapLayout({ children }: { children: React.ReactNode }) {
+ return children;
+}
diff --git a/src/app/map/page.tsx b/src/app/map/page.tsx
index a84e1c8..3d40c86 100644
--- a/src/app/map/page.tsx
+++ b/src/app/map/page.tsx
@@ -135,7 +135,7 @@ function HeatMapPage() {
);
const regionView = rawRegionView.toLowerCase();
- const [showSchools, setShowSchools] = useQueryState(
+ const [showSchools] = useQueryState(
"showSchools",
parseAsBoolean.withDefault(true),
);
@@ -440,13 +440,6 @@ function HeatMapPage() {
-
-
{schoolDataError ? (
diff --git a/src/app/page.tsx b/src/app/page.tsx
index ea5a400..f2044da 100644
--- a/src/app/page.tsx
+++ b/src/app/page.tsx
@@ -1,7 +1,12 @@
+import type { Metadata } from "next";
import { Suspense } from "react";
import Dashboard from "@/components/Dashboard";
import { DashboardSkeleton } from "@/components/skeletons/DashboardSkeleton";
+export const metadata: Metadata = {
+ title: "Dashboard | MHD",
+};
+
export default function Home() {
return (
}>
diff --git a/src/app/schools/[name]/layout.tsx b/src/app/schools/[name]/layout.tsx
new file mode 100644
index 0000000..f8bd846
--- /dev/null
+++ b/src/app/schools/[name]/layout.tsx
@@ -0,0 +1,19 @@
+export async function generateMetadata({
+ params,
+}: {
+ params: Promise<{ name: string }>;
+}) {
+ const { name } = await params;
+ const decoded = decodeURIComponent(name)
+ .replace(/-/g, " ")
+ .replace(/\b\w/g, (c) => c.toUpperCase());
+ return { title: decoded };
+}
+
+export default function SchoolProfileLayout({
+ children,
+}: {
+ children: React.ReactNode;
+}) {
+ return children;
+}
diff --git a/src/app/schools/[name]/page.tsx b/src/app/schools/[name]/page.tsx
index dc017a6..cc06ba5 100644
--- a/src/app/schools/[name]/page.tsx
+++ b/src/app/schools/[name]/page.tsx
@@ -383,15 +383,17 @@ export default function SchoolProfilePage() {
{/* Project type distribution — same 3-col grid as stats; spans 2 cells */}
-
-
-
+ {projects.length !== 0 && (
+
-
+ )}
{/* School location map */}
diff --git a/src/app/schools/layout.tsx b/src/app/schools/layout.tsx
new file mode 100644
index 0000000..39b8855
--- /dev/null
+++ b/src/app/schools/layout.tsx
@@ -0,0 +1,16 @@
+import type { Metadata } from "next";
+
+export const metadata: Metadata = {
+ title: {
+ template: "%s | MHD",
+ default: "Schools",
+ },
+};
+
+export default function SchoolsLayout({
+ children,
+}: {
+ children: React.ReactNode;
+}) {
+ return children;
+}
diff --git a/src/app/settings/layout.tsx b/src/app/settings/layout.tsx
new file mode 100644
index 0000000..9caf6b3
--- /dev/null
+++ b/src/app/settings/layout.tsx
@@ -0,0 +1,13 @@
+import type { Metadata } from "next";
+
+export const metadata: Metadata = {
+ title: "Settings",
+};
+
+export default function SettingsLayout({
+ children,
+}: {
+ children: React.ReactNode;
+}) {
+ return children;
+}
diff --git a/src/app/signin/page.tsx b/src/app/signin/page.tsx
index 1823d6b..1e31020 100644
--- a/src/app/signin/page.tsx
+++ b/src/app/signin/page.tsx
@@ -1,6 +1,11 @@
+import type { Metadata } from "next";
import AuthForm from "@/components/AuthForm";
import WarpShader from "@/components/WarpShader";
+export const metadata: Metadata = {
+ title: "Sign In",
+};
+
export default async function SignInPage({
searchParams,
}: {
diff --git a/src/app/upload/page.tsx b/src/app/upload/page.tsx
index f4e59a9..b7eea0f 100644
--- a/src/app/upload/page.tsx
+++ b/src/app/upload/page.tsx
@@ -10,8 +10,13 @@
*
**************************************************************/
+import type { Metadata } from "next";
import SpreadsheetState from "@/components/SpreadsheetState";
+export const metadata: Metadata = {
+ title: "Upload",
+};
+
export default function UploadPage() {
return ;
}