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.
Files changed (30) hide show
  1. package/dist/{chunk-R4Y2JVJN.js → chunk-ZA7GBGFG.js} +57 -21
  2. package/dist/create-app.js +1 -1
  3. package/dist/index.js +18 -7
  4. package/package.json +2 -2
  5. package/template/react-router/app/docs/page.tsx +6 -6
  6. package/template/tanstack-start/README.md +12 -0
  7. package/template/tanstack-start/app/api.ts +6 -0
  8. package/template/tanstack-start/app/app.css +6 -0
  9. package/template/tanstack-start/app/client.tsx +7 -0
  10. package/template/tanstack-start/app/router.tsx +15 -0
  11. package/template/tanstack-start/app/routes/__root.tsx +49 -0
  12. package/template/tanstack-start/app/routes/api/search.ts +20 -0
  13. package/template/tanstack-start/app/routes/docs/$.tsx +71 -0
  14. package/template/tanstack-start/app/routes/index.tsx +25 -0
  15. package/template/tanstack-start/app/ssr.tsx +13 -0
  16. package/template/tanstack-start/app.config.ts +43 -0
  17. package/template/tanstack-start/content/docs/index.mdx +35 -0
  18. package/template/tanstack-start/example.gitignore +4 -0
  19. package/template/tanstack-start/lib/source.ts +70 -0
  20. package/template/tanstack-start/tsconfig.json +15 -0
  21. /package/template/{content-collections → +next+content-collections}/app/docs/[[...slug]]/page.tsx +0 -0
  22. /package/template/{content-collections → +next+content-collections}/content-collections.ts +0 -0
  23. /package/template/{content-collections → +next+content-collections}/lib/source.ts +0 -0
  24. /package/template/{content-collections → +next+content-collections}/next.config.mjs +0 -0
  25. /package/template/{content-collections → +next+content-collections}/tsconfig.json +0 -0
  26. /package/template/{fuma-docs-mdx → +next+fuma-docs-mdx}/app/docs/[[...slug]]/page.tsx +0 -0
  27. /package/template/{fuma-docs-mdx → +next+fuma-docs-mdx}/lib/source.ts +0 -0
  28. /package/template/{fuma-docs-mdx → +next+fuma-docs-mdx}/next.config.mjs +0 -0
  29. /package/template/{fuma-docs-mdx → +next+fuma-docs-mdx}/source.config.ts +0 -0
  30. /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.0", "fumadocs-ui": "15.2.0", "fumadocs-mdx": "11.5.7", "@fumadocs/mdx-remote": "1.3.0", "@fumadocs/content-collections": "1.1.8" };
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.14",
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
- vite: "^6.2.3",
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 === "content-collections" || options.template === "fuma-docs-mdx";
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
- if (isNext) {
158
- for (const dir of ["app", "lib"]) {
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
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  create
3
- } from "./chunk-R4Y2JVJN.js";
3
+ } from "./chunk-ZA7GBGFG.js";
4
4
  export {
5
5
  create
6
6
  };
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  create,
4
4
  cwd,
5
5
  getPackageManager
6
- } from "./chunk-R4Y2JVJN.js";
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: () => confirm({ message: "Use `/src` directory?", initialValue: false }),
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 === "react-router") return;
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.0",
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.14",
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 = String(
31
- await compiler.compileFile({
32
- value: page.data.content,
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,12 @@
1
+ This is a Tanstack Start application generated with
2
+ [Create Fumadocs](https://github.com/fuma-nama/fumadocs).
3
+
4
+ Run development server:
5
+
6
+ ```bash
7
+ npm run dev
8
+ # or
9
+ pnpm dev
10
+ # or
11
+ yarn dev
12
+ ```
@@ -0,0 +1,6 @@
1
+ import {
2
+ createStartAPIHandler,
3
+ defaultAPIFileRouteHandler,
4
+ } from '@tanstack/react-start/api';
5
+
6
+ export default createStartAPIHandler(defaultAPIFileRouteHandler);
@@ -0,0 +1,6 @@
1
+ @import 'tailwindcss';
2
+ @import 'fumadocs-ui/css/neutral.css';
3
+ @import 'fumadocs-ui/css/preset.css';
4
+
5
+ /* path of `fumadocs-ui` relative to the CSS file */
6
+ @source '../node_modules/fumadocs-ui/dist/**/*.js';
@@ -0,0 +1,7 @@
1
+ import { hydrateRoot } from 'react-dom/client';
2
+ import { StartClient } from '@tanstack/react-start';
3
+ import { createRouter } from './router';
4
+
5
+ const router = createRouter();
6
+
7
+ hydrateRoot(document, <StartClient router={router} />);
@@ -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,4 @@
1
+ routeTree.gen.ts
2
+ node_modules
3
+ .output
4
+ .vinxi
@@ -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
+ }