@jxrstudios/jxr 1.0.10 → 1.1.11

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.
Files changed (87) hide show
  1. package/bin/jxr.js +6 -0
  2. package/dist/index.js +57 -2
  3. package/dist/jxr-server-manager.d.ts.map +1 -1
  4. package/package.json +1 -1
  5. package/src/jxr-server-manager.ts +65 -2
  6. package/zzz_react_template/App.tsx +43 -156
  7. package/zzz_react_template/components/ErrorBoundary.tsx +62 -0
  8. package/zzz_react_template/components/ManusDialog.tsx +85 -0
  9. package/zzz_react_template/components/Map.tsx +155 -0
  10. package/zzz_react_template/components/jxr/CodeEditor.tsx +313 -0
  11. package/zzz_react_template/components/jxr/FileExplorer.tsx +230 -0
  12. package/zzz_react_template/components/jxr/IDEShell.tsx +159 -0
  13. package/zzz_react_template/components/jxr/LandingPage.tsx +414 -0
  14. package/zzz_react_template/components/jxr/LivePreview.tsx +169 -0
  15. package/zzz_react_template/components/jxr/PerformanceDashboard.tsx +379 -0
  16. package/zzz_react_template/components/jxr/TopBar.tsx +149 -0
  17. package/zzz_react_template/components/ui/accordion.tsx +64 -0
  18. package/zzz_react_template/components/ui/alert-dialog.tsx +155 -0
  19. package/zzz_react_template/components/ui/alert.tsx +66 -0
  20. package/zzz_react_template/components/ui/aspect-ratio.tsx +9 -0
  21. package/zzz_react_template/components/ui/avatar.tsx +51 -0
  22. package/zzz_react_template/components/ui/badge.tsx +46 -0
  23. package/zzz_react_template/components/ui/breadcrumb.tsx +109 -0
  24. package/zzz_react_template/components/ui/button-group.tsx +83 -0
  25. package/zzz_react_template/components/ui/button.tsx +60 -0
  26. package/zzz_react_template/components/ui/calendar.tsx +211 -0
  27. package/zzz_react_template/components/ui/card.tsx +92 -0
  28. package/zzz_react_template/components/ui/carousel.tsx +239 -0
  29. package/zzz_react_template/components/ui/chart.tsx +355 -0
  30. package/zzz_react_template/components/ui/checkbox.tsx +30 -0
  31. package/zzz_react_template/components/ui/collapsible.tsx +31 -0
  32. package/zzz_react_template/components/ui/command.tsx +184 -0
  33. package/zzz_react_template/components/ui/context-menu.tsx +250 -0
  34. package/zzz_react_template/components/ui/dialog.tsx +209 -0
  35. package/zzz_react_template/components/ui/drawer.tsx +133 -0
  36. package/zzz_react_template/components/ui/dropdown-menu.tsx +255 -0
  37. package/zzz_react_template/components/ui/empty.tsx +104 -0
  38. package/zzz_react_template/components/ui/field.tsx +242 -0
  39. package/zzz_react_template/components/ui/form.tsx +168 -0
  40. package/zzz_react_template/components/ui/hover-card.tsx +42 -0
  41. package/zzz_react_template/components/ui/input-group.tsx +168 -0
  42. package/zzz_react_template/components/ui/input-otp.tsx +75 -0
  43. package/zzz_react_template/components/ui/input.tsx +70 -0
  44. package/zzz_react_template/components/ui/item.tsx +193 -0
  45. package/zzz_react_template/components/ui/kbd.tsx +28 -0
  46. package/zzz_react_template/components/ui/label.tsx +22 -0
  47. package/zzz_react_template/components/ui/menubar.tsx +274 -0
  48. package/zzz_react_template/components/ui/navigation-menu.tsx +168 -0
  49. package/zzz_react_template/components/ui/pagination.tsx +127 -0
  50. package/zzz_react_template/components/ui/popover.tsx +46 -0
  51. package/zzz_react_template/components/ui/progress.tsx +29 -0
  52. package/zzz_react_template/components/ui/radio-group.tsx +43 -0
  53. package/zzz_react_template/components/ui/resizable.tsx +54 -0
  54. package/zzz_react_template/components/ui/scroll-area.tsx +56 -0
  55. package/zzz_react_template/components/ui/select.tsx +185 -0
  56. package/zzz_react_template/components/ui/separator.tsx +26 -0
  57. package/zzz_react_template/components/ui/sheet.tsx +139 -0
  58. package/zzz_react_template/components/ui/sidebar.tsx +734 -0
  59. package/zzz_react_template/components/ui/skeleton.tsx +13 -0
  60. package/zzz_react_template/components/ui/slider.tsx +61 -0
  61. package/zzz_react_template/components/ui/sonner.tsx +23 -0
  62. package/zzz_react_template/components/ui/spinner.tsx +16 -0
  63. package/zzz_react_template/components/ui/switch.tsx +29 -0
  64. package/zzz_react_template/components/ui/table.tsx +114 -0
  65. package/zzz_react_template/components/ui/tabs.tsx +64 -0
  66. package/zzz_react_template/components/ui/textarea.tsx +67 -0
  67. package/zzz_react_template/components/ui/toggle-group.tsx +73 -0
  68. package/zzz_react_template/components/ui/toggle.tsx +45 -0
  69. package/zzz_react_template/components/ui/tooltip.tsx +59 -0
  70. package/zzz_react_template/const.ts +17 -0
  71. package/zzz_react_template/contexts/JXRContext.tsx +264 -0
  72. package/zzz_react_template/contexts/ThemeContext.tsx +64 -0
  73. package/zzz_react_template/hooks/useComposition.ts +81 -0
  74. package/zzz_react_template/hooks/useMobile.tsx +21 -0
  75. package/zzz_react_template/hooks/usePersistFn.ts +20 -0
  76. package/zzz_react_template/index.css +518 -11
  77. package/zzz_react_template/lib/jxr-runtime/index.ts +201 -0
  78. package/zzz_react_template/lib/jxr-runtime/module-resolver.ts +520 -0
  79. package/zzz_react_template/lib/jxr-runtime/moq-transport.ts +267 -0
  80. package/zzz_react_template/lib/jxr-runtime/web-crypto.ts +279 -0
  81. package/zzz_react_template/lib/jxr-runtime/worker-pool.ts +321 -0
  82. package/zzz_react_template/lib/utils.ts +6 -0
  83. package/zzz_react_template/main.tsx +4 -9
  84. package/zzz_react_template/pages/Docs.tsx +955 -0
  85. package/zzz_react_template/pages/Home.tsx +1080 -0
  86. package/zzz_react_template/pages/NotFound.tsx +105 -0
  87. package/zzz_react_template/tsconfig.json +24 -0
