create-fumadocs-app 15.6.3 → 15.6.4

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.
@@ -1,4 +1,10 @@
1
- routeTree.gen.ts
2
1
  node_modules
2
+
3
+ .DS_Store
4
+ .cache
5
+ .vercel
3
6
  .output
4
- .vinxi
7
+ .nitro
8
+ /build/
9
+
10
+ .tanstack
@@ -0,0 +1,34 @@
1
+ {
2
+ "private": true,
3
+ "sideEffects": false,
4
+ "type": "module",
5
+ "scripts": {
6
+ "dev": "vite dev",
7
+ "build": "vite build && tsc --noEmit",
8
+ "start": "node .output/server/index.mjs"
9
+ },
10
+ "dependencies": {
11
+ "@fumadocs/mdx-remote": "workspace:*",
12
+ "@tanstack/react-router": "^1.127.8",
13
+ "@tanstack/react-router-devtools": "^1.127.8",
14
+ "@tanstack/react-start": "^1.127.8",
15
+ "fumadocs-core": "workspace:*",
16
+ "fumadocs-ui": "workspace:*",
17
+ "gray-matter": "^4.0.3",
18
+ "lucide-static": "^0.525.0",
19
+ "react": "^19.0.0",
20
+ "react-dom": "^19.0.0",
21
+ "tailwind-merge": "^3.3.1",
22
+ "vite": "^7.0.4",
23
+ "zod": "^4.0.5"
24
+ },
25
+ "devDependencies": {
26
+ "@tailwindcss/vite": "^4.1.11",
27
+ "@types/node": "^24.0.13",
28
+ "@types/react": "^19.0.8",
29
+ "@types/react-dom": "^19.0.3",
30
+ "tailwindcss": "^4.1.11",
31
+ "typescript": "^5.7.2",
32
+ "vite-tsconfig-paths": "^5.1.4"
33
+ }
34
+ }
@@ -7,31 +7,19 @@ import {
7
7
  } from 'fumadocs-core/source';
8
8
  import matter from 'gray-matter';
9
9
  import * as path from 'node:path';
10
- import { globSync } from 'tinyglobby';
11
- import * as fs from 'node:fs';
10
+ import * as icons from 'lucide-static';
12
11
 
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 = globSync('content/docs/**/*').map((file) => {
25
- return [file, fs.readFileSync(file).toString()];
26
- });
27
- }
12
+ const files = Object.entries(
13
+ import.meta.glob<true, 'raw'>('/content/**/*', {
14
+ eager: true,
15
+ query: '?raw',
16
+ import: 'default',
17
+ }),
18
+ );
28
19
 
