jamdesk 1.1.7 → 1.1.9

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 (43) hide show
  1. package/README.md +5 -2
  2. package/dist/lib/deps.js +3 -3
  3. package/dist/lib/openapi/types.d.ts +11 -6
  4. package/dist/lib/openapi/types.d.ts.map +1 -1
  5. package/dist/lib/path-security.d.ts +3 -0
  6. package/dist/lib/path-security.d.ts.map +1 -1
  7. package/dist/lib/path-security.js +14 -1
  8. package/dist/lib/path-security.js.map +1 -1
  9. package/dist/lib/tech-words.js +5 -5
  10. package/dist/lib/tech-words.js.map +1 -1
  11. package/package.json +13 -10
  12. package/vendored/app/[[...slug]]/page.tsx +50 -13
  13. package/vendored/app/api/assets/[...path]/route.ts +2 -0
  14. package/vendored/components/layout/LayoutWrapper.tsx +3 -4
  15. package/vendored/components/mdx/ApiEndpoint.tsx +13 -2
  16. package/vendored/components/mdx/MDXComponents.tsx +16 -0
  17. package/vendored/components/mdx/OpenApiEndpoint.tsx +76 -36
  18. package/vendored/components/mdx/Tabs.tsx +1 -1
  19. package/vendored/components/mdx/Video.tsx +82 -0
  20. package/vendored/components/navigation/Header.tsx +3 -3
  21. package/vendored/components/navigation/Sidebar.tsx +3 -3
  22. package/vendored/components/ui/CodePanel.tsx +5 -5
  23. package/vendored/components/ui/CodePanelModal.tsx +3 -3
  24. package/vendored/components/ui/DevOnlyNotice.tsx +78 -0
  25. package/vendored/hooks/useChatPanel.tsx +21 -2
  26. package/vendored/hooks/useMediaQuery.ts +27 -0
  27. package/vendored/lib/build-endpoint-from-mdx.ts +66 -0
  28. package/vendored/lib/isr-build-executor.ts +1 -1
  29. package/vendored/lib/middleware-helpers.ts +26 -1
  30. package/vendored/lib/openapi/code-examples.ts +479 -99
  31. package/vendored/lib/openapi/index.ts +9 -1
  32. package/vendored/lib/openapi/types.ts +29 -5
  33. package/vendored/lib/preprocess-mdx.ts +103 -36
  34. package/vendored/lib/process-mdx-with-exports.ts +22 -14
  35. package/vendored/lib/remark-extract-param-fields.ts +134 -0
  36. package/vendored/lib/shiki-client.ts +12 -0
  37. package/vendored/lib/static-artifacts.ts +2 -1
  38. package/vendored/lib/url-safety.ts +122 -0
  39. package/vendored/next.config.js +8 -0
  40. package/vendored/schema/docs-schema.json +16 -3
  41. package/vendored/scripts/copy-files.cjs +60 -54
  42. package/vendored/scripts/validate-links.cjs +1 -1
  43. package/vendored/shared/path-security.ts +17 -1
