electron-updater in the shell (packaged builds only; dev never updates). Checks at startup + every 24h, downloads silently, and the renderer shows a Restart banner once the update is staged (it installs on quit either way). Manual "Check for Updates..." under the app menu answers via dialog. Every updater event routes through the shell log and is caught - the updater can never take the app down (verified live: a feed failure logs three lines and the app runs on). LH_UPDATE_FEED overrides the baked GitHub feed with a generic local server - the pre-release drill: serve latest-mac.yml + zip + blockmap from localhost and a real installed copy updates itself, no release, no public repo. The asar allow-list re-includes electron-updater + its 16-package runtime tree explicitly (gitignore last-match-wins; asar verified at 2.1 MB). The banner rides the preload bridge (onUpdateStatus/installUpdate) and renders nothing in the browser. window.lh typing centralized in sidebar.tsx's declaration.
42 lines
1.6 KiB
TypeScript
42 lines
1.6 KiB
TypeScript
import type { Metadata } from "next";
|
|
import { JetBrains_Mono, Source_Sans_3 } from "next/font/google";
|
|
import "katex/dist/katex.min.css";
|
|
import "./globals.css";
|
|
import { AppShell, SidebarProvider } from "@/components/sidebar";
|
|
import { ActivityProvider } from "@/components/activity-dock";
|
|
import { ServerEventsProvider } from "@/components/server-events";
|
|
import { AppearanceProvider } from "@/components/settings/appearance";
|
|
import UpdateBanner from "@/components/update-banner";
|
|
|
|
// Chrome = JetBrains Mono, teaching prose = Source Sans 3, titles = CMU
|
|
// Serif (the bundled lh-cmu @font-face in globals.css — no CDN).
|
|
const ui = JetBrains_Mono({ subsets: ["latin"], variable: "--font-jetbrains" });
|
|
const prose = Source_Sans_3({ subsets: ["latin"], variable: "--font-sans3" });
|
|
|
|
export const metadata: Metadata = {
|
|
title: "Learning Harness",
|
|
description: "A teacher agent with a memory — sessions, quizzes, and a knowledge graph of what you know.",
|
|
};
|
|
|
|
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
return (
|
|
<html lang="en" className={`dark ${ui.variable} ${prose.variable}`}>
|
|
<body className="min-h-dvh antialiased">
|
|
{/* The notification channel rides OUTSIDE everything: sidebar, dock,
|
|
and pages all subscribe as the polls retire (push S3, 2026-10-02). */}
|
|
<ServerEventsProvider>
|
|
<AppearanceProvider>
|
|
<SidebarProvider>
|
|
<ActivityProvider>
|
|
<AppShell>{children}</AppShell>
|
|
</ActivityProvider>
|
|
</SidebarProvider>
|
|
</AppearanceProvider>
|
|
</ServerEventsProvider>
|
|
{/* Auto-update banner (Wave C): fixed card, Electron-only pushes. */}
|
|
<UpdateBanner />
|
|
</body>
|
|
</html>
|
|
);
|
|
}
|