29
20
  const virtualFiles: VirtualFile[] = files.flatMap(([file, content]) => {
30
21
  const ext = path.extname(file);
31
- const virtualPath = path.relative(
32
- 'content/docs',
33
- path.join(process.cwd(), file),
34
- );
22
+ const virtualPath = path.relative('content', path.join(process.cwd(), file));
35
23
 
36
24
  if (ext === '.mdx' || ext === '.md') {
37
25
  const parsed = matter(content);
@@ -67,4 +55,12 @@ export const source = loader({
67
55
  metaData: MetaData;
68
56
  }>,
69
57
  baseUrl: '/docs',
58
+ // @ts-expect-error -- string
59
+ icon(icon) {
60
+ if (!icon) {
61
+ return;
62
+ }
63
+
64
+ if (icon in icons) return icons[icon as keyof typeof icons];
65
+ },
70
66
  });
@@ -4,6 +4,7 @@ import { routeTree } from './routeTree.gen';
4
4
  export function createRouter() {
5
5
  return createTanStackRouter({
6
6
  routeTree,
7
+ defaultPreload: 'intent',
7
8
  scrollRestoration: true,
8
9
  });
9
10
  }
@@ -1,12 +1,13 @@
1
- import { type ReactNode } from 'react';
1
+ /// <reference types="vite/client" />
2
2
  import {
3
3
  createRootRoute,
4
4
  HeadContent,
5
5
  Outlet,
6
6
  Scripts,
7
7
  } from '@tanstack/react-router';
8
+ import * as React from 'react';
9
+ import appCss from '~/styles/app.css?url';
8
10
  import { RootProvider } from 'fumadocs-ui/provider/base';
9
- import appCss from '../app.css?url';
10
11
  import { TanstackProvider } from 'fumadocs-core/framework/tanstack';
11
12
 
12
13
  export const Route = createRootRoute({
@@ -36,7 +37,7 @@ function RootComponent() {
36
37
  );
37
38
  }
38
39
 
39
- function RootDocument({ children }: Readonly<{ children: ReactNode }>) {
40
+ function RootDocument({ children }: { children: React.ReactNode }) {
40
41
  return (
41
42
  <html suppressHydrationWarning>
42
43
  <head>
@@ -1,20 +1,17 @@
1
- import { createAPIFileRoute } from '@tanstack/react-start/api';
1
+ import { createServerFileRoute } from '@tanstack/react-start/server';
2
2
  import { createSearchAPI } from 'fumadocs-core/search/server';
3
- import { source } from '@/lib/source';
3
+ import { source } from '~/lib/source';
4
4
  import { structure } from 'fumadocs-core/mdx-plugins';
5
5
 
6
6
  const server = createSearchAPI('advanced', {
7
7
  indexes: source.getPages().map((page) => ({
8
8
  id: page.url,
9
9
  url: page.url,
10
- title: page.data.title ?? '',
11
- description: page.data.description,
10
+ title: page.data.title!,
12
11
  structuredData: structure(page.data.content),
13
12
  })),
14
13
  });
15
14
 
16
- export const APIRoute = createAPIFileRoute('/api/search')({
17
- GET: ({ request }) => {
18
- return server.GET(request);
19
- },
15
+ export const ServerRoute = createServerFileRoute('/api/search').methods({
16
+ GET: async ({ request }) => server.GET(request),
20
17
  });
@@ -1,32 +1,31 @@
1
1
  import { createFileRoute, notFound } from '@tanstack/react-router';
2
+ import { executeMdxSync } from '@fumadocs/mdx-remote/client';
2
3
  import { DocsLayout } from 'fumadocs-ui/layouts/docs';
3
- import { source } from '@/lib/source';
4
4
  import {
5
5
  DocsBody,
6
6
  DocsDescription,
7
7
  DocsPage,
8
8
  DocsTitle,
9
9
  } from 'fumadocs-ui/page';
10
- import { executeMdxSync } from '@fumadocs/mdx-remote/client';
11
- import defaultMdxComponents from 'fumadocs-ui/mdx';
12
10
  import { createServerFn } from '@tanstack/react-start';
13
- import type { PageTree } from 'fumadocs-core/server';
14
11
  import { createCompiler } from '@fumadocs/mdx-remote';
15
- import * as path from 'node:path';
12
+ import { source } from '~/lib/source';
13
+ import path from 'node:path';
14
+ import defaultMdxComponents from 'fumadocs-ui/mdx';
15
+ import type { PageTree } from 'fumadocs-core/server';
16
+ import { useMemo } from 'react';
17
+
18
+ const compiler = createCompiler();
16
19
 
17
20
  export const Route = createFileRoute('/docs/$')({
18
21
  component: Page,
19
- async loader({ params }) {
22
+ loader: async ({ params }) => {
20
23
  const slugs = (params._splat ?? '').split('/');
21
-
22
24
  return loader({ data: slugs });
23
25
  },
24
26
  });
25
27
 
26
- const compiler = createCompiler({
27
- development: false,
28
- });
29
-
28
+ // a wrapper because we don't want `loader` to be called on client-side
30
29
  const loader = createServerFn({
31
30
  method: 'GET',
32
31
  })
@@ -37,7 +36,7 @@ const loader = createServerFn({
37
36
 
38
37
  const { content, ...rest } = page.data;
39
38
  const compiled = await compiler.compileFile({
40
- path: path.resolve('content/docs', page.file.path),
39
+ path: path.resolve('content', page.path),
41
40
  value: content,
42
41
  });
43
42
 
@@ -49,21 +48,51 @@ const loader = createServerFn({
49
48
  });
50
49
 
51
50
  function Page() {
52
- const { tree, compiled, ...data } = Route.useLoaderData();
53
- const { toc, default: MdxContent } = executeMdxSync(compiled);
51
+ const data = Route.useLoaderData();
52
+ const {
53
+ default: MDX,
54
+ toc,
55
+ tree,
56
+ } = useMemo(() => {
57
+ const result = executeMdxSync(data.compiled);
58
+
59
+ function traverse(folder: PageTree.Folder | PageTree.Root) {
60
+ for (const node of folder.children) {
61
+ if (node.type === 'page' && typeof node.icon === 'string') {
62
+ node.icon = (
63
+ <span
64
+ dangerouslySetInnerHTML={{
65
+ __html: node.icon,
66
+ }}
67
+ />
68
+ );
69
+ }
70
+
71
+ if (node.type === 'folder') traverse(node);
72
+ }
73
+ }
74
+
75
+ const tree = structuredClone(data.tree) as PageTree.Root;
76
+ traverse(tree);
77
+ return { ...result, tree };
78
+ }, [data]);
54
79
 
55
80
  return (
56
81
  <DocsLayout
82
+ tree={tree}
57
83
  nav={{
58
- title: 'Tanstack Start',
84
+ title: 'Fumadocs Tanstack',
59
85
  }}
60
- tree={tree as PageTree.Root}
61
86
  >
62
87
  <DocsPage toc={toc}>
63
88
  <DocsTitle>{data.title}</DocsTitle>
64
- <DocsDescription>{data.title}</DocsDescription>
89
+ <DocsDescription>{data.description}</DocsDescription>
65
90
  <DocsBody>
66
- <MdxContent components={defaultMdxComponents} />
91
+ <MDX
92
+ components={{
93
+ ...defaultMdxComponents,
94
+ }}
95
+ />
67
96
  </DocsBody>
68
97
  </DocsPage>
69
98
  </DocsLayout>
@@ -11,11 +11,14 @@ function Home() {
11
11
  nav={{
12
12
  title: 'Tanstack Start',
13
13
  }}
14
- className="text-center py-32"
14
+ className="text-center py-32 justify-center"
15
15
  >
16
16
  <h1 className="font-medium text-xl mb-4">Fumadocs on Tanstack Start.</h1>
17
17
  <Link
18
18
  to="/docs/$"
19
+ params={{
20
+ _splat: '',
21
+ }}
19
22
  className="px-3 py-2 rounded-lg bg-fd-primary text-fd-primary-foreground font-medium text-sm mx-auto"
20
23
  >
21
24
  Open Docs
@@ -1,15 +1,22 @@
1
1
  {
2
+ "include": ["**/*.ts", "**/*.tsx"],
2
3
  "compilerOptions": {
4
+ "strict": true,
5
+ "esModuleInterop": true,
3
6
  "jsx": "react-jsx",
4
- "moduleResolution": "Bundler",
5
- "lib": ["DOM", "DOM.Iterable", "ESNext"],
6
- "types": ["node", "vite/client"],
7
7
  "module": "ESNext",
8
- "target": "ESNext",
8
+ "moduleResolution": "Bundler",
9
+ "lib": ["DOM", "DOM.Iterable", "ES2022"],
10
+ "isolatedModules": true,
11
+ "resolveJsonModule": true,
9
12
  "skipLibCheck": true,
10
- "strictNullChecks": true,
13
+ "target": "ES2022",
14
+ "allowJs": true,
15
+ "forceConsistentCasingInFileNames": true,
16
+ "baseUrl": ".",
11
17
  "paths": {
12
- "@/*": ["./*"]
13
- }
18
+ "~/*": ["./src/*"]
19
+ },
20
+ "noEmit": true
14
21
  }
15
22
  }
@@ -0,0 +1,17 @@
1
+ import { tanstackStart } from '@tanstack/react-start/plugin/vite';
2
+ import { defineConfig } from 'vite';
3
+ import tsConfigPaths from 'vite-tsconfig-paths';
4
+ import tailwindcss from '@tailwindcss/vite';
5
+
6
+ export default defineConfig({
7
+ server: {
8
+ port: 3000,
9
+ },
10
+ plugins: [
11
+ tailwindcss(),
12
+ tsConfigPaths({
13
+ projects: ['./tsconfig.json'],
14
+ }),
15
+ tanstackStart(),
16
+ ],
17
+ });