create-fumadocs-app 15.2.0 → 15.2.2
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/{chunk-R4Y2JVJN.js → chunk-ZA7GBGFG.js} +57 -21
- package/dist/create-app.js +1 -1
- package/dist/index.js +18 -7
- package/package.json +2 -2
- package/template/react-router/app/docs/page.tsx +6 -6
- package/template/tanstack-start/README.md +12 -0
- package/template/tanstack-start/app/api.ts +6 -0
- package/template/tanstack-start/app/app.css +6 -0
- package/template/tanstack-start/app/client.tsx +7 -0
- package/template/tanstack-start/app/router.tsx +15 -0
- package/template/tanstack-start/app/routes/__root.tsx +49 -0
- package/template/tanstack-start/app/routes/api/search.ts +20 -0
- package/template/tanstack-start/app/routes/docs/$.tsx +71 -0
- package/template/tanstack-start/app/routes/index.tsx +25 -0
- package/template/tanstack-start/app/ssr.tsx +13 -0
- package/template/tanstack-start/app.config.ts +43 -0
- package/template/tanstack-start/content/docs/index.mdx +35 -0
- package/template/tanstack-start/example.gitignore +4 -0
- package/template/tanstack-start/lib/source.ts +70 -0
- package/template/tanstack-start/tsconfig.json +15 -0
- /package/template/{content-collections → +next+content-collections}/app/docs/[[...slug]]/page.tsx +0 -0
- /package/template/{content-collections → +next+content-collections}/content-collections.ts +0 -0
- /package/template/{content-collections → +next+content-collections}/lib/source.ts +0 -0
- /package/template/{content-collections → +next+content-collections}/next.config.mjs +0 -0
- /package/template/{content-collections → +next+content-collections}/tsconfig.json +0 -0
- /package/template/{fuma-docs-mdx → +next+fuma-docs-mdx}/app/docs/[[...slug]]/page.tsx +0 -0
- /package/template/{fuma-docs-mdx → +next+fuma-docs-mdx}/lib/source.ts +0 -0
- /package/template/{fuma-docs-mdx → +next+fuma-docs-mdx}/next.config.mjs +0 -0
- /package/template/{fuma-docs-mdx → +next+fuma-docs-mdx}/source.config.ts +0 -0
- /package/template/{fuma-docs-mdx → +next+fuma-docs-mdx}/tsconfig.json +0 -0
|
@@ -60,7 +60,7 @@ function tryGitInit(root) {
|
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
// src/versions.js
|
|
63
|
-
var versions = { "fumadocs-core": "15.2.
|
|
63
|
+
var versions = { "fumadocs-core": "15.2.2", "fumadocs-ui": "15.2.2", "fumadocs-mdx": "11.5.7", "@fumadocs/mdx-remote": "1.3.0", "@fumadocs/content-collections": "1.1.8" };
|
|
64
64
|
|
|
65
65
|
// ../create-app-versions/package.json
|
|
66
66
|
var package_default = {
|
|
@@ -78,10 +78,14 @@ var package_default = {
|
|
|
78
78
|
"@react-router/serve": "^7.4.1",
|
|
79
79
|
"@tailwindcss/postcss": "^4.0.17",
|
|
80
80
|
"@tailwindcss/vite": "^4.0.17",
|
|
81
|
+
"@tanstack/react-router": "^1.114.29",
|
|
82
|
+
"@tanstack/react-start": "^1.114.31",
|
|
81
83
|
"@types/mdx": "^2.0.13",
|
|
82
|
-
"@types/node": "22.13.
|
|
84
|
+
"@types/node": "22.13.16",
|
|
83
85
|
"@types/react": "^19.0.12",
|
|
84
86
|
"@types/react-dom": "^19.0.4",
|
|
87
|
+
"@vitejs/plugin-react": "^4.3.4",
|
|
88
|
+
"fast-glob": "^3.3.3",
|
|
85
89
|
"gray-matter": "^4.0.3",
|
|
86
90
|
isbot: "^5.1.17",
|
|
87
91
|
next: "15.2.4",
|
|
@@ -93,7 +97,8 @@ var package_default = {
|
|
|
93
97
|
shiki: "^3.2.1",
|
|
94
98
|
tailwindcss: "^4.0.17",
|
|
95
99
|
typescript: "^5.8.2",
|
|
96
|
-
|
|
100
|
+
vinxi: "^0.5.3",
|
|
101
|
+
vite: "^6.2.4",
|
|
97
102
|
"vite-tsconfig-paths": "^5.1.4"
|
|
98
103
|
}
|
|
99
104
|
};
|
|
@@ -148,23 +153,16 @@ async function create(options) {
|
|
|
148
153
|
} = options;
|
|
149
154
|
const projectName = path.basename(options.outputDir);
|
|
150
155
|
const dest = path.resolve(cwd, options.outputDir);
|
|
151
|
-
const isNext = options.template
|
|
156
|
+
const isNext = options.template.startsWith("+next");
|
|
152
157
|
function defaultRename(file) {
|
|
153
158
|
file = file.replace("example.gitignore", ".gitignore");
|
|
154
|
-
if (!options.useSrcDir) {
|
|
159
|
+
if (!options.useSrcDir || !isNext) {
|
|
155
160
|
return file;
|
|
156
161
|
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
const relative = path.relative(path.join(dest, dir), file);
|
|
160
|
-
if (!relative.startsWith(`..${path.sep}`)) {
|
|
161
|
-
return path.join(dest, "src", dir, relative);
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
} else if (options.template === "react-router") {
|
|
165
|
-
const relative = path.relative(path.join(dest, "app"), file);
|
|
162
|
+
for (const dir of ["app", "lib"]) {
|
|
163
|
+
const relative = path.relative(path.join(dest, dir), file);
|
|
166
164
|
if (!relative.startsWith(`..${path.sep}`)) {
|
|
167
|
-
return path.join(dest, "src", relative);
|
|
165
|
+
return path.join(dest, "src", dir, relative);
|
|
168
166
|
}
|
|
169
167
|
}
|
|
170
168
|
return file;
|
|
@@ -200,7 +198,7 @@ async function create(options) {
|
|
|
200
198
|
);
|
|
201
199
|
log("Configured ESLint");
|
|
202
200
|
}
|
|
203
|
-
if (options.useSrcDir) {
|
|
201
|
+
if (isNext && options.useSrcDir) {
|
|
204
202
|
const tsconfigPath = path.join(dest, "tsconfig.json");
|
|
205
203
|
const content = (await fs.readFile(tsconfigPath)).toString();
|
|
206
204
|
const config = JSON.parse(content);
|
|
@@ -289,6 +287,44 @@ function createPackageJson(projectName, options) {
|
|
|
289
287
|
])
|
|
290
288
|
};
|
|
291
289
|
}
|
|
290
|
+
if (options.template === "tanstack-start") {
|
|
291
|
+
return {
|
|
292
|
+
name: projectName,
|
|
293
|
+
type: "module",
|
|
294
|
+
scripts: {
|
|
295
|
+
dev: "vinxi dev",
|
|
296
|
+
build: "NODE_ENV=production vinxi build",
|
|
297
|
+
start: "vinxi start"
|
|
298
|
+
},
|
|
299
|
+
private: true,
|
|
300
|
+
dependencies: {
|
|
301
|
+
...pick(versions, [
|
|
302
|
+
"@fumadocs/mdx-remote",
|
|
303
|
+
"fumadocs-ui",
|
|
304
|
+
"fumadocs-core"
|
|
305
|
+
]),
|
|
306
|
+
...pick(package_default.dependencies, [
|
|
307
|
+
"@tanstack/react-router",
|
|
308
|
+
"@tanstack/react-start",
|
|
309
|
+
"fast-glob",
|
|
310
|
+
"gray-matter",
|
|
311
|
+
"react",
|
|
312
|
+
"react-dom",
|
|
313
|
+
"vinxi"
|
|
314
|
+
])
|
|
315
|
+
},
|
|
316
|
+
devDependencies: pick(package_default.dependencies, [
|
|
317
|
+
"@tailwindcss/vite",
|
|
318
|
+
"@types/react",
|
|
319
|
+
"@types/react-dom",
|
|
320
|
+
"@vitejs/plugin-react",
|
|
321
|
+
"tailwindcss",
|
|
322
|
+
"typescript",
|
|
323
|
+
"vite",
|
|
324
|
+
"vite-tsconfig-paths"
|
|
325
|
+
])
|
|
326
|
+
};
|
|
327
|
+
}
|
|
292
328
|
return {
|
|
293
329
|
name: projectName,
|
|
294
330
|
version: "0.0.0",
|
|
@@ -297,14 +333,14 @@ function createPackageJson(projectName, options) {
|
|
|
297
333
|
build: "next build",
|
|
298
334
|
dev: "next dev",
|
|
299
335
|
start: "next start",
|
|
300
|
-
...options.template === "fuma-docs-mdx" ? {
|
|
336
|
+
...options.template === "+next+fuma-docs-mdx" ? {
|
|
301
337
|
postinstall: "fumadocs-mdx"
|
|
302
338
|
} : null
|
|
303
339
|
},
|
|
304
340
|
dependencies: {
|
|
305
341
|
...pick(package_default.dependencies, ["next", "react", "react-dom"]),
|
|
306
342
|
...pick(versions, ["fumadocs-ui", "fumadocs-core"]),
|
|
307
|
-
...options.template === "content-collections" ? {
|
|
343
|
+
...options.template === "+next+content-collections" ? {
|
|
308
344
|
...pick(package_default.dependencies, [
|
|
309
345
|
"@content-collections/mdx",
|
|
310
346
|
"@content-collections/core",
|
|
@@ -312,21 +348,21 @@ function createPackageJson(projectName, options) {
|
|
|
312
348
|
]),
|
|
313
349
|
...pick(versions, ["@fumadocs/content-collections"])
|
|
314
350
|
} : null,
|
|
315
|
-
...options.template === "fuma-docs-mdx" ? pick(versions, ["fumadocs-mdx"]) : null
|
|
351
|
+
...options.template === "+next+fuma-docs-mdx" ? pick(versions, ["fumadocs-mdx"]) : null
|
|
316
352
|
},
|
|
317
353
|
devDependencies: {
|
|
318
354
|
...pick(package_default.dependencies, [
|
|
319
355
|
"@types/node",
|
|
320
356
|
"@types/react",
|
|
321
357
|
"@types/react-dom",
|
|
322
|
-
"typescript"
|
|
358
|
+
"typescript",
|
|
359
|
+
"@types/mdx"
|
|
323
360
|
]),
|
|
324
361
|
...options.tailwindcss ? pick(package_default.dependencies, [
|
|
325
362
|
"@tailwindcss/postcss",
|
|
326
363
|
"tailwindcss",
|
|
327
364
|
"postcss"
|
|
328
365
|
]) : null,
|
|
329
|
-
...options.template === "fuma-docs-mdx" ? pick(package_default.dependencies, ["@types/mdx"]) : null,
|
|
330
366
|
...options.eslint ? {
|
|
331
367
|
eslint: "^8",
|
|
332
368
|
"eslint-config-next": package_default.dependencies.next
|
package/dist/create-app.js
CHANGED
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
create,
|
|
4
4
|
cwd,
|
|
5
5
|
getPackageManager
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-ZA7GBGFG.js";
|
|
7
7
|
|
|
8
8
|
// src/index.ts
|
|
9
9
|
import fs from "node:fs/promises";
|
|
@@ -32,26 +32,37 @@ async function main() {
|
|
|
32
32
|
}),
|
|
33
33
|
template: () => select({
|
|
34
34
|
message: "Choose a template",
|
|
35
|
-
initialValue: "fuma-docs-mdx",
|
|
35
|
+
initialValue: "+next+fuma-docs-mdx",
|
|
36
36
|
options: [
|
|
37
37
|
{
|
|
38
|
-
value: "fuma-docs-mdx",
|
|
38
|
+
value: "+next+fuma-docs-mdx",
|
|
39
39
|
label: "Next.js: Fumadocs MDX",
|
|
40
40
|
hint: "recommended"
|
|
41
41
|
},
|
|
42
42
|
{
|
|
43
|
-
value: "content-collections",
|
|
43
|
+
value: "+next+content-collections",
|
|
44
44
|
label: "Next.js: Content Collections"
|
|
45
45
|
},
|
|
46
46
|
{
|
|
47
47
|
value: "react-router",
|
|
48
48
|
label: "React Router: MDX Remote"
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
value: "tanstack-start",
|
|
52
|
+
label: "Tanstack Start: MDX Remote",
|
|
53
|
+
hint: "Experimental"
|
|
49
54
|
}
|
|
50
55
|
]
|
|
51
56
|
}),
|
|
52
|
-
src: () =>
|
|
57
|
+
src: (v) => {
|
|
58
|
+
if (!v.results.template?.startsWith("+next")) return;
|
|
59
|
+
return confirm({
|
|
60
|
+
message: "Use `/src` directory?",
|
|
61
|
+
initialValue: false
|
|
62
|
+
});
|
|
63
|
+
},
|
|
53
64
|
eslint: (v) => {
|
|
54
|
-
if (v.results.template
|
|
65
|
+
if (!v.results.template?.startsWith("+next")) return;
|
|
55
66
|
return confirm({
|
|
56
67
|
message: "Add default ESLint configuration?",
|
|
57
68
|
initialValue: false
|
|
@@ -102,7 +113,7 @@ async function main() {
|
|
|
102
113
|
outputDir: dest,
|
|
103
114
|
installDeps: options.installDeps,
|
|
104
115
|
eslint: options.eslint === true,
|
|
105
|
-
useSrcDir: options.src,
|
|
116
|
+
useSrcDir: options.src === true,
|
|
106
117
|
log: (message) => {
|
|
107
118
|
info.message(message);
|
|
108
119
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-fumadocs-app",
|
|
3
|
-
"version": "15.2.
|
|
3
|
+
"version": "15.2.2",
|
|
4
4
|
"description": "Create a new documentation site with Fumadocs",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"NextJs",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@types/cross-spawn": "^6.0.6",
|
|
28
|
-
"@types/node": "22.13.
|
|
28
|
+
"@types/node": "22.13.16",
|
|
29
29
|
"fast-glob": "^3.3.3",
|
|
30
30
|
"eslint-config-custom": "0.0.0",
|
|
31
31
|
"tsconfig": "0.0.0"
|
|
@@ -11,6 +11,7 @@ import defaultMdxComponents from 'fumadocs-ui/mdx';
|
|
|
11
11
|
import { executeMdxSync } from '@fumadocs/mdx-remote/client';
|
|
12
12
|
import type { PageTree } from 'fumadocs-core/server';
|
|
13
13
|
import { createCompiler } from '@fumadocs/mdx-remote';
|
|
14
|
+
import * as path from 'node:path';
|
|
14
15
|
|
|
15
16
|
export function meta({}: Route.MetaArgs) {
|
|
16
17
|
return [
|
|
@@ -27,15 +28,14 @@ export async function loader({ params }: Route.LoaderArgs) {
|
|
|
27
28
|
const page = source.getPage(slugs);
|
|
28
29
|
if (!page) throw new Error('Not found');
|
|
29
30
|
|
|
30
|
-
const compiled =
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
);
|
|
31
|
+
const compiled = await compiler.compileFile({
|
|
32
|
+
path: path.resolve('content/docs', page.file.path),
|
|
33
|
+
value: page.data.content,
|
|
34
|
+
});
|
|
35
35
|
|
|
36
36
|
return {
|
|
37
37
|
page,
|
|
38
|
-
compiled,
|
|
38
|
+
compiled: compiled.toString(),
|
|
39
39
|
tree: source.pageTree,
|
|
40
40
|
};
|
|
41
41
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { createRouter as createTanStackRouter } from '@tanstack/react-router';
|
|
2
|
+
import { routeTree } from './routeTree.gen';
|
|
3
|
+
|
|
4
|
+
export function createRouter() {
|
|
5
|
+
return createTanStackRouter({
|
|
6
|
+
routeTree,
|
|
7
|
+
scrollRestoration: true,
|
|
8
|
+
});
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
declare module '@tanstack/react-router' {
|
|
12
|
+
interface Register {
|
|
13
|
+
router: ReturnType<typeof createRouter>;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import { Outlet, createRootRoute, HeadContent } from '@tanstack/react-router';
|
|
3
|
+
import { RootProvider } from 'fumadocs-ui/provider/base';
|
|
4
|
+
import appCss from '../app.css?url';
|
|
5
|
+
import { TanstackProvider } from 'fumadocs-core/framework/tanstack';
|
|
6
|
+
import { Scripts } from '@tanstack/react-router';
|
|
7
|
+
|
|
8
|
+
export const Route = createRootRoute({
|
|
9
|
+
head: () => ({
|
|
10
|
+
meta: [
|
|
11
|
+
{
|
|
12
|
+
charSet: 'utf-8',
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
name: 'viewport',
|
|
16
|
+
content: 'width=device-width, initial-scale=1',
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
title: 'Fumadocs on TanStack Start',
|
|
20
|
+
},
|
|
21
|
+
],
|
|
22
|
+
links: [{ rel: 'stylesheet', href: appCss }],
|
|
23
|
+
}),
|
|
24
|
+
component: RootComponent,
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
function RootComponent() {
|
|
28
|
+
return (
|
|
29
|
+
<RootDocument>
|
|
30
|
+
<Outlet />
|
|
31
|
+
</RootDocument>
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function RootDocument({ children }: Readonly<{ children: ReactNode }>) {
|
|
36
|
+
return (
|
|
37
|
+
<html suppressHydrationWarning>
|
|
38
|
+
<head>
|
|
39
|
+
<HeadContent />
|
|
40
|
+
</head>
|
|
41
|
+
<body>
|
|
42
|
+
<TanstackProvider>
|
|
43
|
+
<RootProvider>{children}</RootProvider>
|
|
44
|
+
</TanstackProvider>
|
|
45
|
+
<Scripts />
|
|
46
|
+
</body>
|
|
47
|
+
</html>
|
|
48
|
+
);
|
|
49
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { createAPIFileRoute } from '@tanstack/react-start/api';
|
|
2
|
+
import { createSearchAPI } from 'fumadocs-core/search/server';
|
|
3
|
+
import { source } from '@/lib/source';
|
|
4
|
+
import { structure } from 'fumadocs-core/mdx-plugins';
|
|
5
|
+
|
|
6
|
+
const server = createSearchAPI('advanced', {
|
|
7
|
+
indexes: source.getPages().map((page) => ({
|
|
8
|
+
id: page.url,
|
|
9
|
+
url: page.url,
|
|
10
|
+
title: page.data.title ?? '',
|
|
11
|
+
description: page.data.description,
|
|
12
|
+
structuredData: structure(page.data.content),
|
|
13
|
+
})),
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
export const APIRoute = createAPIFileRoute('/api/search')({
|
|
17
|
+
GET: ({ request }) => {
|
|
18
|
+
return server.GET(request);
|
|
19
|
+
},
|
|
20
|
+
});
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { createFileRoute, notFound } from '@tanstack/react-router';
|
|
2
|
+
import { DocsLayout } from 'fumadocs-ui/layouts/docs';
|
|
3
|
+
import { source } from '@/lib/source';
|
|
4
|
+
import {
|
|
5
|
+
DocsBody,
|
|
6
|
+
DocsDescription,
|
|
7
|
+
DocsPage,
|
|
8
|
+
DocsTitle,
|
|
9
|
+
} from 'fumadocs-ui/page';
|
|
10
|
+
import { executeMdxSync } from '@fumadocs/mdx-remote/client';
|
|
11
|
+
import defaultMdxComponents from 'fumadocs-ui/mdx';
|
|
12
|
+
import { createServerFn } from '@tanstack/react-start';
|
|
13
|
+
import type { PageTree } from 'fumadocs-core/server';
|
|
14
|
+
import { createCompiler } from '@fumadocs/mdx-remote';
|
|
15
|
+
import * as path from 'node:path';
|
|
16
|
+
|
|
17
|
+
export const Route = createFileRoute('/docs/$')({
|
|
18
|
+
component: Page,
|
|
19
|
+
async loader({ params }) {
|
|
20
|
+
const slugs = (params._splat ?? '').split('/');
|
|
21
|
+
|
|
22
|
+
return loader({ data: slugs });
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
const compiler = createCompiler({
|
|
27
|
+
development: false,
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const loader = createServerFn({
|
|
31
|
+
method: 'GET',
|
|
32
|
+
})
|
|
33
|
+
.validator((slugs: string[]) => slugs)
|
|
34
|
+
.handler(async ({ data: slugs }) => {
|
|
35
|
+
const page = source.getPage(slugs);
|
|
36
|
+
if (!page) throw notFound();
|
|
37
|
+
|
|
38
|
+
const { content, ...rest } = page.data;
|
|
39
|
+
const compiled = await compiler.compileFile({
|
|
40
|
+
path: path.resolve('content/docs', page.file.path),
|
|
41
|
+
value: content,
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
return {
|
|
45
|
+
tree: source.pageTree as object,
|
|
46
|
+
...rest,
|
|
47
|
+
compiled: compiled.toString(),
|
|
48
|
+
};
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
function Page() {
|
|
52
|
+
const { tree, compiled, ...data } = Route.useLoaderData();
|
|
53
|
+
const { toc, default: MdxContent } = executeMdxSync(compiled);
|
|
54
|
+
|
|
55
|
+
return (
|
|
56
|
+
<DocsLayout
|
|
57
|
+
nav={{
|
|
58
|
+
title: 'Tanstack Start',
|
|
59
|
+
}}
|
|
60
|
+
tree={tree as PageTree.Root}
|
|
61
|
+
>
|
|
62
|
+
<DocsPage toc={toc}>
|
|
63
|
+
<DocsTitle>{data.title}</DocsTitle>
|
|
64
|
+
<DocsDescription>{data.title}</DocsDescription>
|
|
65
|
+
<DocsBody>
|
|
66
|
+
<MdxContent components={defaultMdxComponents} />
|
|
67
|
+
</DocsBody>
|
|
68
|
+
</DocsPage>
|
|
69
|
+
</DocsLayout>
|
|
70
|
+
);
|
|
71
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { createFileRoute, Link } from '@tanstack/react-router';
|
|
2
|
+
import { HomeLayout } from 'fumadocs-ui/layouts/home';
|
|
3
|
+
|
|
4
|
+
export const Route = createFileRoute('/')({
|
|
5
|
+
component: Home,
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
function Home() {
|
|
9
|
+
return (
|
|
10
|
+
<HomeLayout
|
|
11
|
+
nav={{
|
|
12
|
+
title: 'Tanstack Start',
|
|
13
|
+
}}
|
|
14
|
+
className="text-center py-32"
|
|
15
|
+
>
|
|
16
|
+
<h1 className="font-medium text-xl mb-4">Fumadocs on Tanstack Start.</h1>
|
|
17
|
+
<Link
|
|
18
|
+
to="/docs/$"
|
|
19
|
+
className="px-3 py-2 rounded-lg bg-fd-primary text-fd-primary-foreground font-medium text-sm mx-auto"
|
|
20
|
+
>
|
|
21
|
+
Open Docs
|
|
22
|
+
</Link>
|
|
23
|
+
</HomeLayout>
|
|
24
|
+
);
|
|
25
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// app/ssr.tsx
|
|
2
|
+
import {
|
|
3
|
+
createStartHandler,
|
|
4
|
+
defaultStreamHandler,
|
|
5
|
+
} from '@tanstack/react-start/server';
|
|
6
|
+
import { getRouterManifest } from '@tanstack/react-start/router-manifest';
|
|
7
|
+
|
|
8
|
+
import { createRouter } from './router';
|
|
9
|
+
|
|
10
|
+
export default createStartHandler({
|
|
11
|
+
createRouter,
|
|
12
|
+
getRouterManifest,
|
|
13
|
+
})(defaultStreamHandler);
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { defineConfig } from '@tanstack/react-start/config';
|
|
2
|
+
import tsConfigPaths from 'vite-tsconfig-paths';
|
|
3
|
+
import tailwindcss from '@tailwindcss/vite';
|
|
4
|
+
|
|
5
|
+
export default defineConfig({
|
|
6
|
+
server: {
|
|
7
|
+
hooks: {
|
|
8
|
+
'prerender:routes': async (routes) => {
|
|
9
|
+
const { source } = await import('./lib/source');
|
|
10
|
+
const pages = source.getPages();
|
|
11
|
+
|
|
12
|
+
for (const page of pages) {
|
|
13
|
+
routes.add(page.url);
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
prerender: {
|
|
18
|
+
routes: ['/'],
|
|
19
|
+
crawlLinks: true,
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
vite: {
|
|
23
|
+
build: {
|
|
24
|
+
rollupOptions: {
|
|
25
|
+
// Shiki results in a huge bundle because Rollup tries to bundle every language/theme
|
|
26
|
+
external: ['shiki'],
|
|
27
|
+
// most React.js libraries now include 'use client'
|
|
28
|
+
onwarn(warning, warn) {
|
|
29
|
+
if (warning.code === 'MODULE_LEVEL_DIRECTIVE') {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
warn(warning);
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
plugins: [
|
|
37
|
+
tsConfigPaths({
|
|
38
|
+
projects: ['./tsconfig.json'],
|
|
39
|
+
}),
|
|
40
|
+
tailwindcss(),
|
|
41
|
+
],
|
|
42
|
+
},
|
|
43
|
+
});
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Hello World
|
|
3
|
+
description: |
|
|
4
|
+
Your first `document`
|
|
5
|
+
You'll love it!
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
Hey there! Fumadocs is a docs framework built for Next.js, but do you know it also works on Tanstack Start?
|
|
9
|
+
|
|
10
|
+
## Heading
|
|
11
|
+
|
|
12
|
+
Hello World!
|
|
13
|
+
|
|
14
|
+
<Cards>
|
|
15
|
+
<Card
|
|
16
|
+
title="Learn more about Tanstack Start"
|
|
17
|
+
href="https://tanstack.com/start"
|
|
18
|
+
/>
|
|
19
|
+
<Card title="Learn more about Fumadocs" href="https://fumadocs.vercel.app" />
|
|
20
|
+
</Cards>
|
|
21
|
+
|
|
22
|
+
### CodeBlock
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
console.log('Hello World');
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
#### Table
|
|
29
|
+
|
|
30
|
+
| Head | Description |
|
|
31
|
+
| ------------------------------- | ----------------------------------- |
|
|
32
|
+
| `hello` | Hello World |
|
|
33
|
+
| very **important** | Hey |
|
|
34
|
+
| _Surprisingly_ | Fumadocs |
|
|
35
|
+
| very long text that looks weird | hello world hello world hello world |
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import {
|
|
2
|
+
loader,
|
|
3
|
+
type MetaData,
|
|
4
|
+
type PageData,
|
|
5
|
+
type Source,
|
|
6
|
+
type VirtualFile,
|
|
7
|
+
} from 'fumadocs-core/source';
|
|
8
|
+
import matter from 'gray-matter';
|
|
9
|
+
import * as path from 'node:path';
|
|
10
|
+
import FastGlob from 'fast-glob';
|
|
11
|
+
import * as fs from 'node:fs';
|
|
12
|
+
|
|
13
|
+
let files: [string, string][];
|
|
14
|
+
|
|
15
|
+
if (typeof import.meta.glob === 'function') {
|
|
16
|
+
files = Object.entries(
|
|
17
|
+
import.meta.glob<true, 'raw'>('/content/docs/**/*', {
|
|
18
|
+
eager: true,
|
|
19
|
+
query: '?raw',
|
|
20
|
+
import: 'default',
|
|
21
|
+
}),
|
|
22
|
+
);
|
|
23
|
+
} else {
|
|
24
|
+
files = FastGlob.sync('content/docs/**/*').map((file) => {
|
|
25
|
+
return [file, fs.readFileSync(file).toString()];
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const virtualFiles: VirtualFile[] = files.flatMap(([file, content]) => {
|
|
30
|
+
const ext = path.extname(file);
|
|
31
|
+
const virtualPath = path.relative(
|
|
32
|
+
'content/docs',
|
|
33
|
+
path.join(process.cwd(), file),
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
if (ext === '.mdx' || ext === '.md') {
|
|
37
|
+
const parsed = matter(content);
|
|
38
|
+
|
|
39
|
+
return {
|
|
40
|
+
type: 'page',
|
|
41
|
+
path: virtualPath,
|
|
42
|
+
data: {
|
|
43
|
+
...parsed.data,
|
|
44
|
+
content: parsed.content,
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (ext === '.json') {
|
|
50
|
+
return {
|
|
51
|
+
type: 'meta',
|
|
52
|
+
path: virtualPath,
|
|
53
|
+
data: JSON.parse(content),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return [];
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
export const source = loader({
|
|
61
|
+
source: {
|
|
62
|
+
files: virtualFiles,
|
|
63
|
+
} as Source<{
|
|
64
|
+
pageData: PageData & {
|
|
65
|
+
content: string;
|
|
66
|
+
};
|
|
67
|
+
metaData: MetaData;
|
|
68
|
+
}>,
|
|
69
|
+
baseUrl: '/docs',
|
|
70
|
+
});
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"jsx": "react-jsx",
|
|
4
|
+
"moduleResolution": "Bundler",
|
|
5
|
+
"lib": ["DOM", "DOM.Iterable", "ESNext"],
|
|
6
|
+
"types": ["node", "vite/client"],
|
|
7
|
+
"module": "ESNext",
|
|
8
|
+
"target": "ESNext",
|
|
9
|
+
"skipLibCheck": true,
|
|
10
|
+
"strictNullChecks": true,
|
|
11
|
+
"paths": {
|
|
12
|
+
"@/*": ["./*"]
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
/package/template/{content-collections → +next+content-collections}/app/docs/[[...slug]]/page.tsx
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|