create-fumadocs-app 16.0.5 → 16.0.6
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/dist/bin.js +2 -2
- package/dist/{chunk-F7NHHEKG.js → chunk-PGCMK5N3.js} +1 -1
- package/dist/{chunk-XPRRZX4H.js → chunk-QKIRNPKF.js} +10 -3
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -2
- package/dist/plugins/biome.js +1 -1
- package/dist/plugins/eslint.js +1 -1
- package/dist/plugins/orama-cloud.js +7 -5
- package/package.json +2 -2
- package/template/+next+fuma-docs-mdx/package.json +3 -3
- package/template/+next+fuma-docs-mdx/tsconfig.json +8 -2
- package/template/react-router/package.json +3 -3
- package/template/react-router-spa/package.json +4 -4
- package/template/tanstack-start/content/docs/index.mdx +1 -1
- package/template/tanstack-start/package.json +8 -8
- package/template/tanstack-start/src/routes/docs/$.tsx +26 -19
- package/template/tanstack-start-spa/README.md +12 -0
- package/template/tanstack-start-spa/content/docs/index.mdx +34 -0
- package/template/tanstack-start-spa/content/docs/test.mdx +12 -0
- package/template/tanstack-start-spa/example.gitignore +19 -0
- package/template/tanstack-start-spa/package.json +38 -0
- package/template/tanstack-start-spa/source.config.ts +7 -0
- package/template/tanstack-start-spa/src/components/not-found.tsx +28 -0
- package/template/tanstack-start-spa/src/components/search.tsx +51 -0
- package/template/tanstack-start-spa/src/lib/layout.shared.tsx +9 -0
- package/template/tanstack-start-spa/src/lib/source.ts +15 -0
- package/template/tanstack-start-spa/src/router.tsx +12 -0
- package/template/tanstack-start-spa/src/routes/__root.tsx +51 -0
- package/template/tanstack-start-spa/src/routes/api/search.ts +16 -0
- package/template/tanstack-start-spa/src/routes/docs/$.tsx +109 -0
- package/template/tanstack-start-spa/src/routes/index.tsx +24 -0
- package/template/tanstack-start-spa/src/styles/app.css +3 -0
- package/template/tanstack-start-spa/tsconfig.json +24 -0
- package/template/tanstack-start-spa/vite.config.ts +39 -0
- package/template/waku/package.json +4 -4
package/dist/bin.js
CHANGED
|
@@ -3,11 +3,11 @@ import {
|
|
|
3
3
|
create,
|
|
4
4
|
getPackageManager,
|
|
5
5
|
managers
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-PGCMK5N3.js";
|
|
7
7
|
import {
|
|
8
8
|
isCI,
|
|
9
9
|
templates
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-QKIRNPKF.js";
|
|
11
11
|
|
|
12
12
|
// src/bin.ts
|
|
13
13
|
import fs from "fs/promises";
|
|
@@ -94,14 +94,14 @@ import { fileURLToPath } from "url";
|
|
|
94
94
|
// ../create-app-versions/package.json
|
|
95
95
|
var package_default = {
|
|
96
96
|
name: "create-fumadocs-versions",
|
|
97
|
-
version: "16.0.
|
|
97
|
+
version: "16.0.6",
|
|
98
98
|
private: true,
|
|
99
99
|
description: "Used to track dependency versions in create-fumadocs-app",
|
|
100
100
|
dependencies: {
|
|
101
|
-
|
|
102
|
-
"@biomejs/biome": "^2.2.6",
|
|
101
|
+
"@biomejs/biome": "^2.3.1",
|
|
103
102
|
"@eslint/eslintrc": "^3.3.1",
|
|
104
103
|
"@orama/core": "^1.2.13",
|
|
104
|
+
eslint: "^9.38.0",
|
|
105
105
|
"fumadocs-core": "workspace:*",
|
|
106
106
|
"fumadocs-mdx": "workspace:*",
|
|
107
107
|
"fumadocs-ui": "workspace:*"
|
|
@@ -143,6 +143,13 @@ var templates = [
|
|
|
143
143
|
label: "Tanstack Start: Fumadocs MDX (not RSC)",
|
|
144
144
|
appDir: "src",
|
|
145
145
|
rootProviderPath: "routes/__root.tsx"
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
value: "tanstack-start-spa",
|
|
149
|
+
label: "Tanstack Start SPA: Fumadocs MDX (not RSC)",
|
|
150
|
+
hint: "SPA mode allows you to host the site statically, compatible with a CDN.",
|
|
151
|
+
appDir: "src",
|
|
152
|
+
rootProviderPath: "routes/__root.tsx"
|
|
146
153
|
}
|
|
147
154
|
];
|
|
148
155
|
var depVersions = package_default.dependencies;
|
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ type PackageManager = (typeof managers)[number];
|
|
|
2
2
|
declare const managers: readonly ["npm", "yarn", "bun", "pnpm"];
|
|
3
3
|
|
|
4
4
|
interface TemplateInfo {
|
|
5
|
-
value: '+next+fuma-docs-mdx' | 'waku' | 'react-router' | 'react-router-spa' | 'tanstack-start';
|
|
5
|
+
value: '+next+fuma-docs-mdx' | 'waku' | 'react-router' | 'react-router-spa' | 'tanstack-start' | 'tanstack-start-spa';
|
|
6
6
|
label: string;
|
|
7
7
|
appDir: string;
|
|
8
8
|
/**
|
package/dist/index.js
CHANGED
package/dist/plugins/biome.js
CHANGED
package/dist/plugins/eslint.js
CHANGED
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
pick,
|
|
5
5
|
sourceDir,
|
|
6
6
|
writeFile
|
|
7
|
-
} from "../chunk-
|
|
7
|
+
} from "../chunk-QKIRNPKF.js";
|
|
8
8
|
|
|
9
9
|
// src/plugins/orama-cloud.ts
|
|
10
10
|
import path2 from "path";
|
|
@@ -148,11 +148,12 @@ async function rootProvider({ appDir, template }, fn) {
|
|
|
148
148
|
name: "search",
|
|
149
149
|
initializer: "{{ SearchDialog }}"
|
|
150
150
|
});
|
|
151
|
+
file.addImportDeclaration({
|
|
152
|
+
moduleSpecifier: specifier,
|
|
153
|
+
defaultImport: "SearchDialog"
|
|
154
|
+
});
|
|
155
|
+
break;
|
|
151
156
|
}
|
|
152
|
-
file.addImportDeclaration({
|
|
153
|
-
moduleSpecifier: specifier,
|
|
154
|
-
defaultImport: "SearchDialog"
|
|
155
|
-
});
|
|
156
157
|
}
|
|
157
158
|
});
|
|
158
159
|
await file.save();
|
|
@@ -286,6 +287,7 @@ See https://fumadocs.dev/docs/headless/search/orama-cloud for integrating Orama
|
|
|
286
287
|
const filePath = {
|
|
287
288
|
"+next+fuma-docs-mdx": ".next/server/app/static.json.body",
|
|
288
289
|
"tanstack-start": ".output/public/static.json",
|
|
290
|
+
"tanstack-start-spa": "dist/client/static.json",
|
|
289
291
|
"react-router": "build/client/static.json",
|
|
290
292
|
"react-router-spa": "build/client/static.json",
|
|
291
293
|
waku: "dist/public/static.json"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-fumadocs-app",
|
|
3
|
-
"version": "16.0.
|
|
3
|
+
"version": "16.0.6",
|
|
4
4
|
"description": "Create a new documentation site with Fumadocs",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@clack/prompts": "^0.11.0",
|
|
34
34
|
"@commander-js/extra-typings": "^14.0.0",
|
|
35
|
-
"commander": "^14.0.
|
|
35
|
+
"commander": "^14.0.2",
|
|
36
36
|
"picocolors": "^1.1.1",
|
|
37
37
|
"tinyexec": "^1.0.1",
|
|
38
38
|
"ts-morph": "^27.0.2"
|
|
@@ -11,19 +11,19 @@
|
|
|
11
11
|
"fumadocs-core": "workspace:*",
|
|
12
12
|
"fumadocs-mdx": "workspace:*",
|
|
13
13
|
"fumadocs-ui": "workspace:*",
|
|
14
|
-
"lucide-react": "^0.
|
|
14
|
+
"lucide-react": "^0.548.0",
|
|
15
15
|
"next": "16.0.0",
|
|
16
16
|
"react": "^19.2.0",
|
|
17
17
|
"react-dom": "^19.2.0"
|
|
18
18
|
},
|
|
19
19
|
"devDependencies": {
|
|
20
|
-
"@tailwindcss/postcss": "^4.1.
|
|
20
|
+
"@tailwindcss/postcss": "^4.1.16",
|
|
21
21
|
"@types/mdx": "^2.0.13",
|
|
22
22
|
"@types/node": "^24.9.1",
|
|
23
23
|
"@types/react": "^19.2.2",
|
|
24
24
|
"@types/react-dom": "^19.2.2",
|
|
25
25
|
"postcss": "^8.5.6",
|
|
26
|
-
"tailwindcss": "^4.1.
|
|
26
|
+
"tailwindcss": "^4.1.16",
|
|
27
27
|
"typescript": "^5.9.3"
|
|
28
28
|
}
|
|
29
29
|
}
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"moduleResolution": "bundler",
|
|
14
14
|
"resolveJsonModule": true,
|
|
15
15
|
"isolatedModules": true,
|
|
16
|
-
"jsx": "
|
|
16
|
+
"jsx": "react-jsx",
|
|
17
17
|
"incremental": true,
|
|
18
18
|
"paths": {
|
|
19
19
|
"@/*": ["./*"],
|
|
@@ -25,6 +25,12 @@
|
|
|
25
25
|
}
|
|
26
26
|
]
|
|
27
27
|
},
|
|
28
|
-
"include": [
|
|
28
|
+
"include": [
|
|
29
|
+
"next-env.d.ts",
|
|
30
|
+
"**/*.ts",
|
|
31
|
+
"**/*.tsx",
|
|
32
|
+
".next/types/**/*.ts",
|
|
33
|
+
".next/dev/types/**/*.ts"
|
|
34
|
+
],
|
|
29
35
|
"exclude": ["node_modules"]
|
|
30
36
|
}
|
|
@@ -21,15 +21,15 @@
|
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
23
|
"@react-router/dev": "^7.9.4",
|
|
24
|
-
"@tailwindcss/vite": "^4.1.
|
|
24
|
+
"@tailwindcss/vite": "^4.1.16",
|
|
25
25
|
"@types/mdx": "^2.0.13",
|
|
26
26
|
"@types/node": "^24.9.1",
|
|
27
27
|
"@types/react": "^19.2.2",
|
|
28
28
|
"@types/react-dom": "^19.2.2",
|
|
29
29
|
"react-router-devtools": "^5.1.3",
|
|
30
|
-
"tailwindcss": "^4.1.
|
|
30
|
+
"tailwindcss": "^4.1.16",
|
|
31
31
|
"typescript": "^5.9.3",
|
|
32
|
-
"vite": "^7.1.
|
|
32
|
+
"vite": "^7.1.12",
|
|
33
33
|
"vite-tsconfig-paths": "^5.1.4"
|
|
34
34
|
}
|
|
35
35
|
}
|
|
@@ -20,17 +20,17 @@
|
|
|
20
20
|
"react-router": "^7.9.4"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
|
-
"serve": "^14.2.5",
|
|
24
23
|
"@react-router/dev": "^7.9.4",
|
|
25
|
-
"@tailwindcss/vite": "^4.1.
|
|
24
|
+
"@tailwindcss/vite": "^4.1.16",
|
|
26
25
|
"@types/mdx": "^2.0.13",
|
|
27
26
|
"@types/node": "^24.9.1",
|
|
28
27
|
"@types/react": "^19.2.2",
|
|
29
28
|
"@types/react-dom": "^19.2.2",
|
|
30
29
|
"react-router-devtools": "^5.1.3",
|
|
31
|
-
"
|
|
30
|
+
"serve": "^14.2.5",
|
|
31
|
+
"tailwindcss": "^4.1.16",
|
|
32
32
|
"typescript": "^5.9.3",
|
|
33
|
-
"vite": "^7.1.
|
|
33
|
+
"vite": "^7.1.12",
|
|
34
34
|
"vite-tsconfig-paths": "^5.1.4"
|
|
35
35
|
}
|
|
36
36
|
}
|
|
@@ -4,7 +4,7 @@ description: Your favourite docs framework.
|
|
|
4
4
|
icon: Rocket
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
Hey there! Fumadocs is
|
|
7
|
+
Hey there! Fumadocs is the docs framework that also works on Tanstack Start!
|
|
8
8
|
|
|
9
9
|
## Heading
|
|
10
10
|
|
|
@@ -9,26 +9,26 @@
|
|
|
9
9
|
"start": "node .output/server/index.mjs"
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@tanstack/react-router": "^1.133.
|
|
13
|
-
"@tanstack/react-router-devtools": "^1.133.
|
|
14
|
-
"@tanstack/react-start": "^1.133.
|
|
12
|
+
"@tanstack/react-router": "^1.133.32",
|
|
13
|
+
"@tanstack/react-router-devtools": "^1.133.34",
|
|
14
|
+
"@tanstack/react-start": "^1.133.34",
|
|
15
15
|
"fumadocs-core": "workspace:*",
|
|
16
16
|
"fumadocs-mdx": "workspace:*",
|
|
17
17
|
"fumadocs-ui": "workspace:*",
|
|
18
|
-
"lucide-static": "^0.
|
|
18
|
+
"lucide-static": "^0.548.0",
|
|
19
19
|
"react": "^19.2.0",
|
|
20
20
|
"react-dom": "^19.2.0",
|
|
21
21
|
"tailwind-merge": "^3.3.1",
|
|
22
|
-
"vite": "^7.1.
|
|
22
|
+
"vite": "^7.1.12"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
|
-
"@tailwindcss/vite": "^4.1.
|
|
25
|
+
"@tailwindcss/vite": "^4.1.16",
|
|
26
26
|
"@types/mdx": "^2.0.13",
|
|
27
27
|
"@types/node": "^24.9.1",
|
|
28
28
|
"@types/react": "^19.2.2",
|
|
29
29
|
"@types/react-dom": "^19.2.2",
|
|
30
|
-
"@vitejs/plugin-react": "^5.0
|
|
31
|
-
"tailwindcss": "^4.1.
|
|
30
|
+
"@vitejs/plugin-react": "^5.1.0",
|
|
31
|
+
"tailwindcss": "^4.1.16",
|
|
32
32
|
"typescript": "^5.9.3",
|
|
33
33
|
"vite-tsconfig-paths": "^5.1.4"
|
|
34
34
|
}
|
|
@@ -73,28 +73,35 @@ function Page() {
|
|
|
73
73
|
);
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
-
function transformPageTree(
|
|
77
|
-
function
|
|
78
|
-
if (typeof item.icon
|
|
76
|
+
function transformPageTree(root: PageTree.Root): PageTree.Root {
|
|
77
|
+
function mapNode<T extends PageTree.Node>(item: T): T {
|
|
78
|
+
if (typeof item.icon === 'string') {
|
|
79
|
+
item = {
|
|
80
|
+
...item,
|
|
81
|
+
icon: (
|
|
82
|
+
<span
|
|
83
|
+
dangerouslySetInnerHTML={{
|
|
84
|
+
__html: item.icon,
|
|
85
|
+
}}
|
|
86
|
+
/>
|
|
87
|
+
),
|
|
88
|
+
};
|
|
89
|
+
}
|
|
79
90
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
};
|
|
91
|
+
if (item.type === 'folder') {
|
|
92
|
+
return {
|
|
93
|
+
...item,
|
|
94
|
+
index: item.index ? mapNode(item.index) : undefined,
|
|
95
|
+
children: item.children.map(mapNode),
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return item;
|
|
90
100
|
}
|
|
91
101
|
|
|
92
102
|
return {
|
|
93
|
-
...
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
if (item.type === 'folder') return transformPageTree(item);
|
|
97
|
-
return transform(item);
|
|
98
|
-
}),
|
|
103
|
+
...root,
|
|
104
|
+
children: root.children.map(mapNode),
|
|
105
|
+
fallback: root.fallback ? transformPageTree(root.fallback) : undefined,
|
|
99
106
|
};
|
|
100
107
|
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Hello World
|
|
3
|
+
description: Your favourite docs framework.
|
|
4
|
+
icon: Rocket
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Hey there! Fumadocs is the docs framework that also works on Tanstack Start!
|
|
8
|
+
|
|
9
|
+
## Heading
|
|
10
|
+
|
|
11
|
+
Hello World!
|
|
12
|
+
|
|
13
|
+
<Cards>
|
|
14
|
+
<Card
|
|
15
|
+
title="Learn more about Tanstack Start"
|
|
16
|
+
href="https://tanstack.com/start"
|
|
17
|
+
/>
|
|
18
|
+
<Card title="Learn more about Fumadocs" href="https://fumadocs.dev" />
|
|
19
|
+
</Cards>
|
|
20
|
+
|
|
21
|
+
### CodeBlock
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
console.log('Hello World');
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
#### Table
|
|
28
|
+
|
|
29
|
+
| Head | Description |
|
|
30
|
+
| ------------------------------- | ----------------------------------- |
|
|
31
|
+
| `hello` | Hello World |
|
|
32
|
+
| very **important** | Hey |
|
|
33
|
+
| _Surprisingly_ | Fumadocs |
|
|
34
|
+
| very long text that looks weird | hello world hello world hello world |
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
node_modules
|
|
2
|
+
|
|
3
|
+
.DS_Store
|
|
4
|
+
.cache
|
|
5
|
+
.vercel
|
|
6
|
+
.output
|
|
7
|
+
.nitro
|
|
8
|
+
/build/
|
|
9
|
+
/api/
|
|
10
|
+
/server/build
|
|
11
|
+
/public/build
|
|
12
|
+
/test-results/
|
|
13
|
+
/playwright-report/
|
|
14
|
+
/blob-report/
|
|
15
|
+
/playwright/.cache/
|
|
16
|
+
.tanstack
|
|
17
|
+
|
|
18
|
+
src/routeTree.gen.ts
|
|
19
|
+
.source
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "example-tanstack-start-spa",
|
|
3
|
+
"private": true,
|
|
4
|
+
"sideEffects": false,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "vite dev",
|
|
8
|
+
"build": "vite build",
|
|
9
|
+
"start": "serve dist/client"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"@orama/orama": "^3.1.16",
|
|
13
|
+
"@tanstack/react-router": "^1.133.32",
|
|
14
|
+
"@tanstack/react-router-devtools": "^1.133.34",
|
|
15
|
+
"@tanstack/react-start": "^1.133.34",
|
|
16
|
+
"@tanstack/start-static-server-functions": "^1.133.34",
|
|
17
|
+
"fumadocs-core": "workspace:*",
|
|
18
|
+
"fumadocs-mdx": "workspace:*",
|
|
19
|
+
"fumadocs-ui": "workspace:*",
|
|
20
|
+
"lucide-static": "^0.548.0",
|
|
21
|
+
"react": "^19.2.0",
|
|
22
|
+
"react-dom": "^19.2.0",
|
|
23
|
+
"tailwind-merge": "^3.3.1",
|
|
24
|
+
"vite": "^7.1.12"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"@tailwindcss/vite": "^4.1.16",
|
|
28
|
+
"@types/mdx": "^2.0.13",
|
|
29
|
+
"@types/node": "^24.9.1",
|
|
30
|
+
"@types/react": "^19.2.2",
|
|
31
|
+
"@types/react-dom": "^19.2.2",
|
|
32
|
+
"@vitejs/plugin-react": "^5.1.0",
|
|
33
|
+
"serve": "^14.2.5",
|
|
34
|
+
"tailwindcss": "^4.1.16",
|
|
35
|
+
"typescript": "^5.9.3",
|
|
36
|
+
"vite-tsconfig-paths": "^5.1.4"
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Link } from '@tanstack/react-router';
|
|
2
|
+
import { HomeLayout } from 'fumadocs-ui/layouts/home';
|
|
3
|
+
|
|
4
|
+
export function NotFound() {
|
|
5
|
+
return (
|
|
6
|
+
<HomeLayout
|
|
7
|
+
nav={{
|
|
8
|
+
title: 'Tanstack Start',
|
|
9
|
+
}}
|
|
10
|
+
className="text-center py-32 justify-center"
|
|
11
|
+
>
|
|
12
|
+
<div className="flex flex-col items-center gap-4">
|
|
13
|
+
<h1 className="text-6xl font-bold text-fd-muted-foreground">404</h1>
|
|
14
|
+
<h2 className="text-2xl font-semibold">Page Not Found</h2>
|
|
15
|
+
<p className="text-fd-muted-foreground max-w-md">
|
|
16
|
+
The page you are looking for might have been removed, had its name
|
|
17
|
+
changed, or is temporarily unavailable.
|
|
18
|
+
</p>
|
|
19
|
+
<Link
|
|
20
|
+
to="/"
|
|
21
|
+
className="mt-4 px-4 py-2 rounded-lg bg-fd-primary text-fd-primary-foreground font-medium text-sm hover:opacity-90 transition-opacity"
|
|
22
|
+
>
|
|
23
|
+
Back to Home
|
|
24
|
+
</Link>
|
|
25
|
+
</div>
|
|
26
|
+
</HomeLayout>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import {
|
|
3
|
+
SearchDialog,
|
|
4
|
+
SearchDialogClose,
|
|
5
|
+
SearchDialogContent,
|
|
6
|
+
SearchDialogHeader,
|
|
7
|
+
SearchDialogIcon,
|
|
8
|
+
SearchDialogInput,
|
|
9
|
+
SearchDialogList,
|
|
10
|
+
SearchDialogOverlay,
|
|
11
|
+
type SharedProps,
|
|
12
|
+
} from 'fumadocs-ui/components/dialog/search';
|
|
13
|
+
import { useDocsSearch } from 'fumadocs-core/search/client';
|
|
14
|
+
import { create } from '@orama/orama';
|
|
15
|
+
import { useI18n } from 'fumadocs-ui/contexts/i18n';
|
|
16
|
+
|
|
17
|
+
function initOrama() {
|
|
18
|
+
return create({
|
|
19
|
+
schema: { _: 'string' },
|
|
20
|
+
// https://docs.orama.com/docs/orama-js/supported-languages
|
|
21
|
+
language: 'english',
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export default function DefaultSearchDialog(props: SharedProps) {
|
|
26
|
+
const { locale } = useI18n(); // (optional) for i18n
|
|
27
|
+
const { search, setSearch, query } = useDocsSearch({
|
|
28
|
+
type: 'static',
|
|
29
|
+
initOrama,
|
|
30
|
+
locale,
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<SearchDialog
|
|
35
|
+
search={search}
|
|
36
|
+
onSearchChange={setSearch}
|
|
37
|
+
isLoading={query.isLoading}
|
|
38
|
+
{...props}
|
|
39
|
+
>
|
|
40
|
+
<SearchDialogOverlay />
|
|
41
|
+
<SearchDialogContent>
|
|
42
|
+
<SearchDialogHeader>
|
|
43
|
+
<SearchDialogIcon />
|
|
44
|
+
<SearchDialogInput />
|
|
45
|
+
<SearchDialogClose />
|
|
46
|
+
</SearchDialogHeader>
|
|
47
|
+
<SearchDialogList items={query.data !== 'empty' ? query.data : null} />
|
|
48
|
+
</SearchDialogContent>
|
|
49
|
+
</SearchDialog>
|
|
50
|
+
);
|
|
51
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { loader } from 'fumadocs-core/source';
|
|
2
|
+
import * as icons from 'lucide-static';
|
|
3
|
+
import { create, docs } from '@/.source';
|
|
4
|
+
|
|
5
|
+
export const source = loader({
|
|
6
|
+
source: await create.sourceAsync(docs.doc, docs.meta),
|
|
7
|
+
baseUrl: '/docs',
|
|
8
|
+
icon(icon) {
|
|
9
|
+
if (!icon) {
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (icon in icons) return icons[icon as keyof typeof icons];
|
|
14
|
+
},
|
|
15
|
+
});
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { createRouter as createTanStackRouter } from '@tanstack/react-router';
|
|
2
|
+
import { routeTree } from './routeTree.gen';
|
|
3
|
+
import { NotFound } from '@/components/not-found';
|
|
4
|
+
|
|
5
|
+
export function getRouter() {
|
|
6
|
+
return createTanStackRouter({
|
|
7
|
+
routeTree,
|
|
8
|
+
defaultPreload: 'intent',
|
|
9
|
+
scrollRestoration: true,
|
|
10
|
+
defaultNotFoundComponent: NotFound,
|
|
11
|
+
});
|
|
12
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createRootRoute,
|
|
3
|
+
HeadContent,
|
|
4
|
+
Outlet,
|
|
5
|
+
Scripts,
|
|
6
|
+
} from '@tanstack/react-router';
|
|
7
|
+
import * as React from 'react';
|
|
8
|
+
import appCss from '@/styles/app.css?url';
|
|
9
|
+
import { RootProvider } from 'fumadocs-ui/provider/tanstack';
|
|
10
|
+
import SearchDialog from '@/components/search';
|
|
11
|
+
|
|
12
|
+
export const Route = createRootRoute({
|
|
13
|
+
head: () => ({
|
|
14
|
+
meta: [
|
|
15
|
+
{
|
|
16
|
+
charSet: 'utf-8',
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
name: 'viewport',
|
|
20
|
+
content: 'width=device-width, initial-scale=1',
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
title: 'Fumadocs on TanStack Start',
|
|
24
|
+
},
|
|
25
|
+
],
|
|
26
|
+
links: [{ rel: 'stylesheet', href: appCss }],
|
|
27
|
+
}),
|
|
28
|
+
component: RootComponent,
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
function RootComponent() {
|
|
32
|
+
return (
|
|
33
|
+
<RootDocument>
|
|
34
|
+
<Outlet />
|
|
35
|
+
</RootDocument>
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function RootDocument({ children }: { children: React.ReactNode }) {
|
|
40
|
+
return (
|
|
41
|
+
<html suppressHydrationWarning>
|
|
42
|
+
<head>
|
|
43
|
+
<HeadContent />
|
|
44
|
+
</head>
|
|
45
|
+
<body className="flex flex-col min-h-screen">
|
|
46
|
+
<RootProvider search={{ SearchDialog }}>{children}</RootProvider>
|
|
47
|
+
<Scripts />
|
|
48
|
+
</body>
|
|
49
|
+
</html>
|
|
50
|
+
);
|
|
51
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { createFileRoute } from '@tanstack/react-router';
|
|
2
|
+
import { source } from '@/lib/source';
|
|
3
|
+
import { createFromSource } from 'fumadocs-core/search/server';
|
|
4
|
+
|
|
5
|
+
const server = createFromSource(source, {
|
|
6
|
+
// https://docs.orama.com/docs/orama-js/supported-languages
|
|
7
|
+
language: 'english',
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
export const Route = createFileRoute('/api/search')({
|
|
11
|
+
server: {
|
|
12
|
+
handlers: {
|
|
13
|
+
GET: () => server.staticGET(),
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
});
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { createFileRoute, notFound } from '@tanstack/react-router';
|
|
2
|
+
import { DocsLayout } from 'fumadocs-ui/layouts/docs';
|
|
3
|
+
import { createServerFn } from '@tanstack/react-start';
|
|
4
|
+
import { source } from '@/lib/source';
|
|
5
|
+
import type * as PageTree from 'fumadocs-core/page-tree';
|
|
6
|
+
import { useMemo } from 'react';
|
|
7
|
+
import { docs } from '@/.source';
|
|
8
|
+
import {
|
|
9
|
+
DocsBody,
|
|
10
|
+
DocsDescription,
|
|
11
|
+
DocsPage,
|
|
12
|
+
DocsTitle,
|
|
13
|
+
} from 'fumadocs-ui/page';
|
|
14
|
+
import defaultMdxComponents from 'fumadocs-ui/mdx';
|
|
15
|
+
import { createClientLoader } from 'fumadocs-mdx/runtime/vite';
|
|
16
|
+
import { baseOptions } from '@/lib/layout.shared';
|
|
17
|
+
import { staticFunctionMiddleware } from '@tanstack/start-static-server-functions';
|
|
18
|
+
|
|
19
|
+
export const Route = createFileRoute('/docs/$')({
|
|
20
|
+
component: Page,
|
|
21
|
+
loader: async ({ params }) => {
|
|
22
|
+
const slugs = params._splat?.split('/') ?? [];
|
|
23
|
+
const data = await loader({ data: slugs });
|
|
24
|
+
await clientLoader.preload(data.path);
|
|
25
|
+
return data;
|
|
26
|
+
},
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const loader = createServerFn({
|
|
30
|
+
method: 'GET',
|
|
31
|
+
})
|
|
32
|
+
.inputValidator((slugs: string[]) => slugs)
|
|
33
|
+
.middleware([staticFunctionMiddleware])
|
|
34
|
+
.handler(async ({ data: slugs }) => {
|
|
35
|
+
const page = source.getPage(slugs);
|
|
36
|
+
if (!page) throw notFound();
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
tree: source.pageTree as object,
|
|
40
|
+
path: page.path,
|
|
41
|
+
};
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
const clientLoader = createClientLoader(docs.doc, {
|
|
45
|
+
id: 'docs',
|
|
46
|
+
component({ toc, frontmatter, default: MDX }) {
|
|
47
|
+
return (
|
|
48
|
+
<DocsPage toc={toc}>
|
|
49
|
+
<DocsTitle>{frontmatter.title}</DocsTitle>
|
|
50
|
+
<DocsDescription>{frontmatter.description}</DocsDescription>
|
|
51
|
+
<DocsBody>
|
|
52
|
+
<MDX
|
|
53
|
+
components={{
|
|
54
|
+
...defaultMdxComponents,
|
|
55
|
+
}}
|
|
56
|
+
/>
|
|
57
|
+
</DocsBody>
|
|
58
|
+
</DocsPage>
|
|
59
|
+
);
|
|
60
|
+
},
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
function Page() {
|
|
64
|
+
const data = Route.useLoaderData();
|
|
65
|
+
const Content = clientLoader.getComponent(data.path);
|
|
66
|
+
const tree = useMemo(
|
|
67
|
+
() => transformPageTree(data.tree as PageTree.Folder),
|
|
68
|
+
[data.tree],
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
return (
|
|
72
|
+
<DocsLayout {...baseOptions()} tree={tree}>
|
|
73
|
+
<Content />
|
|
74
|
+
</DocsLayout>
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function transformPageTree(root: PageTree.Root): PageTree.Root {
|
|
79
|
+
function mapNode<T extends PageTree.Node>(item: T): T {
|
|
80
|
+
if (typeof item.icon === 'string') {
|
|
81
|
+
item = {
|
|
82
|
+
...item,
|
|
83
|
+
icon: (
|
|
84
|
+
<span
|
|
85
|
+
dangerouslySetInnerHTML={{
|
|
86
|
+
__html: item.icon,
|
|
87
|
+
}}
|
|
88
|
+
/>
|
|
89
|
+
),
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (item.type === 'folder') {
|
|
94
|
+
return {
|
|
95
|
+
...item,
|
|
96
|
+
index: item.index ? mapNode(item.index) : undefined,
|
|
97
|
+
children: item.children.map(mapNode),
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return item;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return {
|
|
105
|
+
...root,
|
|
106
|
+
children: root.children.map(mapNode),
|
|
107
|
+
fallback: root.fallback ? transformPageTree(root.fallback) : undefined,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { createFileRoute, Link } from '@tanstack/react-router';
|
|
2
|
+
import { HomeLayout } from 'fumadocs-ui/layouts/home';
|
|
3
|
+
import { baseOptions } from '@/lib/layout.shared';
|
|
4
|
+
|
|
5
|
+
export const Route = createFileRoute('/')({
|
|
6
|
+
component: Home,
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
function Home() {
|
|
10
|
+
return (
|
|
11
|
+
<HomeLayout {...baseOptions()} className="text-center py-32 justify-center">
|
|
12
|
+
<h1 className="font-medium text-xl mb-4">Fumadocs on Tanstack Start.</h1>
|
|
13
|
+
<Link
|
|
14
|
+
to="/docs/$"
|
|
15
|
+
params={{
|
|
16
|
+
_splat: '',
|
|
17
|
+
}}
|
|
18
|
+
className="px-3 py-2 rounded-lg bg-fd-primary text-fd-primary-foreground font-medium text-sm mx-auto"
|
|
19
|
+
>
|
|
20
|
+
Open Docs
|
|
21
|
+
</Link>
|
|
22
|
+
</HomeLayout>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"include": ["**/*.ts", "**/*.tsx"],
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"strict": true,
|
|
5
|
+
"esModuleInterop": true,
|
|
6
|
+
"jsx": "react-jsx",
|
|
7
|
+
"module": "ESNext",
|
|
8
|
+
"moduleResolution": "Bundler",
|
|
9
|
+
"lib": ["DOM", "DOM.Iterable", "ES2022"],
|
|
10
|
+
"types": ["vite/client"],
|
|
11
|
+
"isolatedModules": true,
|
|
12
|
+
"resolveJsonModule": true,
|
|
13
|
+
"skipLibCheck": true,
|
|
14
|
+
"target": "ES2022",
|
|
15
|
+
"allowJs": true,
|
|
16
|
+
"forceConsistentCasingInFileNames": true,
|
|
17
|
+
"baseUrl": ".",
|
|
18
|
+
"paths": {
|
|
19
|
+
"@/*": ["./src/*"],
|
|
20
|
+
"@/.source": [".source"]
|
|
21
|
+
},
|
|
22
|
+
"noEmit": true
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import react from '@vitejs/plugin-react';
|
|
2
|
+
import { tanstackStart } from '@tanstack/react-start/plugin/vite';
|
|
3
|
+
import { defineConfig } from 'vite';
|
|
4
|
+
import tsConfigPaths from 'vite-tsconfig-paths';
|
|
5
|
+
import tailwindcss from '@tailwindcss/vite';
|
|
6
|
+
import mdx from 'fumadocs-mdx/vite';
|
|
7
|
+
|
|
8
|
+
export default defineConfig({
|
|
9
|
+
server: {
|
|
10
|
+
port: 3000,
|
|
11
|
+
},
|
|
12
|
+
plugins: [
|
|
13
|
+
mdx(await import('./source.config')),
|
|
14
|
+
tailwindcss(),
|
|
15
|
+
tsConfigPaths({
|
|
16
|
+
projects: ['./tsconfig.json'],
|
|
17
|
+
}),
|
|
18
|
+
tanstackStart({
|
|
19
|
+
spa: {
|
|
20
|
+
enabled: true,
|
|
21
|
+
prerender: {
|
|
22
|
+
outputPath: 'index.html',
|
|
23
|
+
enabled: true,
|
|
24
|
+
crawlLinks: true,
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
|
|
28
|
+
pages: [
|
|
29
|
+
{
|
|
30
|
+
path: '/docs',
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
path: '/api/search',
|
|
34
|
+
},
|
|
35
|
+
],
|
|
36
|
+
}),
|
|
37
|
+
react(),
|
|
38
|
+
],
|
|
39
|
+
});
|
|
@@ -15,17 +15,17 @@
|
|
|
15
15
|
"react": "^19.2.0",
|
|
16
16
|
"react-dom": "^19.2.0",
|
|
17
17
|
"react-server-dom-webpack": "^19.2.0",
|
|
18
|
-
"waku": "^0.
|
|
18
|
+
"waku": "^0.27.0"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
21
|
-
"@tailwindcss/vite": "^4.1.
|
|
21
|
+
"@tailwindcss/vite": "^4.1.16",
|
|
22
22
|
"@types/mdx": "^2.0.13",
|
|
23
23
|
"@types/node": "^24.9.1",
|
|
24
24
|
"@types/react": "^19.2.2",
|
|
25
25
|
"@types/react-dom": "^19.2.2",
|
|
26
|
-
"tailwindcss": "^4.1.
|
|
26
|
+
"tailwindcss": "^4.1.16",
|
|
27
27
|
"typescript": "^5.9.3",
|
|
28
|
-
"vite": "^7.1.
|
|
28
|
+
"vite": "^7.1.12",
|
|
29
29
|
"vite-tsconfig-paths": "^5.1.4"
|
|
30
30
|
}
|
|
31
31
|
}
|