feat: add Vercel Speed Insights

This commit is contained in:
Patrick Erichsen
2026-06-19 11:36:01 -07:00
committed by GitHub
parent 7760696362
commit 2ae30d70d5
4 changed files with 25 additions and 1 deletions
+3
View File
@@ -30,6 +30,7 @@
"@tanstack/react-router": "1.170.16",
"@tanstack/react-start": "1.168.26",
"@vercel/analytics": "2.0.1",
"@vercel/speed-insights": "2.0.0",
"class-variance-authority": "0.7.1",
"clawhub-schema": "workspace:0.0.2",
"clsx": "2.1.1",
@@ -924,6 +925,8 @@
"@vercel/analytics": ["@vercel/analytics@2.0.1", "", { "peerDependencies": { "@remix-run/react": "^2", "@sveltejs/kit": "^1 || ^2", "next": ">= 13", "nuxt": ">= 3", "react": "^18 || ^19 || ^19.0.0-rc", "svelte": ">= 4", "vue": "^3", "vue-router": "^4" }, "optionalPeers": ["@remix-run/react", "@sveltejs/kit", "next", "nuxt", "react", "svelte", "vue", "vue-router"] }, "sha512-MTQG6V9qQrt1tsDeF+2Uoo5aPjqbVPys1xvnIftXSJYG2SrwXRHnqEvVoYID7BTruDz4lCd2Z7rM1BdkUehk2g=="],
"@vercel/speed-insights": ["@vercel/speed-insights@2.0.0", "", { "peerDependencies": { "@sveltejs/kit": "^1 || ^2", "next": ">= 13", "nuxt": ">= 3", "react": "^18 || ^19 || ^19.0.0-rc", "svelte": ">= 4", "vue": "^3", "vue-router": "^4" }, "optionalPeers": ["@sveltejs/kit", "next", "nuxt", "react", "svelte", "vue", "vue-router"] }, "sha512-jwkNcrTeafWxjmWq4AHBaptSqZiJkYU5adLC9QBSqeim0GcqDMgN5Ievh8OG1rJ6W3A4l1oiP7qr9CWxGuzu3w=="],
"@vitejs/plugin-react": ["@vitejs/plugin-react@6.0.2", "", { "dependencies": { "@rolldown/pluginutils": "^1.0.0" }, "peerDependencies": { "@rolldown/plugin-babel": "^0.1.7 || ^0.2.0", "babel-plugin-react-compiler": "^1.0.0", "vite": "^8.0.0" }, "optionalPeers": ["@rolldown/plugin-babel", "babel-plugin-react-compiler"] }, "sha512-DlSMqo4WhThw4vB8Mpn0Woe9J+Jfq1geJ61AKW0QEgLzGMNwtIMdxbDUzLxcun8W7NbJO0e2Jg/Nxm3cCSVzzg=="],
"@vitest/coverage-v8": ["@vitest/coverage-v8@4.1.9", "", { "dependencies": { "@bcoe/v8-coverage": "^1.0.2", "@vitest/utils": "4.1.9", "ast-v8-to-istanbul": "^1.0.0", "istanbul-lib-coverage": "^3.2.2", "istanbul-lib-report": "^3.0.1", "istanbul-reports": "^3.2.0", "magicast": "^0.5.2", "obug": "^2.1.1", "std-env": "^4.0.0-rc.1", "tinyrainbow": "^3.1.0" }, "peerDependencies": { "@vitest/browser": "4.1.9", "vitest": "4.1.9" }, "optionalPeers": ["@vitest/browser"] }, "sha512-G9/lgqibheLVBDRuya45EbsEXTYcWoSG+TLg7i2axuzx0Eq62eXn+aWXyaVdV5vKvFSWd6ywcX8hA7la9Pvu8g=="],
+1
View File
@@ -96,6 +96,7 @@
"@tanstack/react-router": "1.170.16",
"@tanstack/react-start": "1.168.26",
"@vercel/analytics": "2.0.1",
"@vercel/speed-insights": "2.0.0",
"class-variance-authority": "0.7.1",
"clawhub-schema": "workspace:0.0.2",
"clsx": "2.1.1",
+12
View File
@@ -60,6 +60,7 @@ function contrastRatio(foreground: string, background: string) {
}
describe("restored UI design contract", () => {
const rootRoute = () => read("src/routes/__root.tsx");
const header = () => read("src/components/Header.tsx");
const footer = () => read("src/components/Footer.tsx");
const home = () => read("src/routes/index.tsx");
@@ -68,6 +69,17 @@ describe("restored UI design contract", () => {
const styles = () => read("src/styles.css");
const theme = () => read("src/lib/theme.ts");
it("keeps Vercel browser instrumentation mounted outside local dev", () => {
const rootSource = rootRoute();
expect(rootSource).toContain('import { Analytics } from "@vercel/analytics/react";');
expect(rootSource).toContain('import { SpeedInsights } from "@vercel/speed-insights/react";');
expect(rootSource).toContain('!["localhost", "127.0.0.1", "::1"].includes');
expect(rootSource).toContain("{showAnalytics ? (");
expect(rootSource).toContain("<Analytics />");
expect(rootSource).toContain("<SpeedInsights />");
});
it("requires the responsive header rail, search overlay, and theme controls", () => {
const headerSource = header();
const navSource = navItems();
+9 -1
View File
@@ -6,6 +6,7 @@ import {
useLocation,
} from "@tanstack/react-router";
import { Analytics } from "@vercel/analytics/react";
import { SpeedInsights } from "@vercel/speed-insights/react";
import { useEffect } from "react";
import { Toaster } from "sonner";
import { AppProviders } from "../components/AppProviders";
@@ -196,7 +197,14 @@ function RootDocument({ children }: { children: React.ReactNode }) {
},
}}
/>
<ClientOnly>{showAnalytics ? <Analytics /> : null}</ClientOnly>
<ClientOnly>
{showAnalytics ? (
<>
<Analytics />
<SpeedInsights />
</>
) : null}
</ClientOnly>
</AppProviders>
<Scripts />
</body>