@tokcalc/mcp-server 0.1.3 → 0.2.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +86 -406
- package/dist/http.js +23504 -0
- package/dist/index.js +21290 -0
- package/package.json +36 -92
- package/.zscripts/build.sh +0 -175
- package/.zscripts/database-runtime-build.sh +0 -33
- package/.zscripts/dev.pid +0 -1
- package/.zscripts/dev.sh +0 -154
- package/.zscripts/mini-services-build.sh +0 -78
- package/.zscripts/mini-services-install.sh +0 -65
- package/.zscripts/mini-services-start.sh +0 -123
- package/.zscripts/python-runtime-build.sh +0 -120
- package/.zscripts/start.sh +0 -145
- package/CAPACITY_STUDY.md +0 -283
- package/CODE_OF_CONDUCT.md +0 -55
- package/CONTRIBUTING.md +0 -177
- package/Caddyfile +0 -23
- package/LICENSE +0 -204
- package/bun.lock +0 -1965
- package/components.json +0 -21
- package/db/custom.db +0 -0
- package/download/README.md +0 -1
- package/download/tokcalc-dark-calculator.png +0 -0
- package/download/tokcalc-dark-default.png +0 -0
- package/download/tokcalc-demo.webm +0 -0
- package/download/tokcalc-github-link.png +0 -0
- package/download/tokcalc-hydration-fixed.png +0 -0
- package/download/tokcalc-issue-resolved.png +0 -0
- package/download/tokcalc-light-mode.png +0 -0
- package/download/tokcalc-light-reference.png +0 -0
- package/download/tokcalc-long-context-qwen.png +0 -0
- package/download/tokcalc-long-context.png +0 -0
- package/download/tokcalc-og-image-preview.png +0 -0
- package/download/tokcalc-phase2-3.png +0 -0
- package/download/tokcalc-plain-english.png +0 -0
- package/download/tokcalc-preview.png +0 -0
- package/download/tokcalc-share-bvb.png +0 -0
- package/download/tokcalc-share-feature.png +0 -0
- package/download/tokcalc-tab-build-vs-buy.png +0 -0
- package/download/tokcalc-tab-calculator.png +0 -0
- package/download/tokcalc-tab-reference.png +0 -0
- package/eslint.config.mjs +0 -50
- package/examples/websocket/frontend.tsx +0 -196
- package/examples/websocket/server.ts +0 -138
- package/mini-services/.gitkeep +0 -0
- package/mini-services/mcp-server/README.md +0 -86
- package/mini-services/mcp-server/bun.lock +0 -202
- package/mini-services/mcp-server/index.ts +0 -504
- package/mini-services/mcp-server/package.json +0 -40
- package/next.config.ts +0 -12
- package/postcss.config.mjs +0 -5
- package/prisma/schema.prisma +0 -32
- package/public/google6f58ca6be85fa903.html +0 -1
- package/public/logo.svg +0 -29
- package/public/manifest.json +0 -51
- package/public/og-icon-256.png +0 -0
- package/public/og.png +0 -0
- package/public/robots.txt +0 -25
- package/public/sitemap.xml +0 -23
- package/public/tokcalc-demo.gif +0 -0
- package/scripts/og-template.html +0 -120
- package/scripts/render-og.mjs +0 -43
- package/server.json +0 -21
- package/src/app/api/pricing/aws/route.ts +0 -186
- package/src/app/api/pricing/azure/route.ts +0 -168
- package/src/app/api/pricing/gcp/route.ts +0 -230
- package/src/app/api/pricing/vast-ai/route.ts +0 -164
- package/src/app/api/route.ts +0 -5
- package/src/app/compare/h100-vs-h200/layout.tsx +0 -30
- package/src/app/compare/h100-vs-h200/page.tsx +0 -328
- package/src/app/globals.css +0 -122
- package/src/app/layout.tsx +0 -276
- package/src/app/page.tsx +0 -2670
- package/src/components/azure-live-pricing.tsx +0 -185
- package/src/components/benchmark-import.tsx +0 -340
- package/src/components/confidence-badge.tsx +0 -116
- package/src/components/live-pricing-comparison.tsx +0 -241
- package/src/components/theme-provider.tsx +0 -11
- package/src/components/theme-toggle.tsx +0 -55
- package/src/components/ui/accordion.tsx +0 -66
- package/src/components/ui/alert-dialog.tsx +0 -157
- package/src/components/ui/alert.tsx +0 -66
- package/src/components/ui/aspect-ratio.tsx +0 -11
- package/src/components/ui/avatar.tsx +0 -53
- package/src/components/ui/badge.tsx +0 -46
- package/src/components/ui/breadcrumb.tsx +0 -109
- package/src/components/ui/button.tsx +0 -59
- package/src/components/ui/calendar.tsx +0 -213
- package/src/components/ui/card.tsx +0 -92
- package/src/components/ui/carousel.tsx +0 -241
- package/src/components/ui/chart.tsx +0 -353
- package/src/components/ui/checkbox.tsx +0 -32
- package/src/components/ui/collapsible.tsx +0 -33
- package/src/components/ui/command.tsx +0 -184
- package/src/components/ui/context-menu.tsx +0 -252
- package/src/components/ui/dialog.tsx +0 -143
- package/src/components/ui/drawer.tsx +0 -135
- package/src/components/ui/dropdown-menu.tsx +0 -257
- package/src/components/ui/form.tsx +0 -167
- package/src/components/ui/hover-card.tsx +0 -44
- package/src/components/ui/input-otp.tsx +0 -77
- package/src/components/ui/input.tsx +0 -21
- package/src/components/ui/label.tsx +0 -24
- package/src/components/ui/menubar.tsx +0 -276
- package/src/components/ui/navigation-menu.tsx +0 -168
- package/src/components/ui/pagination.tsx +0 -127
- package/src/components/ui/popover.tsx +0 -48
- package/src/components/ui/progress.tsx +0 -31
- package/src/components/ui/radio-group.tsx +0 -45
- package/src/components/ui/resizable.tsx +0 -56
- package/src/components/ui/scroll-area.tsx +0 -58
- package/src/components/ui/select.tsx +0 -185
- package/src/components/ui/separator.tsx +0 -28
- package/src/components/ui/sheet.tsx +0 -139
- package/src/components/ui/sidebar.tsx +0 -726
- package/src/components/ui/skeleton.tsx +0 -13
- package/src/components/ui/slider.tsx +0 -63
- package/src/components/ui/sonner.tsx +0 -25
- package/src/components/ui/switch.tsx +0 -31
- package/src/components/ui/table.tsx +0 -116
- package/src/components/ui/tabs.tsx +0 -66
- package/src/components/ui/textarea.tsx +0 -18
- package/src/components/ui/toast.tsx +0 -129
- package/src/components/ui/toaster.tsx +0 -35
- package/src/components/ui/toggle-group.tsx +0 -73
- package/src/components/ui/toggle.tsx +0 -47
- package/src/components/ui/tooltip.tsx +0 -61
- package/src/components/vast-ai-live-pricing.tsx +0 -176
- package/src/hooks/use-mobile.ts +0 -19
- package/src/hooks/use-toast.ts +0 -194
- package/src/lib/benchmark-parser-sglang.ts +0 -150
- package/src/lib/benchmark-parser-tokcalc.ts +0 -247
- package/src/lib/benchmark-parser-trtllm.ts +0 -152
- package/src/lib/benchmark-parser-vllm.ts +0 -198
- package/src/lib/benchmark-schema.ts +0 -263
- package/src/lib/db.ts +0 -13
- package/src/lib/engine-presets.ts +0 -183
- package/src/lib/price-schema.ts +0 -141
- package/src/lib/token-calc.ts +0 -808
- package/src/lib/track.ts +0 -31
- package/src/lib/url-state.ts +0 -256
- package/src/lib/utils.ts +0 -6
- package/tailwind.config.ts +0 -64
- package/tests/database-runtime-build.sh +0 -75
- package/tests/python-runtime-build.sh +0 -64
- package/tests/python-runtime-container.sh +0 -31
- package/tool-results/bash_1789888171144_2c5381860539.txt +0 -161
- package/tool-results/bash_1789888175925_49c53ba3c61b.txt +0 -191
- package/tool-results/bash_1789888181202_49c53ba3c61b.txt +0 -191
- package/tool-results/bash_1789888195219_4a86a5c91411.txt +0 -200
- package/tool-results/bash_1789888203128_6cca13c71b47.txt +0 -199
- package/tool-results/bash_1789929256963_2a52aff0d0a8.txt +0 -160
- package/tool-results/read_1789888151021_69f58eec6a5b.txt +0 -653
- package/tool-results/read_1789888153837_1d3a8bfc2a94.txt +0 -653
- package/tool-results/read_1789888163087_ccc406d47505.txt +0 -122
- package/tool-results/read_1789888167347_67d1d7c9830a.txt +0 -122
- package/tool-results/read_1789929252529_d90e8f383a25.txt +0 -285
- package/tsconfig.json +0 -42
- package/upload/Pasted Content_1789887800864.txt +0 -652
- package/upload/Pasted Content_1789887909561.txt +0 -652
- package/upload/Pasted Content_1789887918428.txt +0 -652
- package/upload/Pasted Content_1789887959420.txt +0 -652
- package/upload/Pasted Content_1789888020485.txt +0 -652
- package/upload/Pasted Content_1789888058079.txt +0 -652
- package/upload/Pasted Content_1789888885033.txt +0 -686
- package/upload/Pasted Content_1789928912741.txt +0 -285
- package/upload/Pasted Content_1789928938402.txt +0 -285
- package/upload/Pasted Content_1789929160389.txt +0 -285
- package/upload/Pasted Content_1789929176660.txt +0 -285
- package/upload/issue_vision.json +0 -28
- package/upload/pasted_image_1789883175209.png +0 -0
- package/upload/pasted_image_1789899056690.png +0 -0
- package/upload/pasted_image_1789900371483.png +0 -0
- package/upload/pasted_image_1789900472823.png +0 -0
- package/upload/pasted_image_1789900490374.png +0 -0
- package/upload/pasted_image_1789900585552.png +0 -0
- package/upload/pasted_image_1789900606519.png +0 -0
- package/upload/pasted_image_1789901598705.png +0 -0
- package/upload/pasted_image_1789901613545.png +0 -0
- package/upload/pasted_image_1789978382674.png +0 -0
- package/upload/pasted_image_1789978392749.png +0 -0
- package/upload/pasted_image_1789978474879.png +0 -0
- package/upload/pasted_image_1789978523652.png +0 -0
- package/upload/pasted_image_1789984219089.png +0 -0
- package/upload/pasted_image_1789984491896.png +0 -0
- package/upload/pasted_image_1789985017950.png +0 -0
- package/upload/pasted_image_1789985036765.png +0 -0
- package/upload/pasted_image_1789985049848.png +0 -0
- package/upload/pasted_image_1790002427833.png +0 -0
- package/upload/pasted_image_1790002659944.png +0 -0
- package/upload/pasted_image_1790037038476.png +0 -0
- package/upload/screenshot_analysis.json +0 -28
- package/upload/vision_output.json +0 -28
package/src/app/layout.tsx
DELETED
|
@@ -1,276 +0,0 @@
|
|
|
1
|
-
import type { Metadata, Viewport } from "next";
|
|
2
|
-
import Script from "next/script";
|
|
3
|
-
import { Geist, Geist_Mono } from "next/font/google";
|
|
4
|
-
import "./globals.css";
|
|
5
|
-
import { Toaster } from "@/components/ui/toaster";
|
|
6
|
-
import { ThemeProvider } from "@/components/theme-provider";
|
|
7
|
-
|
|
8
|
-
const geistSans = Geist({
|
|
9
|
-
variable: "--font-geist-sans",
|
|
10
|
-
subsets: ["latin"],
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
const geistMono = Geist_Mono({
|
|
14
|
-
variable: "--font-geist-mono",
|
|
15
|
-
subsets: ["latin"],
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Resolve the canonical site URL for OG / Twitter metadata.
|
|
20
|
-
*
|
|
21
|
-
* Priority:
|
|
22
|
-
* 1. NEXT_PUBLIC_SITE_URL — explicit override (set on Vercel for custom domain)
|
|
23
|
-
* 2. NEXT_PUBLIC_VERCEL_URL — auto-injected by Vercel for preview deployments
|
|
24
|
-
* 3. Hardcoded fallback — works out-of-the-box on tokcalc.vercel.app
|
|
25
|
-
*/
|
|
26
|
-
function getSiteUrl(): string {
|
|
27
|
-
if (process.env.NEXT_PUBLIC_SITE_URL) {
|
|
28
|
-
return process.env.NEXT_PUBLIC_SITE_URL;
|
|
29
|
-
}
|
|
30
|
-
if (process.env.NEXT_PUBLIC_VERCEL_URL) {
|
|
31
|
-
return `https://${process.env.NEXT_PUBLIC_VERCEL_URL}`;
|
|
32
|
-
}
|
|
33
|
-
return "https://tokcalc.vercel.app";
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const SITE_URL = getSiteUrl();
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* Plausible Analytics — privacy-friendly, no cookies, GDPR-compliant.
|
|
40
|
-
* Script ID is tied to this specific Plausible account.
|
|
41
|
-
* Init script enables custom event tracking via window.plausible().
|
|
42
|
-
*/
|
|
43
|
-
const PLAUSIBLE_SCRIPT_SRC = "https://plausible.io/js/pa-HD58q2wnqtv43X23yV9-U.js";
|
|
44
|
-
const PLAUSIBLE_INIT = `
|
|
45
|
-
window.plausible=window.plausible||function(){(plausible.q=plausible.q||[]).push(arguments)},plausible.init=plausible.init||function(i){plausible.o=i||{}};
|
|
46
|
-
plausible.init()
|
|
47
|
-
`;
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Sentry — error monitoring + performance tracing.
|
|
51
|
-
* DSN is public (client-side SDK), safe to commit.
|
|
52
|
-
*
|
|
53
|
-
* Uses the "loader" pattern: a single inline script that dynamically creates
|
|
54
|
-
* a <script> element for the Sentry CDN, then calls Sentry.init() in the
|
|
55
|
-
* onload callback. This guarantees correct execution order (CDN loads
|
|
56
|
-
* before init runs) without blocking page render.
|
|
57
|
-
*/
|
|
58
|
-
const SENTRY_DSN = "https://2991cb014b0e9ad6d24d0192cf4bfb36@o4512137181003776.ingest.us.sentry.io/4512137191882752";
|
|
59
|
-
const SENTRY_CDN = "https://browser.sentry-cdn.com/8.49.0/bundle.min.js";
|
|
60
|
-
const SENTRY_LOADER = `
|
|
61
|
-
(function(){
|
|
62
|
-
var s = document.createElement('script');
|
|
63
|
-
s.src = '${SENTRY_CDN}';
|
|
64
|
-
s.crossOrigin = 'anonymous';
|
|
65
|
-
s.onload = function() {
|
|
66
|
-
if (typeof Sentry !== 'undefined') {
|
|
67
|
-
Sentry.init({
|
|
68
|
-
dsn: '${SENTRY_DSN}',
|
|
69
|
-
tracesSampleRate: 0.1,
|
|
70
|
-
environment: '${process.env.NODE_ENV || "development"}',
|
|
71
|
-
release: 'tokcalc@0.3.0',
|
|
72
|
-
beforeSend: function(event) {
|
|
73
|
-
if (event.environment === 'development') return null;
|
|
74
|
-
return event;
|
|
75
|
-
}
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
};
|
|
79
|
-
document.head.appendChild(s);
|
|
80
|
-
})();
|
|
81
|
-
`;
|
|
82
|
-
|
|
83
|
-
export const metadata: Metadata = {
|
|
84
|
-
metadataBase: new URL(SITE_URL),
|
|
85
|
-
title: {
|
|
86
|
-
default: "tokcalc — LLM serving capacity planner",
|
|
87
|
-
template: "%s · tokcalc",
|
|
88
|
-
},
|
|
89
|
-
description:
|
|
90
|
-
"Plan your LLM deployment before you rent the GPUs. Estimate model fit, KV-cache, prefill/decode throughput, continuous batching, latency, multi-GPU scaling, cloud cost, API cost, and self-hosting break-even — with transparent formulas and cited benchmarks.",
|
|
91
|
-
keywords: [
|
|
92
|
-
"LLM",
|
|
93
|
-
"tokens per second",
|
|
94
|
-
"inference",
|
|
95
|
-
"throughput",
|
|
96
|
-
"GPU",
|
|
97
|
-
"A100",
|
|
98
|
-
"H100",
|
|
99
|
-
"H200",
|
|
100
|
-
"MI300X",
|
|
101
|
-
"capacity planner",
|
|
102
|
-
"vLLM",
|
|
103
|
-
"quantization",
|
|
104
|
-
"GGUF",
|
|
105
|
-
"FP8",
|
|
106
|
-
"build vs buy",
|
|
107
|
-
"self-host vs API",
|
|
108
|
-
"KV cache",
|
|
109
|
-
"TTFT",
|
|
110
|
-
],
|
|
111
|
-
authors: [{ name: "tokcalc", url: SITE_URL }],
|
|
112
|
-
creator: "tokcalc",
|
|
113
|
-
applicationName: "tokcalc",
|
|
114
|
-
publisher: "tokcalc",
|
|
115
|
-
icons: {
|
|
116
|
-
icon: [
|
|
117
|
-
{ url: "/og-icon-256.png", sizes: "256x256", type: "image/png" },
|
|
118
|
-
{ url: "/og-icon-256.png", sizes: "192x192", type: "image/png" },
|
|
119
|
-
{ url: "/og-icon-256.png", sizes: "512x512", type: "image/png" },
|
|
120
|
-
],
|
|
121
|
-
apple: [{ url: "/og-icon-256.png", sizes: "180x180", type: "image/png" }],
|
|
122
|
-
shortcut: ["/og-icon-256.png"],
|
|
123
|
-
},
|
|
124
|
-
manifest: "/manifest.json",
|
|
125
|
-
openGraph: {
|
|
126
|
-
title: "tokcalc — LLM serving capacity planner",
|
|
127
|
-
description:
|
|
128
|
-
"Plan your LLM deployment before you rent the GPUs. Estimate throughput, latency, KV-cache, batching, multi-GPU scaling, and cost — with transparent formulas.",
|
|
129
|
-
url: SITE_URL,
|
|
130
|
-
siteName: "tokcalc",
|
|
131
|
-
type: "website",
|
|
132
|
-
locale: "en_US",
|
|
133
|
-
images: [
|
|
134
|
-
{
|
|
135
|
-
url: "/og.png",
|
|
136
|
-
secure_url: "/og.png",
|
|
137
|
-
width: 2400,
|
|
138
|
-
height: 1260,
|
|
139
|
-
alt: "tokcalc — Plan your LLM deployment before you rent the GPUs. Sample: Llama 3 70B · 2×H200 · FP8 · 128K context · 47 tok/s · 1.4s TTFT · $0.34/M tokens.",
|
|
140
|
-
},
|
|
141
|
-
],
|
|
142
|
-
},
|
|
143
|
-
twitter: {
|
|
144
|
-
card: "summary_large_image",
|
|
145
|
-
title: "tokcalc — LLM serving capacity planner",
|
|
146
|
-
description:
|
|
147
|
-
"Plan your LLM deployment before you rent the GPUs. Transparent formulas, cited benchmarks, no black-box throughput assumptions.",
|
|
148
|
-
images: [
|
|
149
|
-
{
|
|
150
|
-
url: "/og.png",
|
|
151
|
-
width: 2400,
|
|
152
|
-
height: 1260,
|
|
153
|
-
alt: "tokcalc — Plan your LLM deployment before you rent the GPUs. Sample: Llama 3 70B · 2×H200 · FP8 · 128K context · 47 tok/s · 1.4s TTFT · $0.34/M tokens.",
|
|
154
|
-
},
|
|
155
|
-
],
|
|
156
|
-
},
|
|
157
|
-
robots: {
|
|
158
|
-
index: true,
|
|
159
|
-
follow: true,
|
|
160
|
-
googleBot: {
|
|
161
|
-
index: true,
|
|
162
|
-
follow: true,
|
|
163
|
-
"max-image-preview": "large",
|
|
164
|
-
"max-snippet": -1,
|
|
165
|
-
"max-video-preview": -1,
|
|
166
|
-
},
|
|
167
|
-
},
|
|
168
|
-
alternates: {
|
|
169
|
-
canonical: SITE_URL,
|
|
170
|
-
},
|
|
171
|
-
category: "technology",
|
|
172
|
-
};
|
|
173
|
-
|
|
174
|
-
export const viewport: Viewport = {
|
|
175
|
-
themeColor: [
|
|
176
|
-
{ media: "(prefers-color-scheme: dark)", color: "#0a0e0a" },
|
|
177
|
-
{ media: "(prefers-color-scheme: light)", color: "#ffffff" },
|
|
178
|
-
],
|
|
179
|
-
colorScheme: "dark light",
|
|
180
|
-
width: "device-width",
|
|
181
|
-
initialScale: 1,
|
|
182
|
-
maximumScale: 5,
|
|
183
|
-
};
|
|
184
|
-
|
|
185
|
-
/**
|
|
186
|
-
* JSON-LD structured data for Google rich results.
|
|
187
|
-
* Type: SoftwareApplication — appropriate for a devtool web app.
|
|
188
|
-
*/
|
|
189
|
-
const jsonLd = {
|
|
190
|
-
"@context": "https://schema.org",
|
|
191
|
-
"@type": "SoftwareApplication",
|
|
192
|
-
name: "tokcalc",
|
|
193
|
-
applicationCategory: "DeveloperApplication",
|
|
194
|
-
operatingSystem: "Web",
|
|
195
|
-
description:
|
|
196
|
-
"Open-source LLM serving capacity planner. Estimate model fit, KV-cache, throughput, latency, multi-GPU scaling, and cost — with transparent formulas.",
|
|
197
|
-
url: SITE_URL,
|
|
198
|
-
offers: {
|
|
199
|
-
"@type": "Offer",
|
|
200
|
-
price: "0",
|
|
201
|
-
priceCurrency: "USD",
|
|
202
|
-
},
|
|
203
|
-
license: "https://www.apache.org/licenses/LICENSE-2.0",
|
|
204
|
-
isAccessibleForFree: true,
|
|
205
|
-
author: {
|
|
206
|
-
"@type": "Organization",
|
|
207
|
-
name: "tokcalc",
|
|
208
|
-
url: SITE_URL,
|
|
209
|
-
},
|
|
210
|
-
featureList: [
|
|
211
|
-
"Model fit / VRAM calculation",
|
|
212
|
-
"KV-cache by context and concurrency",
|
|
213
|
-
"Prefill vs decode separation (TTFT / ITL)",
|
|
214
|
-
"Continuous batching / paged attention",
|
|
215
|
-
"Multi-GPU topology recommendation",
|
|
216
|
-
"Prompt caching economics (Anthropic / OpenAI)",
|
|
217
|
-
"Reasoning tokens (o1 / R1 / Claude thinking)",
|
|
218
|
-
"Build-vs-buy break-even calculator",
|
|
219
|
-
"Long-context capacity planner (4K → 1M)",
|
|
220
|
-
"Transparent formulas with cited benchmarks",
|
|
221
|
-
],
|
|
222
|
-
softwareVersion: "0.3.0",
|
|
223
|
-
datePublished: "2026-09-20",
|
|
224
|
-
discussionUrl: "https://github.com/stevecrates489-commits/tokcalc",
|
|
225
|
-
};
|
|
226
|
-
|
|
227
|
-
export default function RootLayout({
|
|
228
|
-
children,
|
|
229
|
-
}: Readonly<{
|
|
230
|
-
children: React.ReactNode;
|
|
231
|
-
}>) {
|
|
232
|
-
return (
|
|
233
|
-
<html lang="en" suppressHydrationWarning>
|
|
234
|
-
<head>
|
|
235
|
-
{/* JSON-LD structured data for Google rich results */}
|
|
236
|
-
<script
|
|
237
|
-
type="application/ld+json"
|
|
238
|
-
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
|
|
239
|
-
/>
|
|
240
|
-
</head>
|
|
241
|
-
<body
|
|
242
|
-
className={`${geistSans.variable} ${geistMono.variable} antialiased bg-background text-foreground`}
|
|
243
|
-
>
|
|
244
|
-
{/* Plausible Analytics — privacy-friendly, no cookies */}
|
|
245
|
-
{/* Custom events: window.plausible('event_name', { props: {...} }) */}
|
|
246
|
-
<Script
|
|
247
|
-
src={PLAUSIBLE_SCRIPT_SRC}
|
|
248
|
-
strategy="afterInteractive"
|
|
249
|
-
async
|
|
250
|
-
/>
|
|
251
|
-
<Script
|
|
252
|
-
id="plausible-init"
|
|
253
|
-
strategy="afterInteractive"
|
|
254
|
-
dangerouslySetInnerHTML={{ __html: PLAUSIBLE_INIT }}
|
|
255
|
-
/>
|
|
256
|
-
|
|
257
|
-
{/* Sentry — error monitoring via loader pattern (CDN + init in one script, onload guarantees order) */}
|
|
258
|
-
<Script
|
|
259
|
-
id="sentry-loader"
|
|
260
|
-
strategy="afterInteractive"
|
|
261
|
-
dangerouslySetInnerHTML={{ __html: SENTRY_LOADER }}
|
|
262
|
-
/>
|
|
263
|
-
|
|
264
|
-
<ThemeProvider
|
|
265
|
-
attribute="class"
|
|
266
|
-
defaultTheme="dark"
|
|
267
|
-
enableSystem={false}
|
|
268
|
-
disableTransitionOnChange
|
|
269
|
-
>
|
|
270
|
-
{children}
|
|
271
|
-
<Toaster />
|
|
272
|
-
</ThemeProvider>
|
|
273
|
-
</body>
|
|
274
|
-
</html>
|
|
275
|
-
);
|
|
276
|
-
}
|