Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ lib/dist/

# Vite cache
lib/.vite/
.react-router/

# VSCode extension
vscode-ext/dist/
Expand Down
2 changes: 1 addition & 1 deletion lib/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
"storybook": "^10.4.0",
"tailwindcss": "^4.3.0",
"typescript": "^6.0.3",
"vite": "^7.3.3",
"vite": "^8.0.14",
"vitest": "^4.1.6"
}
}
1,220 changes: 727 additions & 493 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion standalone/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
"jsdom": "^29.1.1",
"tailwindcss": "^4.3.0",
"typescript": "^6.0.3",
"vite": "^7.3.3",
"vite": "^8.0.14",
"vitest": "^4.1.6"
}
}
2 changes: 1 addition & 1 deletion vscode-ext/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,6 @@
"ovsx": "^0.10.12",
"tailwindcss": "^4.3.0",
"typescript": "^6.0.3",
"vite": "^7.3.3"
"vite": "^8.0.14"
}
}
40 changes: 0 additions & 40 deletions website/index.html

This file was deleted.

14 changes: 7 additions & 7 deletions website/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@
"license": "FSL-1.1-MIT",
"type": "module",
"scripts": {
"dev": "vite-react-ssg dev",
"dev": "react-router dev",
"predev": "node scripts/generate-changelog.js",
"prebuild": "node scripts/generate-changelog.js",
"build": "vite-react-ssg build",
"preview": "vite preview",
"build": "react-router build",
"postbuild": "node scripts/flatten-react-router-build.js",
"preview": "vite preview --outDir dist --mode test",
"pretest": "node scripts/generate-changelog.js",
"test": "vitest run"
},
Expand All @@ -19,18 +20,17 @@
"dormouse-lib": "workspace:*",
"react": "^19.2.6",
"react-dom": "^19.2.6",
"react-router-dom": "^6.30.3",
"react-router": "^7.15.1",
"tailwind-variants": "^3.2.2"
},
"devDependencies": {
"@react-router/dev": "^7.15.1",
"@tailwindcss/vite": "^4.3.0",
"@types/react": "^19.2.14",
"@types/react-dom": "^19.2.3",
"@vitejs/plugin-react-swc": "^4.3.1",
"tailwindcss": "^4.3.0",
"typescript": "^6.0.3",
"vite": "^7.3.3",
"vite-react-ssg": "0.9.1-beta.1",
"vite": "^8.0.14",
"vitest": "^4.1.6"
}
}
2 changes: 1 addition & 1 deletion website/public/_redirects
Original file line number Diff line number Diff line change
@@ -1 +1 @@
/changelog/after/* /changelog 200
/changelog/after/* /__spa-fallback.html 200
18 changes: 18 additions & 0 deletions website/react-router.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import type { Config } from "@react-router/dev/config";

export default {
appDirectory: "src",
buildDirectory: "dist",
ssr: false,
prerender() {
return [
"/",
"/playground",
"/playground/desktop",
"/playground/pocket",
"/pocket",
"/changelog",
"/supply-chain",
];
},
} satisfies Config;
25 changes: 25 additions & 0 deletions website/scripts/flatten-react-router-build.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { cpSync, existsSync, readdirSync, rmSync } from "node:fs";
import { dirname, join, resolve } from "node:path";
import { fileURLToPath } from "node:url";

const scriptDir = dirname(fileURLToPath(import.meta.url));
const websiteDir = resolve(scriptDir, "..");
const distDir = join(websiteDir, "dist");
const clientDir = join(distDir, "client");
const serverDir = join(distDir, "server");

if (!existsSync(clientDir)) {
throw new Error(`React Router client build not found at ${clientDir}`);
}

for (const entry of readdirSync(clientDir)) {
cpSync(join(clientDir, entry), join(distDir, entry), {
recursive: true,
force: true,
});
}

rmSync(clientDir, { recursive: true, force: true });
rmSync(serverDir, { recursive: true, force: true });

console.log("Flattened React Router client build into dist/");
36 changes: 0 additions & 36 deletions website/src/App.tsx

This file was deleted.

10 changes: 10 additions & 0 deletions website/src/entry.client.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import ReactDOM from "react-dom/client";
import { HydratedRouter } from "react-router/dom";

import "./index.css";

// Intentionally not wrapped in <React.StrictMode>. The desktop playground's
// Wall/dockview setup is not idempotent across StrictMode's dev-only double
// mount: the first onReady consumes initialPaneIds, so the remount's onReady
// loses `tut-main` and PlaygroundDesktop's addPanel referencePanel throws.
ReactDOM.hydrateRoot(document, <HydratedRouter />);
39 changes: 39 additions & 0 deletions website/src/entry.server.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { renderToReadableStream } from "react-dom/server";
import {
ServerRouter,
type EntryContext,
} from "react-router";

export const streamTimeout = 5_000;

export default async function handleRequest(
request: Request,
responseStatusCode: number,
responseHeaders: Headers,
routerContext: EntryContext,
) {
if (request.method.toUpperCase() === "HEAD") {
return new Response(null, {
status: responseStatusCode,
headers: responseHeaders,
});
}

const stream = await renderToReadableStream(
<ServerRouter context={routerContext} url={request.url} />,
{
signal: AbortSignal.timeout(streamTimeout + 1_000),
onError(error) {
responseStatusCode = 500;
console.error(error);
},
},
);
await stream.allReady;

responseHeaders.set("Content-Type", "text/html");
return new Response(stream, {
status: responseStatusCode,
headers: responseHeaders,
});
}
5 changes: 0 additions & 5 deletions website/src/main.tsx

This file was deleted.

23 changes: 23 additions & 0 deletions website/src/pages/Changelog.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { renderToStaticMarkup } from "react-dom/server";
import { createMemoryRouter, RouterProvider } from "react-router";
import { describe, expect, it } from "vitest";

import Changelog from "./Changelog";

describe("Changelog route", () => {
it("renders the after-version filter for /changelog/after/v0.9.0", () => {
const router = createMemoryRouter(
[
{
path: "/changelog/after/:version",
element: <Changelog />,
},
],
{
initialEntries: ["/changelog/after/v0.9.0"],
},
);

expect(renderToStaticMarkup(<RouterProvider router={router} />)).toMatchSnapshot();
});
});
4 changes: 2 additions & 2 deletions website/src/pages/Changelog.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ReactNode } from "react";
import { Link, useParams } from "react-router-dom";
import { Link, useParams } from "react-router";
import SiteHeader, { STATIC_PAGE_HEADER_STYLE } from "../components/SiteHeader";
import changelog from "../data/changelog.json";

Expand Down Expand Up @@ -158,7 +158,7 @@ function FilterNotice({ children }: { children: ReactNode }) {
);
}

export function Component() {
export default function Changelog() {
const { version: versionParam } = useParams();
const requestedVersion = versionParam ? normalizeVersionParam(versionParam) : null;
const baselineIndex = requestedVersion
Expand Down
1 change: 1 addition & 0 deletions website/src/pages/ChangelogAfter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from "./Changelog";
4 changes: 1 addition & 3 deletions website/src/pages/Home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ import standaloneLatest from "@standalone-latest";
import { prefersReducedMotion } from "dormouse-lib/lib/ui-geometry";
import { NotifySignupForm } from "../components/NotifySignupForm";

export { Home as Component };

/** Multiplier on scroll required to drive the hero animation.
* 1 = baseline, 2 = half as sensitive, 0.5 = twice as sensitive. */
const HERO_SLOMO_FACTOR = 2;
Expand Down Expand Up @@ -273,7 +271,7 @@ function DownloadGroupHeader({
);
}