package/README.md CHANGED
@@ -1,8 +1,10 @@
1
1
  # Jamdesk CLI
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/jamdesk)](https://www.npmjs.com/package/jamdesk)
4
+ [![npm downloads](https://img.shields.io/npm/dm/jamdesk)](https://www.npmjs.com/package/jamdesk)
4
5
  [![Node.js](https://img.shields.io/node/v/jamdesk)](https://nodejs.org)
5
6
  [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](./LICENSE)
7
+ [![Claude Code](https://img.shields.io/badge/Claude_Code-skills-blueviolet?logo=anthropic)](https://www.jamdesk.com/docs/claude-code)
6
8
 
7
9
  CLI for [Jamdesk](https://www.jamdesk.com) — build, preview, and deploy documentation sites from MDX.
8
10
 
@@ -32,7 +34,7 @@ Your docs are at **http://localhost:3000**. That's it.
32
34
 
33
35
  ## Installation
34
36
 
35
- ### npm (recommended)
37
+ ### [npm](https://www.npmjs.com/package/jamdesk) (recommended)
36
38
 
37
39
  ```bash
38
40
  npm install -g jamdesk
@@ -222,7 +224,7 @@ Found 3 misspellings across 24 pages.
222
224
  Tip: Run "jamdesk spellcheck --fix" to interactively fix or ignore words.
223
225
  ```
224
226
 
225
- Uses an English dictionary with 150+ built-in tech terms (API, GraphQL, Kubernetes, etc.) so common jargon doesn't flag. Add project-specific words to `docs.json`:
227
+ Uses an English dictionary with 150+ built-in tech terms (API, GraphQL, Kubernetes, etc.) so common jargon doesn't flag. Currently English only — multi-language support is planned. Add project-specific words to `docs.json`:
226
228
 
227
229
  ```json
228
230
  {
@@ -429,6 +431,7 @@ See the [docs.json reference](https://www.jamdesk.com/docs/config/docs-json-refe
429
431
  - [Config Reference](https://www.jamdesk.com/docs/config/docs-json-reference)
430
432
  - [OpenAPI](https://www.jamdesk.com/docs/api-reference/openapi-setup)
431
433
  - [Deployment](https://www.jamdesk.com/docs/deploy)
434
+ - [npm Package](https://www.npmjs.com/package/jamdesk)
432
435
  - [Homepage](https://www.jamdesk.com)
433
436
  - [Pricing](https://www.jamdesk.com/pricing)
434
437
 
package/dist/lib/deps.js CHANGED
@@ -54,9 +54,9 @@ const REQUIRED_DEPS = {
54
54
  'remark-math': '^6.0.0',
55
55
  'remark-smartypants': '^3.0.2',
56
56
  // Math/LaTeX rendering
57
- 'katex': '^0.16.34',
57
+ 'katex': '^0.16.44',
58
58
  // Diagrams
59
- 'mermaid': '^11.12.2',
59
+ 'mermaid': '^11.14.0',
60
60
  // YAML parsing (for OpenAPI specs)
61
61
  'js-yaml': '^4.1.1',
62
62
  // Schema validation
@@ -81,7 +81,7 @@ const REQUIRED_DEPS = {
81
81
  'json5': '^2.2.3',
82
82
  'glob': '^13.0.6',
83
83
  // TypeScript (needed for Next.js to avoid auto-install breaking symlink)
84
- 'typescript': '^5.3.3',
84
+ 'typescript': '^6.0.2',
85
85
  '@types/node': '^25.5.0',
86
86
  '@types/react': '^19.2.14',
87
87
  '@types/react-dom': '^19.0.0',
@@ -168,12 +168,17 @@ export interface ValidationResult {
168
168
  error?: OpenApiValidationError;
169
169
  }
170
170
  /**
171
- * Generated code examples
172
- */
173
- export interface CodeExamples {
174
- curl: string;
175
- python: string;
176
- javascript: string;
171
+ * Single code example for a specific language
172
+ */
173
+ export interface CodeExample {
174
+ /** Language identifier (e.g., 'curl', 'python', 'go') */
175
+ id: string;
176
+ /** Display label for the tab (e.g., 'cURL', 'Python', 'Go') */
177
+ label: string;
178
+ /** Shiki language ID for syntax highlighting (e.g., 'bash', 'python', 'go') */
179
+ language: string;
180
+ /** Generated code string */
181
+ code: string;
177
182
  }
178
183
  /**
179
184
  * Generated page from auto-generation
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/lib/openapi/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/lib/openapi/types.ts"],"names":[],"mappings":"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"}
@@ -9,6 +9,9 @@
9
9
  /**
10
10
  * Check if a path stays within the project directory.
11
11
  * Returns true if path is within project, false otherwise.
12
+ *
13
+ * Rejects null bytes, URL-encoded sequences, and normalizes
14
+ * backslashes to prevent traversal via encoding tricks.
12
15
  */
13
16
  export declare function isPathWithinProject(filePath: string, projectDir: string): boolean;
14
17
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"path-security.d.ts","sourceRoot":"","sources":["../../src/lib/path-security.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAKjF;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAIpF;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAGtF"}
1
+ {"version":3,"file":"path-security.d.ts","sourceRoot":"","sources":["../../src/lib/path-security.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAkBjF;AAED;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAIpF;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAGtF"}
@@ -10,9 +10,22 @@ import path from 'path';
10
10
  /**
11
11
  * Check if a path stays within the project directory.
12
12
  * Returns true if path is within project, false otherwise.
13
+ *
14
+ * Rejects null bytes, URL-encoded sequences, and normalizes
15
+ * backslashes to prevent traversal via encoding tricks.
13
16
  */
14
17
  export function isPathWithinProject(filePath, projectDir) {
15
- const absolutePath = path.resolve(projectDir, filePath);
18
+ // Reject null bytes (real or URL-encoded)
19
+ if (filePath.includes('\0') || filePath.includes('%00')) {
20
+ return false;
21
+ }
22
+ // Reject URL-encoded path separators and traversal sequences
23
+ if (/%2f/i.test(filePath) || /%5c/i.test(filePath)) {
24
+ return false;
25
+ }
26
+ // Normalize backslashes to forward slashes to prevent Windows-style traversal
27
+ const normalized = filePath.replace(/\\/g, '/');
28
+ const absolutePath = path.resolve(projectDir, normalized);
16
29
  const normalizedProject = path.resolve(projectDir);
17
30
  return absolutePath.startsWith(normalizedProject + path.sep) || absolutePath === normalizedProject;
18
31
  }
@@ -1 +1 @@
1
- {"version":3,"file":"path-security.js","sourceRoot":"","sources":["../../src/lib/path-security.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,QAAgB,EAAE,UAAkB;IACtE,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;IACxD,MAAM,iBAAiB,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAEnD,OAAO,YAAY,CAAC,UAAU,CAAC,iBAAiB,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,YAAY,KAAK,iBAAiB,CAAC;AACrG,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,yBAAyB,CAAC,QAAgB,EAAE,UAAkB;IAC5E,IAAI,CAAC,mBAAmB,CAAC,QAAQ,EAAE,UAAU,CAAC,EAAE,CAAC;QAC/C,MAAM,IAAI,KAAK,CAAC,mCAAmC,QAAQ,EAAE,CAAC,CAAC;IACjE,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAY,EAAE,EAAU,EAAE,UAAkB;IAC9E,yBAAyB,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAC5C,yBAAyB,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;AAC5C,CAAC"}
1
+ {"version":3,"file":"path-security.js","sourceRoot":"","sources":["../../src/lib/path-security.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CAAC,QAAgB,EAAE,UAAkB;IACtE,0CAA0C;IAC1C,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACxD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,6DAA6D;IAC7D,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;QACnD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,8EAA8E;IAC9E,MAAM,UAAU,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAEhD,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;IAC1D,MAAM,iBAAiB,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAEnD,OAAO,YAAY,CAAC,UAAU,CAAC,iBAAiB,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,YAAY,KAAK,iBAAiB,CAAC;AACrG,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,yBAAyB,CAAC,QAAgB,EAAE,UAAkB;IAC5E,IAAI,CAAC,mBAAmB,CAAC,QAAQ,EAAE,UAAU,CAAC,EAAE,CAAC;QAC/C,MAAM,IAAI,KAAK,CAAC,mCAAmC,QAAQ,EAAE,CAAC,CAAC;IACjE,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAY,EAAE,EAAU,EAAE,UAAkB;IAC9E,yBAAyB,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAC5C,yBAAyB,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;AAC5C,CAAC"}
@@ -20,7 +20,7 @@ export const TECH_WORDS = [
20
20
  'HMAC', 'TLS', 'SSL', 'SSH', 'DNS', 'CDN',
21
21
  'iframe', 'iframes',
22
22
  // HTML attributes (leak through from multi-line JSX)
23
- 'href', 'src', 'img', 'autoplay',
23
+ 'href', 'src', 'img', 'autoplay', 'unmuted',
24
24
  // Tools & platforms
25
25
  'npm', 'npx', 'pnpm', 'yarn', 'Webpack', 'Vite', 'Turbopack',
26
26
  'ESLint', 'Prettier', 'Vitest', 'Jest', 'Mocha',
@@ -50,7 +50,7 @@ export const TECH_WORDS = [
50
50
  'frontend', 'backend', 'fullstack', 'dev', 'DevOps', 'CI', 'CD',
51
51
  'regex', 'cron', 'config', 'configs', 'env', 'changelog', 'changelogs',
52
52
  'metadata', 'serializer', 'deserializer',
53
- 'boolean', 'param', 'params', 'args', 'kwargs',
53
+ 'boolean', 'param', 'params', 'args', 'kwargs', 'func', 'fmt', 'req', 'usr',
54
54
  'namespace', 'namespaces', 'enum', 'enums',
55
55
  'nullable', 'nonnull',
56
56
  'README', 'TODO', 'FIXME',
@@ -58,7 +58,7 @@ export const TECH_WORDS = [
58
58
  'pre', 'preconfigured', 'prebuilt', 'presigned',
59
59
  'uncomment', 'uncommented',
60
60
  'whitelist', 'blocklist', 'allowlist', 'denylist',
61
- 'repo', 'repos', 'subpath', 'subgraph', 'subdirectory', 'subdirectories',
61
+ 'repo', 'repos', 'subpath', 'subgraph', 'subgraphs', 'subdirectory', 'subdirectories',
62
62
  'dropdown', 'navbar', 'sidebar', 'tooltip', 'tooltips', 'favicon', 'favicons',
63
63
  'callout', 'callouts', 'walkthrough', 'walkthroughs', 'onboarding',
64
64
  'frontmatter', 'schemas', 'proxying', 'proxied', 'debounced', 'debounce',
@@ -86,7 +86,7 @@ export const TECH_WORDS = [
86
86
  // Common docs terms
87
87
  'Mintlify', 'Docusaurus', 'auth', 'authenticator',
88
88
  'validator', 'validators', 'const', 'init', 'parsers',
89
- 'Cmd', 'Ctrl', 'Duotone',
89
+ 'Cmd', 'Ctrl', 'Duotone', 'Squoosh', 'TOC', 'whoami',
90
90
  'Vimeo', 'Anthropic', 'Shiki', 'Catppuccin',
91
91
  'Pandoc', 'Caddy', 'Traefik', 'HAProxy',
92
92
  'scannable', 'linter', 'checkmark', 'checkboxes',
@@ -110,7 +110,7 @@ export const TECH_WORDS = [
110
110
  'IPv4', 'IPv6', 'TCP', 'UDP',
111
111
  'UUID', 'GUID', 'BASE64', 'UTF',
112
112
  'LLM', 'LLMs', 'GPT', 'RAG',
113
- 'idempotent', 'idempotency',
113
+ 'idempotent', 'idempotency', 'cardinality',
114
114
  'CAPTCHA', 'RGBA', 'RGB', 'DOM',
115
115
  'USD', 'GBP',
116
116
  'LTS', 'OG',
@@ -1 +1 @@
1
- {"version":3,"file":"tech-words.js","sourceRoot":"","sources":["../../src/lib/tech-words.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tech-words.js","sourceRoot":"","sources":["../../src/lib/tech-words.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,36 +1,39 @@
1
1
  {
2
2
  "name": "jamdesk",
3
- "version": "1.1.7",
3
+ "version": "1.1.9",
4
4
  "description": "CLI for Jamdesk — build, preview, and deploy documentation sites from MDX. Dev server with hot reload, 50+ components, OpenAPI support, AI search, and Mintlify migration",
5
5
  "keywords": [
6
6
  "jamdesk",
7
7
  "documentation",
8
8
  "documentation-generator",
9
9
  "documentation-platform",
10
+ "documentation-tool",
10
11
  "docs",
11
12
  "docs-as-code",
13
+ "docs-generator",
12
14
  "mdx",
13
15
  "markdown",
14
16
  "cli",
15
- "dev-server",
16
- "hot-reload",
17
- "turbopack",
18
17
  "developer-tools",
19
18
  "api-documentation",
20
19
  "openapi",
21
20
  "api-reference",
22
- "static-site",
21
+ "static-site-generator",
23
22
  "nextjs",
23
+ "react",
24
+ "typescript",
24
25
  "technical-writing",
25
26
  "mintlify",
26
27
  "mintlify-alternative",
28
+ "docusaurus-alternative",
29
+ "gitbook-alternative",
27
30
  "documentation-hosting",
28
31
  "documentation-site",
29
32
  "developer-documentation",
30
33
  "api-docs",
31
- "react-components",
32
34
  "docs-site-generator",
33
- "ai-search"
35
+ "ai-search",
36
+ "llms-txt"
34
37
  ],
35
38
  "homepage": "https://www.jamdesk.com",
36
39
  "bugs": {
@@ -44,7 +47,7 @@
44
47
  "license": "Apache-2.0",
45
48
  "author": {
46
49
  "name": "Jamdesk",
47
- "email": "hello@jamdesk.com",
50
+ "email": "support@jamdesk.com",
48
51
  "url": "https://www.jamdesk.com"
49
52
  },
50
53
  "type": "module",
@@ -113,8 +116,8 @@
113
116
  "@mdx-js/mdx": "^3.1.1",
114
117
  "@types/fs-extra": "^11.0.0",
115
118
  "@types/node": "^25.5.0",
116
- "typescript": "^5.3.0",
117
- "vitest": "^4.1.0"
119
+ "typescript": "^6.0.2",
120
+ "vitest": "^4.1.2"
118
121
  },
119
122
  "engines": {
120
123
  "node": ">=20.0.0"
@@ -42,6 +42,7 @@ import { getLatexRemarkPlugins, getLatexRehypePlugins } from '@/lib/latex-config
42
42
  import { getTypographyRemarkPlugins } from '@/lib/typography-config';
43
43
  import { recmaCompoundComponents } from '@/lib/recma-compound-components';
44
44
  import { extractInlineComponents } from '@/lib/process-mdx-with-exports';
45
+ import { buildEndpointFromMdx } from '@/lib/build-endpoint-from-mdx';
45
46
  import { mdxSecurityOptions } from '@/lib/mdx-security-options';
46
47
  import fs from 'fs';
47
48
  import path from 'path';
@@ -67,7 +68,7 @@ import {
67
68
  generateCodeExamples,
68
69
  formatOpenApiWarning,
69
70
  type OpenApiEndpointData,
70
- type CodeExamples,
71
+ type CodeExample,
71
72
  type AuthMethod,
72
73
  } from '@/lib/openapi';
73
74
  import { ApiEndpoint } from '@/components/mdx/ApiEndpoint';
@@ -134,6 +135,7 @@ interface FrontmatterData {
134
135
  description?: string;
135
136
  api?: string;
136
137
  openapi?: string;
138
+ playground?: string;
137
139
  mode?: string;
138
140
  hideFooter?: boolean;
139
141
  rss?: boolean;
@@ -505,7 +507,7 @@ export default async function DocPage({ params }: PageProps) {
505
507
 
506
508
  // Extract and compile inline component exports from MDX
507
509
  // Only pass MDXComponents (server-compatible) to inline extraction
508
- const { inlineComponents } = await extractInlineComponents(content, MDXComponents);
510
+ const { inlineComponents, paramFields } = await extractInlineComponents(content, MDXComponents);
509
511
 
510
512
  // Check for component name collisions and warn
511
513
  const overriddenComponents = Object.keys(inlineComponents).filter(
@@ -560,7 +562,7 @@ export default async function DocPage({ params }: PageProps) {
560
562
 
561
563
  // Parse OpenAPI endpoint data if openapi frontmatter is present
562
564
  let openApiEndpointData: OpenApiEndpointData | null = null;
563
- let openApiCodeExamples: CodeExamples | null = null;
565
+ let openApiCodeExamples: CodeExample[] | null = null;
564
566
 
565
567
  // OpenAPI spec parsing - supports both static and ISR modes
566
568
  if (data.openapi && typeof data.openapi === 'string') {
@@ -591,7 +593,8 @@ export default async function DocPage({ params }: PageProps) {
591
593
 
592
594
  // Generate code examples
593
595
  const authMethod = config.api?.mdx?.auth?.method as AuthMethod | undefined;
594
- openApiCodeExamples = generateCodeExamples(openApiEndpointData, { authMethod });
596
+ const languages = config.api?.examples?.languages;
597
+ openApiCodeExamples = generateCodeExamples(openApiEndpointData, { authMethod, languages });
595
598
  } catch (err) {
596
599
  // Log formatted warning to console (appears in CLI and build logs)
597
600
  // Check if it's an OpenAPI validation error with our format
@@ -607,16 +610,12 @@ export default async function DocPage({ params }: PageProps) {
607
610
  // Parse MDX api field for pages with api: frontmatter (but not openapi:)
608
611
  let mdxApiMethod: HttpMethod | null = null;
609
612
  let mdxApiPath: string | null = null;
610
- let mdxApiBaseUrl: string | undefined;
611
613
 
612
614
  if (data.api && typeof data.api === 'string' && !data.openapi) {
613
615
  const parsed = parseMdxApiField(data.api);
614
616
  if (parsed) {
615
617
  mdxApiMethod = parsed.method;
616
618
  mdxApiPath = parsed.path;
617
- // Get server URL from config, with fallback
618
- const serverConfig = config.api?.mdx?.server;
619
- mdxApiBaseUrl = Array.isArray(serverConfig) ? serverConfig[0] : serverConfig;
620
619
  }
621
620
  }
622
621
 
@@ -644,6 +643,25 @@ export default async function DocPage({ params }: PageProps) {
644
643
  // Prose class for MDX content styling (defined in base.css)
645
644
  const proseClasses = 'prose max-w-none';
646
645
 
646
+ // Playground configuration — covers both openapi: and api: pages
647
+ const hasApiEndpoint = openApiEndpointData || (mdxApiMethod && mdxApiPath);
648
+ const playgroundDisplay = hasApiEndpoint
649
+ ? ((data.playground as 'interactive' | 'simple' | 'none' | undefined)
650
+ || config.api?.playground?.display || 'interactive') as 'interactive' | 'simple' | 'none'
651
+ : 'none';
652
+ const mdxServerConfig = config.api?.mdx?.server;
653
+ const fallbackServerUrl = Array.isArray(mdxServerConfig) ? mdxServerConfig[0] : mdxServerConfig;
654
+ // Force proxy on hostAtDocs sites — direct mode is always cross-origin there
655
+ const proxyEnabled = hostAtDocs
656
+ || config.api?.playground?.proxy
657
+ || (config.api?.playground?.proxy == null && playgroundDisplay === 'interactive');
658
+
659
+ // Build endpoint data for api: pages (for playground)
660
+ let mdxEndpointData: OpenApiEndpointData | undefined;
661
+ if (!openApiEndpointData && mdxApiMethod && mdxApiPath && playgroundDisplay !== 'none') {
662
+ mdxEndpointData = buildEndpointFromMdx(mdxApiMethod, mdxApiPath, paramFields, fallbackServerUrl);
663
+ }
664
+
647
665
  // For API pages, wrap the entire content area with ApiPageWrapper
648
666
  // so code panels can be positioned as siblings at the page level
649
667
  if (isApiPage) {
@@ -676,11 +694,24 @@ export default async function DocPage({ params }: PageProps) {
676
694
  <div className={proseClasses}>
677
695
  {/* MDX API endpoint badge (for pages with api: frontmatter) */}
678
696
  {mdxApiMethod && mdxApiPath && (
679
- <ApiEndpoint
680
- method={mdxApiMethod}
681
- path={mdxApiPath}
682
- baseUrl={mdxApiBaseUrl}
683
- />
697
+ mdxEndpointData && playgroundDisplay !== 'none' ? (
698
+ <OpenApiEndpoint
699
+ endpoint={mdxEndpointData}
700
+ playgroundOnly
701
+ playgroundDisplay={playgroundDisplay}
702
+ authMethod={config.api?.mdx?.auth?.method as AuthMethod | undefined}
703
+ authHeaderName={config.api?.mdx?.auth?.name}
704
+ serverUrl={fallbackServerUrl}
705
+ proxyEnabled={proxyEnabled}
706
+ languages={config.api?.examples?.languages}
707
+ />
708
+ ) : (
709
+ <ApiEndpoint
710
+ method={mdxApiMethod}
711
+ path={mdxApiPath}
712
+ baseUrl={fallbackServerUrl}
713
+ />
714
+ )
684
715
  )}
685
716
 
686
717
  {/* OpenAPI endpoint documentation (auto-generated from spec) */}
@@ -688,6 +719,12 @@ export default async function DocPage({ params }: PageProps) {
688
719
  <OpenApiEndpoint
689
720
  endpoint={openApiEndpointData}
690
721
  codeExamples={openApiCodeExamples || undefined}
722
+ playgroundDisplay={playgroundDisplay}
723
+ authMethod={config.api?.mdx?.auth?.method as AuthMethod | undefined}
724
+ authHeaderName={config.api?.mdx?.auth?.name}
725
+ serverUrl={fallbackServerUrl}
726
+ proxyEnabled={proxyEnabled}
727
+ languages={config.api?.examples?.languages}
691
728
  />
692
729
  )}
693
730
 
@@ -18,6 +18,8 @@ const CACHE_DURATIONS: Record<string, number> = {
18
18
  'image/svg+xml': 86400, // 1 day (may change)
19
19
  'image/x-icon': 31536000,
20
20
  'application/pdf': 86400,
21
+ 'video/mp4': 31536000, // 1 year (busted by ?v= query param on new builds)
22
+ 'video/webm': 31536000,
21
23
  default: 3600, // 1 hour
22
24
  };
23
25
 
@@ -37,10 +37,9 @@ function useMediaQuery(query: string): boolean {
37
37
 
38
38
  export function LayoutWrapper({ config, children }: LayoutWrapperProps) {
39
39
  const [isSidebarOpen, setIsSidebarOpen] = useState(false);
40
- // Chat is on by default in production; projects can opt out with chat.enabled: false.
41
- // Hidden in local dev the chat API route needs Upstash Vector + Anthropic API.
42
- const chatEnabled = process.env.NODE_ENV === 'production'
43
- && (config.chat?.enabled !== false);
40
+ // Chat button is shown in both dev and production so the layout matches.
41
+ // In dev mode, clicking it shows a "production only" notice instead of opening the panel.
42
+ const chatEnabled = config.chat?.enabled !== false;
44
43
 
45
44
  // xl breakpoint (1280px) — chat renders inline on desktop, overlay on mobile
46
45
  const isDesktop = useMediaQuery('(min-width: 1280px)');
@@ -6,6 +6,7 @@ interface ApiEndpointProps {
6
6
  method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS' | 'TRACE';
7
7
  path: string;
8
8
  baseUrl?: string;
9
+ onTryIt?: () => void;
9
10
  }
10
11
 
11
12
  const methodColors: Record<string, { bg: string; text: string; border: string }> = {
@@ -51,7 +52,7 @@ const methodColors: Record<string, { bg: string; text: string; border: string }>
51
52
  },
52
53
  };
53
54
 
54
- export function ApiEndpoint({ method, path, baseUrl = 'https://api.jamdesk.com/api' }: ApiEndpointProps) {
55
+ export function ApiEndpoint({ method, path, baseUrl = 'https://api.jamdesk.com/api', onTryIt }: ApiEndpointProps) {
55
56
  const [copied, setCopied] = useState(false);
56
57
  const colors = methodColors[method] || methodColors.GET;
57
58
  const fullUrl = `${baseUrl}${path}`;
@@ -73,10 +74,20 @@ export function ApiEndpoint({ method, path, baseUrl = 'https://api.jamdesk.com/a
73
74
  <span className="text-[var(--color-text-muted)]">{baseUrl}</span>
74
75
  <span className="text-[var(--color-text-primary)]">{path}</span>
75
76
  </span>
77
+ {/* Try it button */}
78
+ {onTryIt && (
79
+ <button
80
+ onClick={onTryIt}
81
+ className="px-2.5 py-1 text-xs font-medium rounded-md bg-gradient-to-r from-[var(--color-accent)] to-[var(--color-accent-hover,var(--color-accent))] text-white hover:opacity-90 transition-opacity cursor-pointer"
82
+ aria-label="Open API playground"
83
+ >
84
+ Try it
85
+ </button>
86
+ )}
76
87
  {/* Copy button */}
77
88
  <button
78
89
  onClick={handleCopy}
79
- className="p-1.5 text-[var(--color-text-muted)] hover:text-[var(--color-text-primary)] hover:bg-[var(--color-bg-secondary)] rounded-md transition-colors"
90
+ className="p-1.5 text-[var(--color-text-muted)] hover:text-[var(--color-text-primary)] hover:bg-[var(--color-bg-secondary)] rounded-md transition-colors cursor-pointer"
80
91
  title="Copy endpoint URL"
81
92
  aria-label="Copy endpoint URL"
82
93
  >
@@ -30,6 +30,7 @@ import { Tree, TreeFolder, TreeFile } from './Tree';
30
30
  import { Columns } from './Columns';
31
31
  import { View, ViewProvider, ViewSelector, ViewWrapper } from './View';
32
32
  import { YouTube } from './YouTube';
33
+ import { Video } from './Video';
33
34
 
34
35
  /**
35
36
  * Extract language from a pre element for tab label
@@ -148,6 +149,14 @@ function HttpCodeBlock({ method, url }: { method: string; url: string }) {
148
149
  );
149
150
  }
150
151
 
152
+ /** Fallback for raw <img src="video.mp4"> in MDX (preprocessor handles markdown syntax) */
153
+ const VIDEO_EXTENSIONS_IMG = ['.mp4', '.webm'];
154
+ function isVideoUrl(src: string | undefined): boolean {
155
+ if (!src) return false;
156
+ const pathOnly = src.split('?')[0];
157
+ return VIDEO_EXTENSIONS_IMG.some(ext => pathOnly.toLowerCase().endsWith(ext));
158
+ }
159
+
151
160
  export const MDXComponents = {
152
161
  Card,
153
162
  // Callout components
@@ -218,6 +227,8 @@ export const MDXComponents = {
218
227
  ViewWrapper,
219
228
  // Media embeds
220
229
  YouTube,
230
+ // Video player for local video files
231
+ Video,
221
232
  // Sized images from preprocess-mdx (![alt](url =WIDTHx) syntax).
222
233
  // These are output as <SizedImage> JSX so they go through component mapping
223
234
  // (raw <img> JSX in MDX bypasses the components provider).
@@ -253,6 +264,11 @@ export const MDXComponents = {
253
264
  // Destructure and ignore any other props to prevent them from being passed to DOM
254
265
  ...rest
255
266
  }: any) => {
267
+ // Check if this is a video file — render <Video> instead of <ZoomableImage>
268
+ if (isVideoUrl(src)) {
269
+ return <Video src={src} title={alt || undefined} />;
270
+ }
271
+
256
272
  // Check for data-no-zoom attribute or noZoom prop (handle both camelCase and lowercase)
257
273
  const disableZoom = dataNoZoom === 'true' || dataNoZoom === true ||
258
274
  noZoom === true || noZoom === 'true' ||