@@ -0,0 +1,955 @@
1
+ /**
2
+ * JXR.js — Documentation Page
3
+ * LavaFlow OS Design System
4
+ * Powered by JXR Studios × DamascusAI
5
+ */
6
+
7
+ import { useState, useMemo } from 'react';
8
+ import { Link } from 'wouter';
9
+ import {
10
+ Zap, Terminal, Package, GitBranch, Shield, Cpu,
11
+ Activity, ChevronRight, Copy, Check,
12
+ BookOpen, Code2, Layers, Globe, ArrowLeft,
13
+ } from 'lucide-react';
14
+
15
+ // ─── Copy button ──────────────────────────────────────────────────────────────
16
+
17
+ function CopyBtn({ text }: { text: string }) {
18
+ const [copied, setCopied] = useState(false);
19
+ const copy = async () => {
20
+ await navigator.clipboard.writeText(text);
21
+ setCopied(true);
22
+ setTimeout(() => setCopied(false), 2000);
23
+ };
24
+ return (
25
+ <button
26
+ onClick={copy}
27
+ className="absolute top-3 right-3 p-1.5 rounded transition-all"
28
+ style={{ color: '#4b5563', background: 'rgba(255,255,255,0.04)', border: '1px solid rgba(255,255,255,0.06)' }}
29
+ title="Copy"
30
+ >
31
+ {copied ? <Check size={13} style={{ color: '#22c55e' }} /> : <Copy size={13} />}
32
+ </button>
33
+ );
34
+ }
35
+
36
+ // ─── Syntax highlighter ──────────────────────────────────────────────────────
37
+
38
+ type Token = { text: string; color: string };
39
+
40
+ function tokenizeBash(code: string): Token[][] {
41
+ return code.split('\n').map((line) => {
42
+ const tokens: Token[] = [];
43
+ // Comment lines
44
+ if (/^\s*#/.test(line)) {
45
+ tokens.push({ text: line, color: '#6b7280' });
46
+ return tokens;
47
+ }
48
+ // Prompt line: $ command [args]
49
+ const promptMatch = line.match(/^(\$\s*)(.+)$/);
50
+ if (promptMatch) {
51
+ tokens.push({ text: promptMatch[1], color: '#4b5563' });
52
+ const rest = promptMatch[2];
53
+ // Split into cmd + args
54
+ const parts = rest.split(/(?<=^\S+)\s+/);
55
+ const cmd = parts[0];
56
+ const args = parts.slice(1).join(' ');
57
+ // Highlight flags (--foo), strings, and scoped packages
58
+ const cmdTokens: Token[] = [];
59
+ cmdTokens.push({ text: cmd, color: '#f97316' });
60
+ if (args) {
61
+ const argParts = args.split(/((?:@[\w-]+\/[\w-]+)|(?:--[\w-]+)|(?:'[^']*')|(?:"[^"]*"))/g);
62
+ argParts.forEach((p) => {
63
+ if (!p) return;
64
+ if (p.startsWith('--')) cmdTokens.push({ text: ' ' + p, color: '#22c55e' });
65
+ else if (p.startsWith('@') || p.startsWith('\'') || p.startsWith('"')) cmdTokens.push({ text: ' ' + p, color: '#f97316' });
66
+ else cmdTokens.push({ text: ' ' + p, color: '#d1d5db' });
67
+ });
68
+ }
69
+ tokens.push(...cmdTokens);
70
+ return tokens;
71
+ }
72
+ // Output / plain lines
73
+ if (/^→|^✓|^✗/.test(line.trim())) {
74
+ tokens.push({ text: line, color: '#22c55e' });
75
+ } else if (/^#/.test(line.trim())) {
76
+ tokens.push({ text: line, color: '#6b7280' });
77
+ } else {
78
+ // Flags inline
79
+ const flagParts = line.split(/(--[\w-]+(?:\s+<[^>]+>)?)/g);
80
+ flagParts.forEach((p) => {
81
+ if (!p) return;
82
+ if (p.startsWith('--')) tokens.push({ text: p, color: '#22c55e' });
83
+ else tokens.push({ text: p, color: '#9ca3af' });
84
+ });
85
+ }
86
+ return tokens;
87
+ });
88
+ }
89
+
90
+ function tokenizeTS(code: string): Token[][] {
91
+ const KEYWORDS = /\b(import|export|from|default|const|let|var|function|return|type|interface|extends|implements|class|new|if|else|for|while|async|await|true|false|null|undefined)\b/g;
92
+ const STRINGS = /('[^']*'|"[^"]*"|`[^`]*`)/g;
93
+ const COMMENTS = /(\/\/[^\n]*)/g;
94
+ const NUMBERS = /\b(\d+(\.\d+)?)\b/g;
95
+ const TYPES = /\b([A-Z][A-Za-z0-9_]*)\b/g;
96
+ return code.split('\n').map((line) => {
97
+ // Simple single-pass tokenizer
98
+ const tokens: Token[] = [];
99
+ let remaining = line;
100
+ // Comment
101
+ const commentIdx = remaining.indexOf('//');
102
+ let commentSuffix = '';
103
+ if (commentIdx !== -1) {
104
+ commentSuffix = remaining.slice(commentIdx);
105
+ remaining = remaining.slice(0, commentIdx);
106
+ }
107
+ // Tokenize remaining by strings first
108
+ const parts = remaining.split(/((?:'[^']*')|(?:"[^"]*")|(?:`[^`]*`))/g);
109
+ parts.forEach((p) => {
110
+ if (!p) return;
111
+ if ((p.startsWith("'") || p.startsWith('"') || p.startsWith('`')) && p.length > 1) {
112
+ tokens.push({ text: p, color: '#22c55e' });
113
+ } else {
114
+ // Keywords, types, numbers in non-string segments
115
+ const sub = p.split(/(\b(?:import|export|from|default|const|let|var|function|return|type|interface|extends|implements|class|new|if|else|for|while|async|await|true|false|null|undefined)\b)/g);
116
+ sub.forEach((s) => {
117
+ if (!s) return;
118
+ if (/^(import|export|from|default|const|let|var|function|return|type|interface|extends|implements|class|new|if|else|for|while|async|await|true|false|null|undefined)$/.test(s)) {
119
+ tokens.push({ text: s, color: '#ea580c' });
120
+ } else if (/^[A-Z][A-Za-z0-9_]*$/.test(s.trim())) {
121
+ tokens.push({ text: s, color: '#f97316' });
122
+ } else if (/^\d+(\.\d+)?$/.test(s.trim())) {
123
+ tokens.push({ text: s, color: '#22c55e' });
124
+ } else {
125
+ tokens.push({ text: s, color: '#d1d5db' });
126
+ }
127
+ });
128
+ }
129
+ });
130
+ if (commentSuffix) tokens.push({ text: commentSuffix, color: '#6b7280' });
131
+ return tokens;
132
+ });
133
+ }
134
+
135
+ function tokenizeJSON(code: string): Token[][] {
136
+ return code.split('\n').map((line) => {
137
+ const tokens: Token[] = [];
138
+ const parts = line.split(/("[^"]*")/g);
139
+ parts.forEach((p, i) => {
140
+ if (!p) return;
141
+ if (p.startsWith('"')) {
142
+ // Key vs value: keys are followed by ':'
143
+ const after = parts[i + 1] || '';
144
+ if (after.trimStart().startsWith(':')) {
145
+ tokens.push({ text: p, color: '#9ca3af' });
146
+ } else {
147
+ tokens.push({ text: p, color: '#22c55e' });
148
+ }
149
+ } else {
150
+ // Numbers, booleans, punctuation
151
+ const sub = p.split(/(\b(?:true|false|null)\b|\b\d+\b)/g);
152
+ sub.forEach((s) => {
153
+ if (!s) return;
154
+ if (/^(true|false|null)$/.test(s)) tokens.push({ text: s, color: '#f97316' });
155
+ else if (/^\d+$/.test(s)) tokens.push({ text: s, color: '#22c55e' });
156
+ else tokens.push({ text: s, color: '#4b5563' });
157
+ });
158
+ }
159
+ });
160
+ return tokens;
161
+ });
162
+ }
163
+
164
+ function tokenizeTree(code: string): Token[][] {
165
+ return code.split('\n').map((line) => {
166
+ const tokens: Token[] = [];
167
+ const commentMatch = line.match(/^(.+?)(#.+)$/);
168
+ if (commentMatch) {
169
+ tokens.push({ text: commentMatch[1], color: '#d1d5db' });
170
+ tokens.push({ text: commentMatch[2], color: '#6b7280' });
171
+ } else if (/\.ts$|\.tsx$|\.js$|\.jsx$|\.json$|\.css$|\.html$/.test(line)) {
172
+ tokens.push({ text: line, color: '#f97316' });
173
+ } else if (/\/\s*$/.test(line.trim()) || /^[\w-]+\/$/.test(line.trim().replace(/[├└─│ ]/g, ''))) {
174
+ tokens.push({ text: line, color: '#22c55e' });
175
+ } else {
176
+ tokens.push({ text: line, color: '#d1d5db' });
177
+ }
178
+ return tokens;
179
+ });
180
+ }
181
+
182
+ function SyntaxLine({ tokens }: { tokens: Token[] }) {
183
+ return (
184
+ <div style={{ minHeight: '1.4em' }}>
185
+ {tokens.map((t, i) => (
186
+ <span key={i} style={{ color: t.color }}>{t.text}</span>
187
+ ))}
188
+ </div>
189
+ );
190
+ }
191
+
192
+ function CodeBlock({ children, lang = '' }: { children: string; lang?: string }) {
193
+ const lines = useMemo(() => {
194
+ if (lang === 'bash') return tokenizeBash(children);
195
+ if (lang === 'typescript' || lang === 'ts') return tokenizeTS(children);
196
+ if (lang === 'json') return tokenizeJSON(children);
197
+ if (lang === 'tree') return tokenizeTree(children);
198
+ // Plain fallback
199
+ return children.split('\n').map((l) => [{ text: l, color: '#d1d5db' }] as Token[]);
200
+ }, [children, lang]);
201
+
202
+ const langLabels: Record<string, string> = {
203
+ bash: 'bash', typescript: 'typescript', ts: 'typescript',
204
+ json: 'json', tree: 'tree', '': 'plain',
205
+ };
206
+
207
+ return (
208
+ <div className="terminal-chrome relative my-5">
209
+ <div className="terminal-header">
210
+ <div className="terminal-dot" style={{ background: '#ff5f57' }} />
211
+ <div className="terminal-dot" style={{ background: '#febc2e' }} />
212
+ <div className="terminal-dot" style={{ background: '#28c840' }} />
213
+ {lang && (
214
+ <span className="terminal-label" style={{ marginLeft: 'auto', color: '#4b5563', fontSize: '0.68rem', fontFamily: 'JetBrains Mono', letterSpacing: '0.08em' }}>
215
+ {langLabels[lang] ?? lang}
216
+ </span>
217
+ )}
218
+ </div>
219
+ <div className="terminal-body relative">
220
+ <CopyBtn text={children} />
221
+ <pre style={{ margin: 0, fontSize: '0.8rem', lineHeight: 1.85, whiteSpace: 'pre-wrap', wordBreak: 'break-word', fontFamily: 'JetBrains Mono' }}>
222
+ {lines.map((lineTokens: Token[], i: number) => (
223
+ <SyntaxLine key={i} tokens={lineTokens} />
224
+ ))}
225
+ </pre>
226
+ </div>
227
+ </div>
228
+ );
229
+ }
230
+
231
+ // ─── Sidebar nav ─────────────────────────────────────────────────────────────
232
+
233
+ const NAV_SECTIONS = [
234
+ {
235
+ title: 'Getting Started',
236
+ items: [
237
+ { id: 'introduction', label: 'Introduction', icon: BookOpen },
238
+ { id: 'installation', label: 'Installation', icon: Package },
239
+ { id: 'quick-start', label: 'Quick Start', icon: Zap },
240
+ ],
241
+ },
242
+ {
243
+ title: 'CLI',
244
+ items: [
245
+ { id: 'cli', label: 'CLI Reference', icon: Terminal },
246
+ { id: 'init', label: 'jxr init', icon: Layers },
247
+ { id: 'dev', label: 'jxr dev', icon: Activity },
248
+ { id: 'build', label: 'jxr build', icon: Code2 },
249
+ { id: 'migrate', label: 'jxr migrate', icon: GitBranch },
250
+ { id: 'deploy', label: 'jxr deploy', icon: Globe },
251
+ ],
252
+ },
253
+ {
254
+ title: 'Configuration',
255
+ items: [
256
+ { id: 'config', label: 'jxr.config.ts', icon: Code2 },
257
+ { id: 'workers', label: 'Worker Pool', icon: Cpu },
258
+ { id: 'moq', label: 'MoQ Transport', icon: Activity },
259
+ { id: 'crypto', label: 'Web Crypto', icon: Shield },
260
+ ],
261
+ },
262
+ {
263
+ title: 'MCP Server',
264
+ items: [
265
+ { id: 'mcp', label: 'MCP Overview', icon: Package },
266
+ { id: 'mcp-tools', label: 'Tool Reference', icon: Code2 },
267
+ ],
268
+ },
269
+ ];
270
+
271
+ // ─── Doc content ──────────────────────────────────────────────────────────────
272
+
273
+ const DOC_CONTENT: Record<string, React.ReactNode> = {
274
+ introduction: (
275
+ <div>
276
+ <h1 style={{ fontFamily: 'Inter', fontWeight: 900, fontSize: '2.2rem', color: '#ffffff', letterSpacing: '-0.02em', marginBottom: '1rem', lineHeight: 1.1 }}>
277
+ Introduction to <span style={{ color: '#f97316' }}>JXR.js</span>
278
+ </h1>
279
+ <p style={{ color: '#9ca3af', lineHeight: 1.7, marginBottom: '1.5rem', fontSize: '1.05rem' }}>
280
+ JXR.js is a next-generation build framework and edge runtime for React Native and React projects.
281
+ It is designed to be used in any IDE — VSCode, Warp, Cursor, or any terminal — and provides
282
+ a Model Context Protocol (MCP) server so AI agents can manage your entire project lifecycle.
283
+ </p>
284
+ <div className="grid md:grid-cols-3 gap-3 my-6">
285
+ {[
286
+ { icon: Cpu, color: '#ea580c', title: 'Worker Pools', desc: 'Pre-warmed worker_threads for parallel builds and transforms' },
287
+ { icon: Activity, color: '#22c55e', title: 'MoQ Transport', desc: 'Media over QUIC for sub-RTT module streaming and HMR' },
288
+ { icon: Shield, color: '#ea580c', title: 'Web Crypto', desc: 'AES-GCM-256 module caching and ECDSA manifest signing' },
289
+ ].map((item) => {
290
+ const Icon = item.icon;
291
+ return (
292
+ <div key={item.title} className="jxr-card">
293
+ <div className="w-8 h-8 rounded-lg flex items-center justify-center mb-3" style={{ background: `${item.color}18`, border: `1px solid ${item.color}30` }}>
294
+ <Icon size={15} style={{ color: item.color }} />
295
+ </div>
296
+ <h3 style={{ fontFamily: 'Inter', fontWeight: 700, fontSize: '0.9rem', color: '#ffffff', marginBottom: '0.35rem' }}>{item.title}</h3>
297
+ <p style={{ fontSize: '0.78rem', color: '#6b7280', lineHeight: 1.55 }}>{item.desc}</p>
298
+ </div>
299
+ );
300
+ })}
301
+ </div>
302
+ <h2 style={{ fontFamily: 'Inter', fontWeight: 800, fontSize: '1.4rem', color: '#ffffff', letterSpacing: '-0.01em', marginTop: '2rem', marginBottom: '0.75rem' }}>Why JXR?</h2>
303
+ <p style={{ color: '#9ca3af', lineHeight: 1.7, marginBottom: '1rem' }}>
304
+ Existing frameworks like Next.js, Vite, and Bun are excellent tools, but they were not designed
305
+ with edge-first, AI-native, or MoQ-based workflows in mind. JXR fills this gap by providing
306
+ a framework that is simultaneously a CLI tool, a build engine, and an MCP server.
307
+ </p>
308
+ <p style={{ color: '#9ca3af', lineHeight: 1.7 }}>
309
+ JXR is powered by <strong style={{ color: '#f97316' }}>JXR Studios</strong> and{' '}
310
+ <strong style={{ color: '#22c55e' }}>DamascusAI</strong>.
311
+ It is the future of edge cloud OS deployments for developers who want to take their game to the next level.
312
+ </p>
313
+ </div>
314
+ ),
315
+
316
+ installation: (
317
+ <div>
318
+ <h1 style={{ fontFamily: 'Inter', fontWeight: 900, fontSize: '2.2rem', color: '#ffffff', letterSpacing: '-0.02em', marginBottom: '1rem', lineHeight: 1.1 }}>Installation</h1>
319
+ <p style={{ color: '#9ca3af', lineHeight: 1.7, marginBottom: '1rem' }}>
320
+ Install the JXR CLI globally using your preferred package manager.
321
+ </p>
322
+ <CodeBlock lang="bash">{`# npm
323
+ npm install -g @jxrstudios/jxr
324
+
325
+ # pnpm
326
+ pnpm add -g @jxrstudios/jxr
327
+
328
+ # yarn
329
+ yarn global add @jxrstudios/jxr
330
+
331
+ # bun
332
+ bun add -g @jxrstudios/jxr`}</CodeBlock>
333
+ <p style={{ color: '#9ca3af', lineHeight: 1.7, marginBottom: '0.75rem' }}>Verify the installation:</p>
334
+ <CodeBlock lang="bash">{`jxr --version
335
+ # JXR.js v1.0.0-edge
336
+
337
+ jxr info
338
+ # Prints full environment and project info`}</CodeBlock>
339
+ <h2 style={{ fontFamily: 'Inter', fontWeight: 800, fontSize: '1.4rem', color: '#ffffff', marginTop: '2rem', marginBottom: '0.75rem' }}>Requirements</h2>
340
+ <div className="jxr-card">
341
+ <div className="grid grid-cols-2 gap-3">
342
+ {[
343
+ ['Node.js', '≥ 20.0.0'],
344
+ ['npm / pnpm / yarn / bun', 'Any version'],
345
+ ['TypeScript', '≥ 5.0 (optional)'],
346
+ ['Platform', 'macOS, Linux, Windows'],
347
+ ].map(([k, v]) => (
348
+ <div key={k} className="flex justify-between">
349
+ <span style={{ fontSize: '0.82rem', color: '#6b7280' }}>{k}</span>
350
+ <span style={{ fontFamily: 'JetBrains Mono', fontSize: '0.8rem', color: '#f97316' }}>{v}</span>
351
+ </div>
352
+ ))}
353
+ </div>
354
+ </div>
355
+ </div>
356
+ ),
357
+
358
+ 'quick-start': (
359
+ <div>
360
+ <h1 style={{ fontFamily: 'Inter', fontWeight: 900, fontSize: '2.2rem', color: '#ffffff', letterSpacing: '-0.02em', marginBottom: '1rem', lineHeight: 1.1 }}>Quick Start</h1>
361
+ <p style={{ color: '#9ca3af', lineHeight: 1.7, marginBottom: '1rem' }}>Get a JXR project running in under 60 seconds.</p>
362
+ <CodeBlock lang="bash">{`# 1. Create a new project
363
+ jxr init my-app
364
+
365
+ # 2. Enter the project directory
366
+ cd my-app
367
+
368
+ # 3. Start the dev server
369
+ jxr dev
370
+ # → Local: http://localhost:3000`}</CodeBlock>
371
+ <p style={{ color: '#9ca3af', lineHeight: 1.7, marginBottom: '0.75rem' }}>
372
+ The interactive <code style={{ fontFamily: 'JetBrains Mono', fontSize: '0.85em', color: '#f97316', background: 'rgba(234,88,12,0.1)', padding: '1px 5px', borderRadius: '4px' }}>jxr init</code> prompt
373
+ will ask for your project name, template, and package manager. You can also pass flags directly:
374
+ </p>
375
+ <CodeBlock lang="bash">{`jxr init my-app --template react-native --package-manager pnpm
376
+ jxr init my-worker --template cloudflare
377
+ jxr init my-expo-app --template expo`}</CodeBlock>
378
+ </div>
379
+ ),
380
+
381
+ cli: (
382
+ <div>
383
+ <h1 style={{ fontFamily: 'Inter', fontWeight: 900, fontSize: '2.2rem', color: '#ffffff', letterSpacing: '-0.02em', marginBottom: '1rem', lineHeight: 1.1 }}>CLI Reference</h1>
384
+ <p style={{ color: '#9ca3af', lineHeight: 1.7, marginBottom: '1.25rem' }}>
385
+ The <code style={{ fontFamily: 'JetBrains Mono', fontSize: '0.85em', color: '#f97316', background: 'rgba(234,88,12,0.1)', padding: '1px 5px', borderRadius: '4px' }}>jxr</code> CLI is the primary interface for JXR.js.
386
+ It works in any terminal — VSCode integrated terminal, Warp, Cursor, iTerm, Windows Terminal, or any shell.
387
+ </p>
388
+ {[
389
+ { cmd: 'jxr init [name]', desc: 'Scaffold a new JXR project', flags: ['--template react-web|react-native|expo|cloudflare', '--platform web|native|expo|cloudflare-worker|deno|node', '--package-manager npm|yarn|pnpm|bun', '--no-install', '--no-git'] },
390
+ { cmd: 'jxr dev', desc: 'Start the development server', flags: ['--port <port>', '--host <host>', '--open', '--https', '--no-hmr', '--config <path>'] },
391
+ { cmd: 'jxr build', desc: 'Production build', flags: ['--platform <platform>', '--out-dir <dir>', '--no-minify', '--no-sourcemap', '--analyze', '--config <path>'] },
392
+ { cmd: 'jxr migrate', desc: 'Migrate from another framework', flags: ['--from nextjs|vite|bun|cra|expo|remix|nuxt|auto', '--dry-run', '--no-backup', '--config <path>'] },
393
+ { cmd: 'jxr deploy', desc: 'Deploy to an edge platform', flags: ['--target cloudflare|deno|node|vercel', '--env production|preview|staging', '--no-build', '--config <path>'] },
394
+ { cmd: 'jxr add <plugin>', desc: 'Add a JXR plugin', flags: ['--dev'] },
395
+ { cmd: 'jxr info', desc: 'Print environment and project info', flags: [] },
396
+ ].map((item) => (
397
+ <div key={item.cmd} className="jxr-card mb-3">
398
+ <div style={{ fontFamily: 'JetBrains Mono', fontSize: '0.88rem', color: '#f97316', fontWeight: 700, marginBottom: '0.35rem' }}>{item.cmd}</div>
399
+ <div style={{ fontSize: '0.82rem', color: '#6b7280', marginBottom: item.flags.length ? '0.75rem' : 0 }}>{item.desc}</div>
400
+ {item.flags.length > 0 && (
401
+ <div className="space-y-1">
402
+ {item.flags.map((f) => (
403
+ <div key={f} style={{ fontFamily: 'JetBrains Mono', fontSize: '0.72rem', color: '#374151' }}>&nbsp;&nbsp;{f}</div>
404
+ ))}
405
+ </div>
406
+ )}
407
+ </div>
408
+ ))}
409
+ </div>
410
+ ),
411
+
412
+ config: (
413
+ <div>
414
+ <h1 style={{ fontFamily: 'Inter', fontWeight: 900, fontSize: '2.2rem', color: '#ffffff', letterSpacing: '-0.02em', marginBottom: '1rem', lineHeight: 1.1 }}>jxr.config.ts</h1>
415
+ <p style={{ color: '#9ca3af', lineHeight: 1.7, marginBottom: '1rem' }}>
416
+ The JXR configuration file is a TypeScript file at the root of your project.
417
+ It is fully typed via <code style={{ fontFamily: 'JetBrains Mono', fontSize: '0.85em', color: '#f97316', background: 'rgba(234,88,12,0.1)', padding: '1px 5px', borderRadius: '4px' }}>defineConfig</code> from <code style={{ fontFamily: 'JetBrains Mono', fontSize: '0.85em', color: '#f97316', background: 'rgba(234,88,12,0.1)', padding: '1px 5px', borderRadius: '4px' }}>@jxrstudios/core</code>.
418
+ </p>
419
+ <CodeBlock lang="typescript">{`import { defineConfig } from '@jxrstudios/core';
420
+
421
+ export default defineConfig({
422
+ name: 'my-app',
423
+ platform: 'web', // 'web' | 'native' | 'expo' | 'cloudflare-worker' | 'deno' | 'node'
424
+
425
+ workers: {
426
+ size: 4, // Number of worker threads
427
+ enablePriority: true, // Enable priority queue
428
+ maxQueueSize: 1000, // Max pending tasks
429
+ },
430
+
431
+ moq: {
432
+ enabled: true,
433
+ relayUrl: 'wss://relay.jxr.dev', // Optional: MoQ relay server
434
+ },
435
+
436
+ crypto: {
437
+ enabled: true,
438
+ algorithm: 'AES-GCM', // 'AES-GCM' | 'AES-CBC'
439
+ signing: true, // ECDSA P-256 manifest signing
440
+ keyDerivation: 'HKDF',
441
+ },
442
+
443
+ build: {
444
+ entry: 'src/main.tsx',
445
+ outDir: 'dist',
446
+ minify: true,
447
+ sourcemap: true,
448
+ splitting: 'auto', // 'auto' | 'manual' | false
449
+ target: ['es2022'],
450
+ external: [],
451
+ },
452
+
453
+ devServer: {
454
+ port: 3000,
455
+ host: 'localhost',
456
+ hmr: true,
457
+ open: false,
458
+ https: false,
459
+ },
460
+
461
+ plugins: [], // JXR plugins
462
+ });`}</CodeBlock>
463
+ </div>
464
+ ),
465
+
466
+ mcp: (
467
+ <div>
468
+ <h1 style={{ fontFamily: 'Inter', fontWeight: 900, fontSize: '2.2rem', color: '#ffffff', letterSpacing: '-0.02em', marginBottom: '1rem', lineHeight: 1.1 }}>MCP Server</h1>
469
+ <p style={{ color: '#9ca3af', lineHeight: 1.7, marginBottom: '1.25rem' }}>
470
+ The JXR MCP server (<code style={{ fontFamily: 'JetBrains Mono', fontSize: '0.85em', color: '#f97316', background: 'rgba(234,88,12,0.1)', padding: '1px 5px', borderRadius: '4px' }}>@jxrstudios/mcp</code>) implements the
471
+ Model Context Protocol, allowing AI agents like Claude, Cursor, and GitHub Copilot to manage
472
+ JXR projects autonomously — initializing, building, migrating, and deploying without leaving the chat.
473
+ </p>
474
+ <h2 style={{ fontFamily: 'Inter', fontWeight: 800, fontSize: '1.4rem', color: '#ffffff', marginTop: '2rem', marginBottom: '0.75rem' }}>Setup</h2>
475
+ <p style={{ color: '#9ca3af', lineHeight: 1.7, marginBottom: '0.75rem' }}>Add to your MCP client configuration:</p>
476
+ <CodeBlock lang="json">{`// Claude Desktop: ~/Library/Application Support/Claude/claude_desktop_config.json
477
+ // Cursor: .cursor/mcp.json
478
+ // Any MCP client: see client docs
479
+
480
+ {
481
+ "mcpServers": {
482
+ "jxrstudios": {
483
+ "command": "npx",
484
+ "args": ["-y", "@jxrstudios/mcp"]
485
+ }
486
+ }
487
+ }`}</CodeBlock>
488
+ <h2 style={{ fontFamily: 'Inter', fontWeight: 800, fontSize: '1.4rem', color: '#ffffff', marginTop: '2rem', marginBottom: '0.75rem' }}>Example AI Prompts</h2>
489
+ <div className="space-y-2">
490
+ {[
491
+ 'Create a new JXR React Native project called "my-app" and start the dev server',
492
+ 'Migrate this Next.js project to JXR, then build it for Cloudflare Workers',
493
+ 'Add the Tailwind plugin to this JXR project and update the config',
494
+ 'Deploy this JXR project to Cloudflare Workers in production mode',
495
+ ].map((prompt) => (
496
+ <div key={prompt} className="jxr-card flex items-start gap-3 py-3">
497
+ <ChevronRight size={14} style={{ color: '#ea580c', marginTop: '2px', flexShrink: 0 }} />
498
+ <p style={{ fontSize: '0.85rem', color: '#9ca3af', fontStyle: 'italic' }}>"{prompt}"</p>
499
+ </div>
500
+ ))}
501
+ </div>
502
+ </div>
503
+ ),
504
+
505
+ migrate: (
506
+ <div>
507
+ <h1 style={{ fontFamily: 'Inter', fontWeight: 900, fontSize: '2.2rem', color: '#ffffff', letterSpacing: '-0.02em', marginBottom: '1rem', lineHeight: 1.1 }}>Migration Guide</h1>
508
+ <p style={{ color: '#9ca3af', lineHeight: 1.7, marginBottom: '1rem' }}>
509
+ JXR can migrate projects from Next.js, Vite, Bun, Create React App, Expo, Remix, and Nuxt.
510
+ The migration engine performs AST-level transforms and creates a full backup before touching any files.
511
+ </p>
512
+ <CodeBlock lang="bash">{`# Auto-detect and migrate
513
+ jxr migrate
514
+
515
+ # Specify source framework
516
+ jxr migrate --from nextjs
517
+ jxr migrate --from vite
518
+ jxr migrate --from bun
519
+ jxr migrate --from cra
520
+ jxr migrate --from expo
521
+
522
+ # Preview changes without writing
523
+ jxr migrate --dry-run
524
+
525
+ # Skip backup (not recommended)
526
+ jxr migrate --no-backup`}</CodeBlock>
527
+ <h2 style={{ fontFamily: 'Inter', fontWeight: 800, fontSize: '1.4rem', color: '#ffffff', marginTop: '2rem', marginBottom: '0.75rem' }}>What gets migrated</h2>
528
+ <div className="grid md:grid-cols-2 gap-3">
529
+ {[
530
+ { from: 'next.config.js', to: 'jxr.config.ts' },
531
+ { from: 'vite.config.ts', to: 'jxr.config.ts' },
532
+ { from: 'next/image', to: '@jxrstudios/runtime/image' },
533
+ { from: 'next/link', to: '@jxrstudios/runtime/link' },
534
+ { from: 'next/router', to: '@jxrstudios/runtime/router' },
535
+ { from: 'react-scripts', to: 'jxr (CLI)' },
536
+ { from: 'REACT_APP_*', to: 'VITE_* (import.meta.env)' },
537
+ { from: 'pages/api/*', to: 'JXR edge handlers' },
538
+ ].map((item) => (
539
+ <div key={item.from} className="flex items-center gap-3 p-2.5 rounded" style={{ background: '#111111', border: '1px solid rgba(255,255,255,0.05)' }}>
540
+ <code style={{ fontFamily: 'JetBrains Mono', fontSize: '0.75rem', color: '#4b5563', textDecoration: 'line-through' }}>{item.from}</code>
541
+ <ChevronRight size={11} style={{ color: '#ea580c', flexShrink: 0 }} />
542
+ <code style={{ fontFamily: 'JetBrains Mono', fontSize: '0.75rem', color: '#f97316' }}>{item.to}</code>
543
+ </div>
544
+ ))}
545
+ </div>
546
+ </div>
547
+ ),
548
+
549
+ init: (
550
+ <div>
551
+ <h1 style={{ fontFamily: 'Inter', fontWeight: 900, fontSize: '2.2rem', color: '#ffffff', letterSpacing: '-0.02em', marginBottom: '1rem', lineHeight: 1.1 }}>jxr init</h1>
552
+ <p style={{ color: '#9ca3af', lineHeight: 1.7, marginBottom: '1rem' }}>
553
+ Scaffold a new JXR project interactively or via flags. Supports React (web), React Native, Expo, and Cloudflare Worker templates.
554
+ </p>
555
+ <CodeBlock lang="bash">{`# Interactive scaffold
556
+ jxr init my-app
557
+
558
+ # With flags
559
+ jxr init my-app --template react-native --package-manager pnpm
560
+ jxr init my-worker --template cloudflare
561
+ jxr init my-expo-app --template expo --no-git`}</CodeBlock>
562
+ <h2 style={{ fontFamily: 'Inter', fontWeight: 800, fontSize: '1.4rem', color: '#ffffff', marginTop: '2rem', marginBottom: '0.75rem' }}>Flags</h2>
563
+ <div className="space-y-2">
564
+ {[
565
+ ['--template', 'react-web | react-native | expo | cloudflare', 'Project template'],
566
+ ['--platform', 'web | native | expo | cloudflare-worker | deno | node', 'Target platform'],
567
+ ['--package-manager', 'npm | yarn | pnpm | bun', 'Package manager to use'],
568
+ ['--no-install', '', 'Skip dependency installation'],
569
+ ['--no-git', '', 'Skip git repository initialization'],
570
+ ].map(([flag, values, desc]) => (
571
+ <div key={flag} className="jxr-card py-3">
572
+ <div className="flex items-start gap-3">
573
+ <code style={{ fontFamily: 'JetBrains Mono', fontSize: '0.8rem', color: '#f97316', flexShrink: 0 }}>{flag}</code>
574
+ {values && <code style={{ fontFamily: 'JetBrains Mono', fontSize: '0.75rem', color: '#4b5563' }}>{values}</code>}
575
+ </div>
576
+ <p style={{ fontSize: '0.8rem', color: '#6b7280', marginTop: '0.25rem' }}>{desc}</p>
577
+ </div>
578
+ ))}
579
+ </div>
580
+ <h2 style={{ fontFamily: 'Inter', fontWeight: 800, fontSize: '1.4rem', color: '#ffffff', marginTop: '2rem', marginBottom: '0.75rem' }}>Generated structure</h2>
581
+ <CodeBlock lang="tree">{`my-app/
582
+ ├── jxr.config.ts # JXR configuration
583
+ ├── src/
584
+ │ ├── main.tsx # Entry point
585
+ │ ├── App.tsx # Root component
586
+ │ └── components/
587
+ ├── public/
588
+ ├── package.json
589
+ └── tsconfig.json`}</CodeBlock>
590
+ </div>
591
+ ),
592
+
593
+ dev: (
594
+ <div>
595
+ <h1 style={{ fontFamily: 'Inter', fontWeight: 900, fontSize: '2.2rem', color: '#ffffff', letterSpacing: '-0.02em', marginBottom: '1rem', lineHeight: 1.1 }}>jxr dev</h1>
596
+ <p style={{ color: '#9ca3af', lineHeight: 1.7, marginBottom: '1rem' }}>
597
+ Start the JXR development server with Hot Module Replacement (HMR), Worker pool pre-warming, and MoQ transport initialization.
598
+ No build step is required — modules are served directly from the virtual file system.
599
+ </p>
600
+ <CodeBlock lang="bash">{`# Start on default port 3000
601
+ jxr dev
602
+
603
+ # Custom port and host
604
+ jxr dev --port 8080 --host 0.0.0.0
605
+
606
+ # Open browser automatically
607
+ jxr dev --open
608
+
609
+ # HTTPS with self-signed cert
610
+ jxr dev --https`}</CodeBlock>
611
+ <h2 style={{ fontFamily: 'Inter', fontWeight: 800, fontSize: '1.4rem', color: '#ffffff', marginTop: '2rem', marginBottom: '0.75rem' }}>What happens on start</h2>
612
+ <div className="space-y-2">
613
+ {[
614
+ { step: '1', label: 'Worker pool pre-warm', desc: 'Spawns worker_threads up to hardware concurrency. Subsequent builds use the warm pool with zero startup cost.' },
615
+ { step: '2', label: 'MoQ transport init', desc: 'Initializes the Media over QUIC transport layer. If a relay URL is configured, connects and subscribes to the project track.' },
616
+ { step: '3', label: 'Web Crypto engine', desc: 'Derives the session key via HKDF and initializes the AES-GCM module cache. All served modules are integrity-checked.' },
617
+ { step: '4', label: 'File watcher', desc: 'Watches src/ for changes. On change, the module is transformed in a Worker and pushed to connected clients via HMR.' },
618
+ ].map((item) => (
619
+ <div key={item.step} className="jxr-card flex gap-4">
620
+ <div className="w-7 h-7 rounded-full flex items-center justify-center flex-shrink-0" style={{ background: 'rgba(234,88,12,0.12)', border: '1px solid rgba(234,88,12,0.25)' }}>
621
+ <span style={{ fontFamily: 'JetBrains Mono', fontSize: '0.7rem', color: '#f97316', fontWeight: 700 }}>{item.step}</span>
622
+ </div>
623
+ <div>
624
+ <div style={{ fontFamily: 'Inter', fontWeight: 700, fontSize: '0.88rem', color: '#ffffff', marginBottom: '0.25rem' }}>{item.label}</div>
625
+ <p style={{ fontSize: '0.8rem', color: '#6b7280', lineHeight: 1.55 }}>{item.desc}</p>
626
+ </div>
627
+ </div>
628
+ ))}
629
+ </div>
630
+ <h2 style={{ fontFamily: 'Inter', fontWeight: 800, fontSize: '1.4rem', color: '#ffffff', marginTop: '2rem', marginBottom: '0.75rem' }}>Flags</h2>
631
+ <CodeBlock lang="bash">{`--port <port> # Dev server port (default: 3000)
632
+ --host <host> # Dev server host (default: localhost)
633
+ --open # Open browser on start
634
+ --https # Enable HTTPS
635
+ --no-hmr # Disable Hot Module Replacement
636
+ --config <path> # Path to jxr.config.ts`}</CodeBlock>
637
+ </div>
638
+ ),
639
+
640
+ build: (
641
+ <div>
642
+ <h1 style={{ fontFamily: 'Inter', fontWeight: 900, fontSize: '2.2rem', color: '#ffffff', letterSpacing: '-0.02em', marginBottom: '1rem', lineHeight: 1.1 }}>jxr build</h1>
643
+ <p style={{ color: '#9ca3af', lineHeight: 1.7, marginBottom: '1rem' }}>
644
+ Produce a production-optimized build. The JXR build engine uses esbuild under the hood with Worker-parallel transforms,
645
+ automatic code splitting, and a cryptographically signed build manifest.
646
+ </p>
647
+ <CodeBlock lang="bash">{`# Standard production build
648
+ jxr build
649
+
650
+ # Target a specific platform
651
+ jxr build --platform cloudflare-worker
652
+ jxr build --platform deno
653
+ jxr build --platform node
654
+
655
+ # Analyze bundle
656
+ jxr build --analyze
657
+
658
+ # Skip minification (for debugging)
659
+ jxr build --no-minify`}</CodeBlock>
660
+ <h2 style={{ fontFamily: 'Inter', fontWeight: 800, fontSize: '1.4rem', color: '#ffffff', marginTop: '2rem', marginBottom: '0.75rem' }}>Build outputs</h2>
661
+ <CodeBlock lang="tree">{`dist/
662
+ ├── assets/
663
+ │ ├── index-[hash].js # Main bundle
664
+ │ ├── vendor-[hash].js # Vendor chunk
665
+ │ └── *.css
666
+ ├── index.html
667
+ └── jxr-manifest.json # Crypto-signed build manifest`}</CodeBlock>
668
+ <h2 style={{ fontFamily: 'Inter', fontWeight: 800, fontSize: '1.4rem', color: '#ffffff', marginTop: '2rem', marginBottom: '0.75rem' }}>Build manifest</h2>
669
+ <p style={{ color: '#9ca3af', lineHeight: 1.7, marginBottom: '0.75rem' }}>
670
+ Every JXR build produces a <code style={{ fontFamily: 'JetBrains Mono', fontSize: '0.85em', color: '#f97316', background: 'rgba(234,88,12,0.1)', padding: '1px 5px', borderRadius: '4px' }}>jxr-manifest.json</code> file
671
+ signed with ECDSA P-256. The runtime verifies this signature before serving any module.
672
+ </p>
673
+ <CodeBlock lang="json">{`{
674
+ "version": "1.0.0",
675
+ "platform": "web",
676
+ "buildTime": "2026-03-13T00:00:00Z",
677
+ "entries": {
678
+ "main": "assets/index-abc123.js",
679
+ "vendor": "assets/vendor-def456.js"
680
+ },
681
+ "signature": "MEQCIBx...",
682
+ "algorithm": "ECDSA-P256"
683
+ }`}</CodeBlock>
684
+ </div>
685
+ ),
686
+
687
+ deploy: (
688
+ <div>
689
+ <h1 style={{ fontFamily: 'Inter', fontWeight: 900, fontSize: '2.2rem', color: '#ffffff', letterSpacing: '-0.02em', marginBottom: '1rem', lineHeight: 1.1 }}>jxr deploy</h1>
690
+ <p style={{ color: '#9ca3af', lineHeight: 1.7, marginBottom: '1rem' }}>
691
+ Deploy your JXR project to Cloudflare Workers, Deno Deploy, or a Node.js server. JXR automatically
692
+ selects the correct adapter and builds for the target platform.
693
+ </p>
694
+ <CodeBlock lang="bash">{`# Deploy to Cloudflare Workers
695
+ jxr deploy --target cloudflare
696
+
697
+ # Deploy to Deno Deploy
698
+ jxr deploy --target deno
699
+
700
+ # Deploy to Node.js (Docker / VPS)
701
+ jxr deploy --target node
702
+
703
+ # Deploy to preview environment
704
+ jxr deploy --target cloudflare --env preview
705
+
706
+ # Skip build step (use existing dist/)
707
+ jxr deploy --target cloudflare --no-build`}</CodeBlock>
708
+ <h2 style={{ fontFamily: 'Inter', fontWeight: 800, fontSize: '1.4rem', color: '#ffffff', marginTop: '2rem', marginBottom: '0.75rem' }}>Platform requirements</h2>
709
+ <div className="space-y-2">
710
+ {[
711
+ { target: 'cloudflare', req: 'wrangler CLI installed and authenticated (npx wrangler login)', color: '#f97316' },
712
+ { target: 'deno', req: 'Deno CLI installed and DENO_DEPLOY_TOKEN set in environment', color: '#22c55e' },
713
+ { target: 'node', req: 'Node.js ≥ 20 on target server, SSH access or CI pipeline configured', color: '#9ca3af' },
714
+ ].map((item) => (
715
+ <div key={item.target} className="jxr-card flex items-start gap-3">
716
+ <code style={{ fontFamily: 'JetBrains Mono', fontSize: '0.8rem', color: item.color, flexShrink: 0, minWidth: '90px' }}>{item.target}</code>
717
+ <p style={{ fontSize: '0.8rem', color: '#6b7280', lineHeight: 1.55 }}>{item.req}</p>
718
+ </div>
719
+ ))}
720
+ </div>
721
+ </div>
722
+ ),
723
+
724
+ workers: (
725
+ <div>
726
+ <h1 style={{ fontFamily: 'Inter', fontWeight: 900, fontSize: '2.2rem', color: '#ffffff', letterSpacing: '-0.02em', marginBottom: '1rem', lineHeight: 1.1 }}>Worker Pool</h1>
727
+ <p style={{ color: '#9ca3af', lineHeight: 1.7, marginBottom: '1rem' }}>
728
+ The JXR Worker Pool engine manages a fleet of Node.js <code style={{ fontFamily: 'JetBrains Mono', fontSize: '0.85em', color: '#f97316', background: 'rgba(234,88,12,0.1)', padding: '1px 5px', borderRadius: '4px' }}>worker_threads</code> that
729
+ are pre-warmed at startup. All CPU-intensive operations — JSX transforms, crypto ops, module resolution — run off the main thread.
730
+ </p>
731
+ <h2 style={{ fontFamily: 'Inter', fontWeight: 800, fontSize: '1.4rem', color: '#ffffff', marginTop: '2rem', marginBottom: '0.75rem' }}>Configuration</h2>
732
+ <CodeBlock lang="typescript">{`// jxr.config.ts
733
+ export default defineConfig({
734
+ workers: {
735
+ size: 8, // Worker thread count (default: os.cpus().length)
736
+ enablePriority: true, // Priority queue for task scheduling
737
+ maxQueueSize: 1000, // Max pending tasks before backpressure
738
+ taskTimeout: 30000, // Task timeout in ms (default: 30s)
739
+ },
740
+ });`}</CodeBlock>
741
+ <h2 style={{ fontFamily: 'Inter', fontWeight: 800, fontSize: '1.4rem', color: '#ffffff', marginTop: '2rem', marginBottom: '0.75rem' }}>How it works</h2>
742
+ <div className="space-y-2">
743
+ {[
744
+ { title: 'Pre-warming', desc: 'Workers are spawned at dev server start or build init. The first task has zero cold-start cost because the pool is already live.' },
745
+ { title: 'Priority queue', desc: 'Tasks are enqueued with a priority level (high / normal / low). HMR updates are always high priority; background cache writes are low.' },
746
+ { title: 'Backpressure', desc: 'When the queue exceeds maxQueueSize, new tasks are rejected with a JXRWorkerPoolError. The caller should retry with exponential backoff.' },
747
+ { title: 'Auto-scaling', desc: 'The pool monitors queue depth and worker utilization. Under sustained load it will spawn additional workers up to 2× the configured size.' },
748
+ ].map((item) => (
749
+ <div key={item.title} className="jxr-card">
750
+ <div style={{ fontFamily: 'Inter', fontWeight: 700, fontSize: '0.88rem', color: '#ea580c', marginBottom: '0.3rem' }}>{item.title}</div>
751
+ <p style={{ fontSize: '0.8rem', color: '#6b7280', lineHeight: 1.55 }}>{item.desc}</p>
752
+ </div>
753
+ ))}
754
+ </div>
755
+ </div>
756
+ ),
757
+
758
+ moq: (
759
+ <div>
760
+ <h1 style={{ fontFamily: 'Inter', fontWeight: 900, fontSize: '2.2rem', color: '#ffffff', letterSpacing: '-0.02em', marginBottom: '1rem', lineHeight: 1.1 }}>MoQ Transport</h1>
761
+ <p style={{ color: '#9ca3af', lineHeight: 1.7, marginBottom: '1rem' }}>
762
+ JXR implements Media over QUIC (MoQ) transport semantics for sub-RTT module streaming and HMR delivery.
763
+ The track/object/subscription model means module updates are pushed to the browser before the file is even saved to disk.
764
+ </p>
765
+ <h2 style={{ fontFamily: 'Inter', fontWeight: 800, fontSize: '1.4rem', color: '#ffffff', marginTop: '2rem', marginBottom: '0.75rem' }}>Configuration</h2>
766
+ <CodeBlock lang="typescript">{`// jxr.config.ts
767
+ export default defineConfig({
768
+ moq: {
769
+ enabled: true,
770
+ relayUrl: 'wss://relay.jxr.dev', // Optional MoQ relay
771
+ trackPriority: 'high', // 'high' | 'normal' | 'low'
772
+ maxSubscriptions: 100,
773
+ reconnectDelay: 1000, // ms before reconnect attempt
774
+ },
775
+ });`}</CodeBlock>
776
+ <h2 style={{ fontFamily: 'Inter', fontWeight: 800, fontSize: '1.4rem', color: '#ffffff', marginTop: '2rem', marginBottom: '0.75rem' }}>Core concepts</h2>
777
+ <div className="space-y-2">
778
+ {[
779
+ { term: 'Track', desc: 'A named stream of related objects. JXR creates one track per project (e.g. jxr/my-app/modules). Subscribers receive all objects on the track.' },
780
+ { term: 'Object', desc: 'A single versioned payload on a track — typically a transformed module. Objects are immutable and content-addressed by their crypto hash.' },
781
+ { term: 'Subscription', desc: 'A client subscribes to a track and receives new objects in real time. The browser HMR client subscribes to the project track on connect.' },
782
+ { term: 'Relay', desc: 'An optional server that fans out track objects to multiple subscribers. Without a relay, JXR falls back to WebSocket-based HMR.' },
783
+ ].map((item) => (
784
+ <div key={item.term} className="jxr-card">
785
+ <code style={{ fontFamily: 'JetBrains Mono', fontSize: '0.82rem', color: '#22c55e', fontWeight: 700 }}>{item.term}</code>
786
+ <p style={{ fontSize: '0.8rem', color: '#6b7280', lineHeight: 1.55, marginTop: '0.3rem' }}>{item.desc}</p>
787
+ </div>
788
+ ))}
789
+ </div>
790
+ </div>
791
+ ),
792
+
793
+ crypto: (
794
+ <div>
795
+ <h1 style={{ fontFamily: 'Inter', fontWeight: 900, fontSize: '2.2rem', color: '#ffffff', letterSpacing: '-0.02em', marginBottom: '1rem', lineHeight: 1.1 }}>Web Crypto</h1>
796
+ <p style={{ color: '#9ca3af', lineHeight: 1.7, marginBottom: '1rem' }}>
797
+ The JXR crypto engine is built entirely on the W3C Web Crypto API (<code style={{ fontFamily: 'JetBrains Mono', fontSize: '0.85em', color: '#f97316', background: 'rgba(234,88,12,0.1)', padding: '1px 5px', borderRadius: '4px' }}>SubtleCrypto</code>).
798
+ It has zero native dependencies and runs identically in Node.js, Deno, Cloudflare Workers, and the browser.
799
+ </p>
800
+ <h2 style={{ fontFamily: 'Inter', fontWeight: 800, fontSize: '1.4rem', color: '#ffffff', marginTop: '2rem', marginBottom: '0.75rem' }}>Configuration</h2>
801
+ <CodeBlock lang="typescript">{`// jxr.config.ts
802
+ export default defineConfig({
803
+ crypto: {
804
+ enabled: true,
805
+ algorithm: 'AES-GCM', // 'AES-GCM' | 'AES-CBC'
806
+ keySize: 256, // Key size in bits
807
+ signing: true, // ECDSA P-256 manifest signing
808
+ keyDerivation: 'HKDF', // Key derivation function
809
+ },
810
+ });`}</CodeBlock>
811
+ <h2 style={{ fontFamily: 'Inter', fontWeight: 800, fontSize: '1.4rem', color: '#ffffff', marginTop: '2rem', marginBottom: '0.75rem' }}>Primitives</h2>
812
+ <div className="space-y-2">
813
+ {[
814
+ { name: 'AES-GCM-256', use: 'Module cache encryption', detail: 'Each cached module is encrypted with a unique IV. The key is derived from the project secret via HKDF.' },
815
+ { name: 'ECDSA P-256', use: 'Build manifest signing', detail: 'The build manifest is signed with an ECDSA P-256 private key. The runtime verifies the signature before serving any module.' },
816
+ { name: 'HKDF', use: 'Key derivation', detail: 'Session and cache keys are derived from a master secret using HKDF with SHA-256. Each project gets a unique derived key.' },
817
+ { name: 'SHA-256', use: 'Content addressing', detail: 'Every module object is content-addressed by its SHA-256 hash. This enables deterministic caching and integrity verification.' },
818
+ ].map((item) => (
819
+ <div key={item.name} className="jxr-card">
820
+ <div className="flex items-center justify-between mb-1">
821
+ <code style={{ fontFamily: 'JetBrains Mono', fontSize: '0.82rem', color: '#f97316', fontWeight: 700 }}>{item.name}</code>
822
+ <span style={{ fontSize: '0.72rem', color: '#22c55e', fontFamily: 'JetBrains Mono' }}>{item.use}</span>
823
+ </div>
824
+ <p style={{ fontSize: '0.8rem', color: '#6b7280', lineHeight: 1.55 }}>{item.detail}</p>
825
+ </div>
826
+ ))}
827
+ </div>
828
+ </div>
829
+ ),
830
+
831
+ 'mcp-tools': (
832
+ <div>
833
+ <h1 style={{ fontFamily: 'Inter', fontWeight: 900, fontSize: '2.2rem', color: '#ffffff', letterSpacing: '-0.02em', marginBottom: '1rem', lineHeight: 1.1 }}>MCP Tool Reference</h1>
834
+ <p style={{ color: '#9ca3af', lineHeight: 1.7, marginBottom: '1.25rem' }}>
835
+ The JXR MCP server exposes 14 tools over the Model Context Protocol. Each tool accepts a JSON input object
836
+ and returns a structured result. Tools can be called by any MCP-compatible AI agent.
837
+ </p>
838
+ <div className="space-y-3">
839
+ {[
840
+ { name: 'jxr_init', input: '{ name, template?, platform?, packageManager? }', output: 'Project scaffold path and generated files list', desc: 'Scaffold a new JXR project in the specified directory.' },
841
+ { name: 'jxr_dev', input: '{ projectPath, port?, open? }', output: 'Dev server URL and PID', desc: 'Start the JXR dev server with HMR and MoQ transport.' },
842
+ { name: 'jxr_build', input: '{ projectPath, platform?, analyze? }', output: 'Build stats, output files, and manifest path', desc: 'Run a production build and return the signed manifest.' },
843
+ { name: 'jxr_migrate', input: '{ projectPath, from?, dryRun? }', output: 'Migration report with changed files and backup path', desc: 'Migrate a project from another framework to JXR.' },
844
+ { name: 'jxr_deploy', input: '{ projectPath, target, env? }', output: 'Deployment URL and platform response', desc: 'Deploy to Cloudflare Workers, Deno Deploy, or Node.js.' },
845
+ { name: 'jxr_detect_framework', input: '{ projectPath }', output: 'Detected framework name and confidence score', desc: 'Auto-detect the source framework of an existing project.' },
846
+ { name: 'jxr_read_config', input: '{ projectPath }', output: 'Parsed jxr.config.ts as a JSON object', desc: 'Read and parse the JXR configuration file.' },
847
+ { name: 'jxr_write_config', input: '{ projectPath, config }', output: 'Updated config file path', desc: 'Write or update the jxr.config.ts file.' },
848
+ { name: 'jxr_list_files', input: '{ projectPath, pattern? }', output: 'File tree as a nested JSON object', desc: 'List all files in the project directory.' },
849
+ { name: 'jxr_read_file', input: '{ projectPath, filePath }', output: 'File contents as a string', desc: 'Read the contents of any file in the project.' },
850
+ { name: 'jxr_write_file', input: '{ projectPath, filePath, content }', output: 'Written file path', desc: 'Write or create a file in the project.' },
851
+ { name: 'jxr_add_plugin', input: '{ projectPath, plugin }', output: 'Updated package.json and config', desc: 'Add a JXR plugin and update the config.' },
852
+ { name: 'jxr_run_command', input: '{ projectPath, command }', output: 'stdout, stderr, and exit code', desc: 'Run an arbitrary shell command inside the project directory.' },
853
+ { name: 'jxr_info', input: '{ projectPath? }', output: 'Full environment and project metadata', desc: 'Get JXR version, Node version, platform, and project info.' },
854
+ ].map((tool) => (
855
+ <div key={tool.name} className="jxr-card">
856
+ <div className="flex items-center gap-2 mb-2">
857
+ <Code2 size={13} style={{ color: '#22c55e', flexShrink: 0 }} />
858
+ <code style={{ fontFamily: 'JetBrains Mono', fontSize: '0.85rem', color: '#22c55e', fontWeight: 700 }}>{tool.name}</code>
859
+ </div>
860
+ <p style={{ fontSize: '0.82rem', color: '#9ca3af', marginBottom: '0.75rem', lineHeight: 1.55 }}>{tool.desc}</p>
861
+ <div className="grid grid-cols-1 gap-1.5">
862
+ <div className="flex items-start gap-2">
863
+ <span style={{ fontFamily: 'JetBrains Mono', fontSize: '0.68rem', color: '#4b5563', flexShrink: 0, marginTop: '1px', textTransform: 'uppercase', letterSpacing: '0.1em' }}>Input</span>
864
+ <code style={{ fontFamily: 'JetBrains Mono', fontSize: '0.72rem', color: '#6b7280' }}>{tool.input}</code>
865
+ </div>
866
+ <div className="flex items-start gap-2">
867
+ <span style={{ fontFamily: 'JetBrains Mono', fontSize: '0.68rem', color: '#4b5563', flexShrink: 0, marginTop: '1px', textTransform: 'uppercase', letterSpacing: '0.1em' }}>Output</span>
868
+ <code style={{ fontFamily: 'JetBrains Mono', fontSize: '0.72rem', color: '#f97316' }}>{tool.output}</code>
869
+ </div>
870
+ </div>
871
+ </div>
872
+ ))}
873
+ </div>
874
+ </div>
875
+ ),
876
+ };
877
+
878
+ // ─── Page ─────────────────────────────────────────────────────────────────────
879
+
880
+ export default function DocsPage() {
881
+ const [activeSection, setActiveSection] = useState('introduction');
882
+ const content = DOC_CONTENT[activeSection] ?? DOC_CONTENT['introduction'];
883
+
884
+ return (
885
+ <div style={{ background: '#0a0a0a', minHeight: '100vh', display: 'flex', flexDirection: 'column' }}>
886
+ {/* Top bar */}
887
+ <header style={{ position: 'sticky', top: 0, zIndex: 50, background: 'rgba(10,10,10,0.95)', backdropFilter: 'blur(12px)', borderBottom: '1px solid rgba(255,255,255,0.06)' }}>
888
+ <div className="container flex items-center justify-between h-14">
889
+ <div className="flex items-center gap-4">
890
+ <Link href="/" className="flex items-center gap-1.5 no-underline" style={{ color: '#6b7280' }}>
891
+ <ArrowLeft size={14} />
892
+ <span style={{ fontSize: '0.85rem' }}>Back</span>
893
+ </Link>
894
+ <div style={{ width: '1px', height: '16px', background: 'rgba(255,255,255,0.08)' }} />
895
+ <div className="flex items-center gap-2">
896
+ <div className="w-6 h-6 rounded flex items-center justify-center" style={{ background: '#ea580c' }}>
897
+ <Zap size={11} color="#ffffff" strokeWidth={2.5} />
898
+ </div>
899
+ <span style={{ fontFamily: 'Inter', fontWeight: 700, color: '#ffffff', fontSize: '0.9rem' }}>JXR.js</span>
900
+ <span style={{ color: '#374151', fontSize: '0.85rem' }}>/</span>
901
+ <span style={{ color: '#6b7280', fontSize: '0.85rem' }}>docs</span>
902
+ </div>
903
+ </div>
904
+ <div className="badge-lava hidden sm:flex items-center gap-1.5">
905
+ <span className="live-dot" style={{ width: '6px', height: '6px' }} />
906
+ v1.0.0-edge
907
+ </div>
908
+ </div>
909
+ </header>
910
+
911
+ <div className="flex flex-1">
912
+ {/* Sidebar */}
913
+ <aside className="hidden md:block flex-shrink-0" style={{ width: '220px', borderRight: '1px solid rgba(255,255,255,0.06)', padding: '1.5rem 0', position: 'sticky', top: '56px', height: 'calc(100vh - 56px)', overflowY: 'auto' }}>
914
+ {NAV_SECTIONS.map((group) => (
915
+ <div key={group.title} className="mb-5">
916
+ <div style={{ padding: '0 1.25rem', marginBottom: '0.4rem', fontSize: '0.62rem', fontWeight: 700, letterSpacing: '0.15em', textTransform: 'uppercase', color: '#374151', fontFamily: 'JetBrains Mono' }}>
917
+ {group.title}
918
+ </div>
919
+ {group.items.map((item) => {
920
+ const Icon = item.icon;
921
+ return (
922
+ <button
923
+ key={item.id}
924
+ onClick={() => setActiveSection(item.id)}
925
+ className="w-full text-left flex items-center gap-2 px-4 py-2 transition-all"
926
+ style={{
927
+ background: activeSection === item.id ? 'rgba(234,88,12,0.08)' : 'transparent',
928
+ color: activeSection === item.id ? '#f97316' : '#6b7280',
929
+ borderLeft: activeSection === item.id ? '2px solid #ea580c' : '2px solid transparent',
930
+ fontFamily: 'Inter',
931
+ fontSize: '0.84rem',
932
+ }}
933
+ >
934
+ <Icon size={13} style={{ flexShrink: 0 }} />
935
+ {item.label}
936
+ </button>
937
+ );
938
+ })}
939
+ </div>
940
+ ))}
941
+ </aside>
942
+
943
+ {/* Content */}
944
+ <main className="flex-1 min-w-0 p-8 md:p-12" style={{ maxWidth: '760px' }}>
945
+ {content}
946
+ <div className="mt-12 pt-8" style={{ borderTop: '1px solid rgba(255,255,255,0.06)' }}>
947
+ <a href="https://github.com/jxrstudios/jxr" target="_blank" rel="noopener noreferrer" className="btn-lava no-underline inline-flex">
948
+ View source on GitHub <ChevronRight size={14} />
949
+ </a>
950
+ </div>
951
+ </main>
952
+ </div>
953
+ </div>
954
+ );
955
+ }