function Home() {
export default function Home() {
const videoRef = useRef<HTMLVideoElement>(null);
const posterRef = useRef<HTMLImageElement>(null);
const runwayRef = useRef<HTMLDivElement>(null);
Expand Down
6 changes: 2 additions & 4 deletions website/src/pages/Playground.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import { useEffect } from "react";
import { useNavigate } from "react-router-dom";
import { useNavigate } from "react-router";
import {
DESKTOP_PLAYGROUND_PATH,
POCKET_PLAYGROUND_PATH,
usePreferredPlayground,
} from "../lib/playground-routing";

export { PlaygroundRedirect as Component };

function PlaygroundRedirect() {
export default function PlaygroundRedirect() {
const navigate = useNavigate();
const preferred = usePreferredPlayground();

Expand Down
6 changes: 2 additions & 4 deletions website/src/pages/PlaygroundDesktop.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useState, useEffect, useCallback, useRef } from "react";
import { Link } from "react-router-dom";
import { Link } from "react-router";
import SiteHeader, { STATIC_PAGE_HEADER_STYLE } from "../components/SiteHeader";
import { PlaceToPaste } from "../components/PlaceToPaste";
import { POCKET_THEME_ID } from "../components/PocketTerminalExperience";
Expand All @@ -11,8 +11,6 @@ import { BUSY_DEMO_DURATION_MS, BUSY_DEMO_INTERVAL_MS, TutRunner } from "../lib/
import { ChangelogRunner } from "../lib/changelog-runner";
import { POCKET_PLAYGROUND_PATH, usePreferredPlayground } from "../lib/playground-routing";

export { PlaygroundDesktop as Component };

const PANE_MAIN = "tut-main";
const PANE_BOXED = "tut-boxed";
const PANE_SPLASH = "tut-splash";
Expand Down Expand Up @@ -271,7 +269,7 @@ function PlaygroundDesktopExperience() {
);
}

function PlaygroundDesktop() {
export default function PlaygroundDesktop() {
const preferred = usePreferredPlayground();
if (preferred === "pocket") return <DesktopPlaygroundUnavailable />;
return <PlaygroundDesktopExperience />;
Expand Down
6 changes: 2 additions & 4 deletions website/src/pages/Pocket.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import { useEffect } from "react";
import { useNavigate } from "react-router-dom";
import { useNavigate } from "react-router";
import { POCKET_PLAYGROUND_PATH } from "../lib/playground-routing";

export { Pocket as Component };

function Pocket() {
export default function Pocket() {
const navigate = useNavigate();

useEffect(() => {
Expand Down
4 changes: 1 addition & 3 deletions website/src/pages/PocketPlayground.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ import { ShareUrlButton } from "../components/ShareUrlButton";
import { ThemePicker } from "dormouse-lib/components/ThemePicker";
import { POCKET_PLAYGROUND_PATH, usePreferredPlayground } from "../lib/playground-routing";

export { PocketPlayground as Component };

function MobilePocketPlaygroundPage() {
return (
<main className="fixed inset-0 bg-black">
Expand Down Expand Up @@ -67,7 +65,7 @@ function DesktopPocketPlaygroundPage() {
);
}

function PocketPlayground() {
export default function PocketPlayground() {
const preferred = usePreferredPlayground();

useEffect(() => {
Expand Down
2 changes: 1 addition & 1 deletion website/src/pages/SupplyChain.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ function DependencySection({
);
}

export function Component() {
export default function SupplyChain() {
return (
<>
<SiteHeader activePath="/supply-chain" style={STATIC_PAGE_HEADER_STYLE} />
Expand Down
Loading
Loading