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.
- package/dist/chunk-KW5K7PMS.js +330 -0
- package/dist/create-app.d.ts +5 -3
- package/dist/create-app.js +5 -3
- package/dist/index.js +84 -38
- package/package.json +5 -4
- package/template/react-router/app/docs/page.tsx +4 -8
- package/template/react-router/app/routes/home.tsx +2 -3
- package/template/react-router/content/docs/test.mdx +20 -4
- package/template/react-router/package.json +35 -0
- package/template/tanstack-start/content/{docs/index.mdx → index.mdx} +2 -3
- package/template/tanstack-start/content/test.mdx +10 -0
- package/template/tanstack-start/example.gitignore +8 -2
- package/template/tanstack-start/package.json +34 -0
- package/template/tanstack-start/{lib → src/lib}/source.ts +17 -21
- package/template/tanstack-start/{app → src}/router.tsx +1 -0
- package/template/tanstack-start/{app → src}/routes/__root.tsx +4 -3
- package/template/tanstack-start/{app → src}/routes/api/search.ts +5 -8
- package/template/tanstack-start/{app → src}/routes/docs/$.tsx +47 -18
- package/template/tanstack-start/{app → src}/routes/index.tsx +4 -1
- package/template/tanstack-start/tsconfig.json +14 -7
- package/template/tanstack-start/vite.config.ts +17 -0
- package/dist/chunk-FAFA6275.js +0 -380
- package/template/tanstack-start/app/api.ts +0 -6
- package/template/tanstack-start/app/client.tsx +0 -7
- package/template/tanstack-start/app/ssr.tsx +0 -13
- package/template/tanstack-start/app.config.ts +0 -43
- /package/template/tanstack-start/{app → src/styles}/app.css +0 -0
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
// src/create-app.ts
|
|
2
|
+
import path from "path";
|
|
3
|
+
import fs2 from "fs/promises";
|
|
4
|
+
|
|
5
|
+
// src/git.ts
|
|
6
|
+
import * as fs from "fs/promises";
|
|
7
|
+
import { join } from "path";
|
|
8
|
+
import { x } from "tinyexec";
|
|
9
|
+
async function isInGitRepository(cwd2) {
|
|
10
|
+
const { exitCode } = await x("git", ["rev-parse", "--is-inside-work-tree"], {
|
|
11
|
+
nodeOptions: { cwd: cwd2 }
|
|
12
|
+
});
|
|
13
|
+
return exitCode !== 0;
|
|
14
|
+
}
|
|
15
|
+
async function isDefaultBranchSet(cwd2) {
|
|
16
|
+
const { exitCode } = await x("git", ["config", "init.defaultBranch"], {
|
|
17
|
+
nodeOptions: { cwd: cwd2 }
|
|
18
|
+
});
|
|
19
|
+
return exitCode !== 0;
|
|
20
|
+
}
|
|
21
|
+
async function tryGitInit(cwd2) {
|
|
22
|
+
const { exitCode } = await x("git", ["--version"]);
|
|
23
|
+
if (exitCode !== 0) return false;
|
|
24
|
+
if (await isInGitRepository(cwd2)) return false;
|
|
25
|
+
try {
|
|
26
|
+
await x("git", ["init"], {
|
|
27
|
+
throwOnError: true,
|
|
28
|
+
nodeOptions: { cwd: cwd2 }
|
|
29
|
+
});
|
|
30
|
+
if (!await isDefaultBranchSet(cwd2)) {
|
|
31
|
+
await x("git", ["checkout", "-b", "main"], {
|
|
32
|
+
throwOnError: true,
|
|
33
|
+
nodeOptions: {
|
|
34
|
+
cwd: cwd2
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
await x("git", ["add", "-A"], {
|
|
39
|
+
throwOnError: true,
|
|
40
|
+
nodeOptions: {
|
|
41
|
+
cwd: cwd2
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
await x(
|
|
45
|
+
"git",
|
|
46
|
+
["commit", "-m", "Initial commit from Create Fumadocs App"],
|
|
47
|
+
{
|
|
48
|
+
throwOnError: true,
|
|
49
|
+
nodeOptions: {
|
|
50
|
+
cwd: cwd2
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
);
|
|
54
|
+
return true;
|
|
55
|
+
} catch {
|
|
56
|
+
await fs.rmdir(join(cwd2, ".git"), { recursive: true }).catch(() => null);
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// src/versions.js
|
|
62
|
+
var versions = { "fumadocs-core": "15.6.4", "fumadocs-ui": "15.6.4", "fumadocs-mdx": "11.6.11", "@fumadocs/mdx-remote": "1.3.4", "@fumadocs/content-collections": "1.2.1" };
|
|
63
|
+
|
|
64
|
+
// ../create-app-versions/package.json
|
|
65
|
+
var package_default = {
|
|
66
|
+
name: "example-versions",
|
|
67
|
+
version: "0.0.0",
|
|
68
|
+
private: true,
|
|
69
|
+
description: "Used to track dependency versions in create-fumadocs-app",
|
|
70
|
+
license: "MIT",
|
|
71
|
+
dependencies: {
|
|
72
|
+
"@content-collections/core": "^0.10.0",
|
|
73
|
+
"@content-collections/mdx": "^0.2.2",
|
|
74
|
+
"@content-collections/next": "^0.2.6",
|
|
75
|
+
"@react-router/dev": "^7.6.3",
|
|
76
|
+
"@react-router/node": "^7.6.3",
|
|
77
|
+
"@react-router/serve": "^7.6.3",
|
|
78
|
+
"@tailwindcss/postcss": "^4.1.11",
|
|
79
|
+
"@tailwindcss/vite": "^4.1.11",
|
|
80
|
+
"@tanstack/react-router": "^1.127.8",
|
|
81
|
+
"@tanstack/react-start": "^1.127.8",
|
|
82
|
+
"@types/mdx": "^2.0.13",
|
|
83
|
+
"@types/node": "24.0.13",
|
|
84
|
+
"@types/react": "^19.1.8",
|
|
85
|
+
"@types/react-dom": "^19.1.6",
|
|
86
|
+
"@vitejs/plugin-react": "^4.6.0",
|
|
87
|
+
"gray-matter": "^4.0.3",
|
|
88
|
+
isbot: "^5.1.28",
|
|
89
|
+
next: "15.4.1",
|
|
90
|
+
postcss: "^8.5.6",
|
|
91
|
+
react: "^19.1.0",
|
|
92
|
+
"react-dom": "^19.1.0",
|
|
93
|
+
"react-router": "^7.6.3",
|
|
94
|
+
"react-router-devtools": "^5.0.6",
|
|
95
|
+
shiki: "^3.8.0",
|
|
96
|
+
tailwindcss: "^4.1.11",
|
|
97
|
+
tinyglobby: "^0.2.14",
|
|
98
|
+
typescript: "^5.8.3",
|
|
99
|
+
vinxi: "^0.5.8",
|
|
100
|
+
vite: "^7.0.4",
|
|
101
|
+
"vite-tsconfig-paths": "^5.1.4"
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
// src/auto-install.ts
|
|
106
|
+
import { x as x2 } from "tinyexec";
|
|
107
|
+
var managers = ["npm", "yarn", "bun", "pnpm"];
|
|
108
|
+
function getPackageManager() {
|
|
109
|
+
const userAgent = process.env.npm_config_user_agent ?? "";
|
|
110
|
+
if (userAgent.startsWith("yarn")) {
|
|
111
|
+
return "yarn";
|
|
112
|
+
}
|
|
113
|
+
if (userAgent.startsWith("pnpm")) {
|
|
114
|
+
return "pnpm";
|
|
115
|
+
}
|
|
116
|
+
if (userAgent.startsWith("bun")) {
|
|
117
|
+
return "bun";
|
|
118
|
+
}
|
|
119
|
+
return "npm";
|
|
120
|
+
}
|
|
121
|
+
async function autoInstall(manager, dest) {
|
|
122
|
+
await x2(manager, ["install"], {
|
|
123
|
+
throwOnError: true,
|
|
124
|
+
nodeOptions: {
|
|
125
|
+
env: {
|
|
126
|
+
...process.env,
|
|
127
|
+
NODE_ENV: "development",
|
|
128
|
+
DISABLE_OPENCOLLECTIVE: "1"
|
|
129
|
+
},
|
|
130
|
+
cwd: dest
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// src/constants.ts
|
|
136
|
+
import { fileURLToPath } from "url";
|
|
137
|
+
var sourceDir = fileURLToPath(new URL(`../`, import.meta.url).href);
|
|
138
|
+
var cwd = process.cwd();
|
|
139
|
+
|
|
140
|
+
// src/create-app.ts
|
|
141
|
+
var templates = [
|
|
142
|
+
"+next+content-collections",
|
|
143
|
+
"+next+fuma-docs-mdx",
|
|
144
|
+
"react-router",
|
|
145
|
+
"tanstack-start"
|
|
146
|
+
];
|
|
147
|
+
async function create(options) {
|
|
148
|
+
const {
|
|
149
|
+
installDeps = true,
|
|
150
|
+
initializeGit = true,
|
|
151
|
+
log = console.log
|
|
152
|
+
} = options;
|
|
153
|
+
const projectName = path.basename(options.outputDir);
|
|
154
|
+
const dest = path.resolve(cwd, options.outputDir);
|
|
155
|
+
const isNext = options.template.startsWith("+next");
|
|
156
|
+
function isRelative(dir, file) {
|
|
157
|
+
return !path.relative(path.join(dest, dir), file).startsWith(`..${path.sep}`);
|
|
158
|
+
}
|
|
159
|
+
function defaultRename(file) {
|
|
160
|
+
file = file.replace("example.gitignore", ".gitignore");
|
|
161
|
+
if (!options.useSrcDir || !isNext) {
|
|
162
|
+
return file;
|
|
163
|
+
}
|
|
164
|
+
if (path.basename(file) === "mdx-components.tsx" || isRelative("app", file) || isRelative("lib", file)) {
|
|
165
|
+
return path.join(dest, "src", path.relative(dest, file));
|
|
166
|
+
}
|
|
167
|
+
return file;
|
|
168
|
+
}
|
|
169
|
+
if (isNext) {
|
|
170
|
+
await copy(path.join(sourceDir, `template/+next`), dest, defaultRename);
|
|
171
|
+
await copy(
|
|
172
|
+
path.join(sourceDir, `template/${options.template}`),
|
|
173
|
+
dest,
|
|
174
|
+
defaultRename
|
|
175
|
+
);
|
|
176
|
+
if (options.tailwindcss) {
|
|
177
|
+
await copy(
|
|
178
|
+
path.join(sourceDir, `template/+next+tailwindcss`),
|
|
179
|
+
dest,
|
|
180
|
+
defaultRename
|
|
181
|
+
);
|
|
182
|
+
log("Configured Tailwind CSS");
|
|
183
|
+
}
|
|
184
|
+
if (options.eslint) {
|
|
185
|
+
await copy(
|
|
186
|
+
path.join(sourceDir, `template/+next+eslint`),
|
|
187
|
+
dest,
|
|
188
|
+
defaultRename
|
|
189
|
+
);
|
|
190
|
+
log("Configured ESLint");
|
|
191
|
+
}
|
|
192
|
+
if (options.useSrcDir) {
|
|
193
|
+
const tsconfigPath = path.join(dest, "tsconfig.json");
|
|
194
|
+
const content = (await fs2.readFile(tsconfigPath)).toString();
|
|
195
|
+
const config = JSON.parse(content);
|
|
196
|
+
if (config.compilerOptions?.paths) {
|
|
197
|
+
Object.assign(config.compilerOptions.paths, {
|
|
198
|
+
"@/*": ["./src/*"]
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
await fs2.writeFile(tsconfigPath, JSON.stringify(config, null, 2));
|
|
202
|
+
}
|
|
203
|
+
} else {
|
|
204
|
+
await copy(
|
|
205
|
+
path.join(sourceDir, `template/${options.template}`),
|
|
206
|
+
dest,
|
|
207
|
+
defaultRename
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
const packageJson = await createPackageJson(projectName, dest, options);
|
|
211
|
+
await fs2.writeFile(
|
|
212
|
+
path.join(dest, "package.json"),
|
|
213
|
+
JSON.stringify(packageJson, null, 2)
|
|
214
|
+
);
|
|
215
|
+
const readMe = await getReadme(dest, projectName);
|
|
216
|
+
await fs2.writeFile(path.join(dest, "README.md"), readMe);
|
|
217
|
+
if (installDeps) {
|
|
218
|
+
try {
|
|
219
|
+
await autoInstall(options.packageManager, dest);
|
|
220
|
+
log("Installed dependencies");
|
|
221
|
+
} catch (err) {
|
|
222
|
+
log(`Failed to install dependencies: ${err}`);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
if (initializeGit && await tryGitInit(dest)) {
|
|
226
|
+
log("Initialized Git repository");
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
async function getReadme(dest, projectName) {
|
|
230
|
+
const template = await fs2.readFile(path.join(dest, "README.md")).then((res) => res.toString());
|
|
231
|
+
return `# ${projectName}
|
|
232
|
+
|
|
233
|
+
${template}`;
|
|
234
|
+
}
|
|
235
|
+
async function copy(from, to, rename = (s) => s) {
|
|
236
|
+
const stats = await fs2.stat(from);
|
|
237
|
+
if (stats.isDirectory()) {
|
|
238
|
+
const files = await fs2.readdir(from);
|
|
239
|
+
await Promise.all(
|
|
240
|
+
files.map(
|
|
241
|
+
(file) => copy(path.join(from, file), rename(path.join(to, file)))
|
|
242
|
+
)
|
|
243
|
+
);
|
|
244
|
+
} else {
|
|
245
|
+
await fs2.mkdir(path.dirname(to), { recursive: true });
|
|
246
|
+
await fs2.copyFile(from, to);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
async function createPackageJson(projectName, dir, options) {
|
|
250
|
+
function replaceWorkspaceDeps(deps) {
|
|
251
|
+
for (const k in deps) {
|
|
252
|
+
if (deps[k].startsWith("workspace:") && k in versions) {
|
|
253
|
+
deps[k] = versions[k];
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
return deps;
|
|
257
|
+
}
|
|
258
|
+
if (options.template === "tanstack-start" || options.template === "react-router") {
|
|
259
|
+
const packageJson = JSON.parse(
|
|
260
|
+
await fs2.readFile(path.join(dir, "package.json")).then((res) => res.toString())
|
|
261
|
+
);
|
|
262
|
+
return {
|
|
263
|
+
name: projectName,
|
|
264
|
+
...packageJson,
|
|
265
|
+
dependencies: replaceWorkspaceDeps(packageJson.dependencies),
|
|
266
|
+
devDependencies: replaceWorkspaceDeps(packageJson.devDependencies)
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
return {
|
|
270
|
+
name: projectName,
|
|
271
|
+
version: "0.0.0",
|
|
272
|
+
private: true,
|
|
273
|
+
scripts: {
|
|
274
|
+
build: "next build",
|
|
275
|
+
dev: "next dev --turbo",
|
|
276
|
+
start: "next start",
|
|
277
|
+
...options.template === "+next+fuma-docs-mdx" ? {
|
|
278
|
+
postinstall: "fumadocs-mdx"
|
|
279
|
+
} : null
|
|
280
|
+
},
|
|
281
|
+
dependencies: {
|
|
282
|
+
...pick(package_default.dependencies, ["next", "react", "react-dom"]),
|
|
283
|
+
...pick(versions, ["fumadocs-ui", "fumadocs-core"]),
|
|
284
|
+
...options.template === "+next+content-collections" ? {
|
|
285
|
+
...pick(package_default.dependencies, [
|
|
286
|
+
"@content-collections/mdx",
|
|
287
|
+
"@content-collections/core",
|
|
288
|
+
"@content-collections/next"
|
|
289
|
+
]),
|
|
290
|
+
...pick(versions, ["@fumadocs/content-collections"])
|
|
291
|
+
} : null,
|
|
292
|
+
...options.template === "+next+fuma-docs-mdx" ? pick(versions, ["fumadocs-mdx"]) : null
|
|
293
|
+
},
|
|
294
|
+
devDependencies: {
|
|
295
|
+
...pick(package_default.dependencies, [
|
|
296
|
+
"@types/node",
|
|
297
|
+
"@types/react",
|
|
298
|
+
"@types/react-dom",
|
|
299
|
+
"typescript",
|
|
300
|
+
"@types/mdx"
|
|
301
|
+
]),
|
|
302
|
+
...options.tailwindcss ? pick(package_default.dependencies, [
|
|
303
|
+
"@tailwindcss/postcss",
|
|
304
|
+
"tailwindcss",
|
|
305
|
+
"postcss"
|
|
306
|
+
]) : null,
|
|
307
|
+
...options.eslint ? {
|
|
308
|
+
eslint: "^8",
|
|
309
|
+
"eslint-config-next": package_default.dependencies.next
|
|
310
|
+
} : null
|
|
311
|
+
}
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
function pick(obj, keys) {
|
|
315
|
+
const result = {};
|
|
316
|
+
for (const key of keys) {
|
|
317
|
+
if (key in obj) {
|
|
318
|
+
result[key] = obj[key];
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
return result;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
export {
|
|
325
|
+
managers,
|
|
326
|
+
getPackageManager,
|
|
327
|
+
cwd,
|
|
328
|
+
templates,
|
|
329
|
+
create
|
|
330
|
+
};
|
package/dist/create-app.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
type PackageManager =
|
|
1
|
+
type PackageManager = (typeof managers)[number];
|
|
2
|
+
declare const managers: readonly ["npm", "yarn", "bun", "pnpm"];
|
|
2
3
|
|
|
3
|
-
|
|
4
|
+
declare const templates: readonly ["+next+content-collections", "+next+fuma-docs-mdx", "react-router", "tanstack-start"];
|
|
5
|
+
type Template = (typeof templates)[number];
|
|
4
6
|
interface Options {
|
|
5
7
|
outputDir: string;
|
|
6
8
|
template: Template;
|
|
@@ -32,4 +34,4 @@ interface Options {
|
|
|
32
34
|
}
|
|
33
35
|
declare function create(options: Options): Promise<void>;
|
|
34
36
|
|
|
35
|
-
export { type Options, type Template, create };
|
|
37
|
+
export { type Options, type Template, create, templates };
|
package/dist/create-app.js
CHANGED
package/dist/index.js
CHANGED
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
import {
|
|
3
3
|
create,
|
|
4
4
|
cwd,
|
|
5
|
-
getPackageManager
|
|
6
|
-
|
|
5
|
+
getPackageManager,
|
|
6
|
+
managers,
|
|
7
|
+
templates
|
|
8
|
+
} from "./chunk-KW5K7PMS.js";
|
|
7
9
|
|
|
8
10
|
// src/index.ts
|
|
9
11
|
import fs from "fs/promises";
|
|
@@ -20,42 +22,77 @@ import {
|
|
|
20
22
|
text
|
|
21
23
|
} from "@clack/prompts";
|
|
22
24
|
import pc from "picocolors";
|
|
23
|
-
|
|
24
|
-
|
|
25
|
+
import { program } from "commander";
|
|
26
|
+
program.argument("[name]", "the project name");
|
|
27
|
+
program.option("--src", "(Next.js only) enable `src/` directory");
|
|
28
|
+
program.option("--no-src", "(Next.js only) disable `src/` directory");
|
|
29
|
+
program.option("--eslint", "(Next.js only) enable ESLint configuration");
|
|
30
|
+
program.option("--no-eslint", "(Next.js only) disable ESLint configuration");
|
|
31
|
+
program.option("--install", "Enable installing packages automatically");
|
|
32
|
+
program.option("--no-install", "Disable installing packages automatically");
|
|
33
|
+
program.option(
|
|
34
|
+
"--template <name>",
|
|
35
|
+
`template to choose: ${templates.join(", ")}`,
|
|
36
|
+
(value) => {
|
|
37
|
+
if (!templates.includes(value)) {
|
|
38
|
+
throw new Error(`Invalid template: ${value}.`);
|
|
39
|
+
}
|
|
40
|
+
return value;
|
|
41
|
+
}
|
|
42
|
+
);
|
|
43
|
+
program.option(
|
|
44
|
+
"--pm <name>",
|
|
45
|
+
`package manager to choose: ${managers.join(", ")}`,
|
|
46
|
+
(value) => {
|
|
47
|
+
if (!managers.includes(value)) {
|
|
48
|
+
throw new Error(`Invalid package manager: ${value}.`);
|
|
49
|
+
}
|
|
50
|
+
return value;
|
|
51
|
+
}
|
|
52
|
+
);
|
|
53
|
+
async function main(config) {
|
|
25
54
|
intro(pc.bgCyan(pc.bold("Create Fumadocs App")));
|
|
55
|
+
const manager = config.pm ?? getPackageManager();
|
|
26
56
|
const options = await group(
|
|
27
57
|
{
|
|
28
|
-
name: () =>
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
58
|
+
name: () => {
|
|
59
|
+
if (config.name) return Promise.resolve(config.name);
|
|
60
|
+
return text({
|
|
61
|
+
message: "Project name",
|
|
62
|
+
placeholder: "my-app",
|
|
63
|
+
defaultValue: "my-app"
|
|
64
|
+
});
|
|
65
|
+
},
|
|
66
|
+
template: () => {
|
|
67
|
+
if (config.template) return Promise.resolve(config.template);
|
|
68
|
+
return select({
|
|
69
|
+
message: "Choose a template",
|
|
70
|
+
initialValue: "+next+fuma-docs-mdx",
|
|
71
|
+
options: [
|
|
72
|
+
{
|
|
73
|
+
value: "+next+fuma-docs-mdx",
|
|
74
|
+
label: "Next.js: Fumadocs MDX",
|
|
75
|
+
hint: "recommended"
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
value: "+next+content-collections",
|
|
79
|
+
label: "Next.js: Content Collections"
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
value: "react-router",
|
|
83
|
+
label: "React Router: MDX Remote"
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
value: "tanstack-start",
|
|
87
|
+
label: "Tanstack Start: MDX Remote",
|
|
88
|
+
hint: "Experimental"
|
|
89
|
+
}
|
|
90
|
+
]
|
|
91
|
+
});
|
|
92
|
+
},
|
|
57
93
|
src: (v) => {
|
|
58
94
|
if (!v.results.template?.startsWith("+next")) return;
|
|
95
|
+
if (config.src !== void 0) return Promise.resolve(config.src);
|
|
59
96
|
return confirm({
|
|
60
97
|
message: "Use `/src` directory?",
|
|
61
98
|
initialValue: false
|
|
@@ -63,14 +100,19 @@ async function main() {
|
|
|
63
100
|
},
|
|
64
101
|
eslint: (v) => {
|
|
65
102
|
if (!v.results.template?.startsWith("+next")) return;
|
|
103
|
+
if (config.eslint !== void 0) return Promise.resolve(config.eslint);
|
|
66
104
|
return confirm({
|
|
67
105
|
message: "Add default ESLint configuration?",
|
|
68
106
|
initialValue: false
|
|
69
107
|
});
|
|
70
108
|
},
|
|
71
|
-
installDeps: () =>
|
|
72
|
-
|
|
73
|
-
|
|
109
|
+
installDeps: () => {
|
|
110
|
+
if (config.install !== void 0)
|
|
111
|
+
return Promise.resolve(config.install);
|
|
112
|
+
return confirm({
|
|
113
|
+
message: `Do you want to install packages automatically? (detected as ${manager})`
|
|
114
|
+
});
|
|
115
|
+
}
|
|
74
116
|
},
|
|
75
117
|
{
|
|
76
118
|
onCancel: () => {
|
|
@@ -129,7 +171,11 @@ async function main() {
|
|
|
129
171
|
);
|
|
130
172
|
process.exit(0);
|
|
131
173
|
}
|
|
132
|
-
|
|
174
|
+
program.parse();
|
|
175
|
+
main({
|
|
176
|
+
name: program.args[0],
|
|
177
|
+
...program.opts()
|
|
178
|
+
}).catch((e) => {
|
|
133
179
|
console.error(e);
|
|
134
|
-
|
|
180
|
+
process.exit(1);
|
|
135
181
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-fumadocs-app",
|
|
3
|
-
"version": "15.6.
|
|
3
|
+
"version": "15.6.4",
|
|
4
4
|
"description": "Create a new documentation site with Fumadocs",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"NextJs",
|
|
@@ -22,12 +22,13 @@
|
|
|
22
22
|
],
|
|
23
23
|
"dependencies": {
|
|
24
24
|
"@clack/prompts": "^0.11.0",
|
|
25
|
-
"
|
|
26
|
-
"picocolors": "^1.1.1"
|
|
25
|
+
"commander": "^14.0.0",
|
|
26
|
+
"picocolors": "^1.1.1",
|
|
27
|
+
"tinyexec": "^1.0.1"
|
|
27
28
|
},
|
|
28
29
|
"devDependencies": {
|
|
29
30
|
"@types/cross-spawn": "^6.0.6",
|
|
30
|
-
"@types/node": "24.0.
|
|
31
|
+
"@types/node": "24.0.13",
|
|
31
32
|
"tinyglobby": "^0.2.14",
|
|
32
33
|
"eslint-config-custom": "0.0.0",
|
|
33
34
|
"tsconfig": "0.0.0"
|
|
@@ -13,12 +13,6 @@ import type { PageTree } from 'fumadocs-core/server';
|
|
|
13
13
|
import { createCompiler } from '@fumadocs/mdx-remote';
|
|
14
14
|
import * as path from 'node:path';
|
|
15
15
|
|
|
16
|
-
export function meta({}: Route.MetaArgs) {
|
|
17
|
-
return [
|
|
18
|
-
{ title: 'New React Router App' },
|
|
19
|
-
{ name: 'description', content: 'Welcome to React Router!' },
|
|
20
|
-
];
|
|
21
|
-
}
|
|
22
16
|
const compiler = createCompiler({
|
|
23
17
|
development: false,
|
|
24
18
|
});
|
|
@@ -26,10 +20,10 @@ const compiler = createCompiler({
|
|
|
26
20
|
export async function loader({ params }: Route.LoaderArgs) {
|
|
27
21
|
const slugs = params['*'].split('/').filter((v) => v.length > 0);
|
|
28
22
|
const page = source.getPage(slugs);
|
|
29
|
-
if (!page) throw new
|
|
23
|
+
if (!page) throw new Response('Not found', { status: 404 });
|
|
30
24
|
|
|
31
25
|
const compiled = await compiler.compileFile({
|
|
32
|
-
path: path.resolve('content/docs', page.
|
|
26
|
+
path: path.resolve('content/docs', page.path),
|
|
33
27
|
value: page.data.content,
|
|
34
28
|
});
|
|
35
29
|
|
|
@@ -51,6 +45,8 @@ export default function Page(props: Route.ComponentProps) {
|
|
|
51
45
|
}}
|
|
52
46
|
tree={tree as PageTree.Root}
|
|
53
47
|
>
|
|
48
|
+
<title>{page.data.title}</title>
|
|
49
|
+
<meta name="description" content={page.data.description} />
|
|
54
50
|
<DocsPage toc={toc}>
|
|
55
51
|
<DocsTitle>{page.data.title}</DocsTitle>
|
|
56
52
|
<DocsDescription>{page.data.description}</DocsDescription>
|
|
@@ -12,14 +12,13 @@ export function meta({}: Route.MetaArgs) {
|
|
|
12
12
|
export default function Home() {
|
|
13
13
|
return (
|
|
14
14
|
<HomeLayout
|
|
15
|
-
className="text-center"
|
|
16
15
|
nav={{
|
|
17
16
|
title: 'React Router',
|
|
18
17
|
}}
|
|
19
18
|
>
|
|
20
|
-
<div className="
|
|
19
|
+
<div className="p-4 flex flex-col items-center justify-center text-center flex-1">
|
|
21
20
|
<h1 className="text-xl font-bold mb-2">Fumadocs on React Router.</h1>
|
|
22
|
-
<p className="text-fd-muted-foreground mb-
|
|
21
|
+
<p className="text-fd-muted-foreground mb-4">
|
|
23
22
|
The truly flexible docs framework on React.js.
|
|
24
23
|
</p>
|
|
25
24
|
<Link
|
|
@@ -1,8 +1,24 @@
|
|
|
1
1
|
---
|
|
2
|
-
title:
|
|
3
|
-
description:
|
|
2
|
+
title: Test
|
|
3
|
+
description: A document to test Fumadocs
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
Hey there!
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
## Cards
|
|
9
|
+
|
|
10
|
+
<Cards>
|
|
11
|
+
<Card title="Learn more about Next.js" href="https://nextjs.org/docs" />
|
|
12
|
+
<Card title="Learn more about Fumadocs" href="https://fumadocs.vercel.app" />
|
|
13
|
+
</Cards>
|
|
14
|
+
|
|
15
|
+
### CodeBlock
|
|
16
|
+
|
|
17
|
+
```js
|
|
18
|
+
console.log('Hello World');
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
#### List
|
|
22
|
+
|
|
23
|
+
- Hello
|
|
24
|
+
- World
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"private": true,
|
|
3
|
+
"type": "module",
|
|
4
|
+
"scripts": {
|
|
5
|
+
"build": "react-router build",
|
|
6
|
+
"dev": "react-router dev",
|
|
7
|
+
"start": "react-router-serve ./build/server/index.js",
|
|
8
|
+
"typecheck": "react-router typegen && tsc"
|
|
9
|
+
},
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"@fumadocs/mdx-remote": "workspace:*",
|
|
12
|
+
"@react-router/node": "^7.6.3",
|
|
13
|
+
"@react-router/serve": "^7.6.3",
|
|
14
|
+
"fumadocs-core": "workspace:*",
|
|
15
|
+
"fumadocs-ui": "workspace:*",
|
|
16
|
+
"gray-matter": "^4.0.3",
|
|
17
|
+
"isbot": "^5.1.28",
|
|
18
|
+
"react": "^19.1.0",
|
|
19
|
+
"react-dom": "^19.1.0",
|
|
20
|
+
"react-router": "^7.6.3",
|
|
21
|
+
"shiki": "^3.8.0"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@react-router/dev": "^7.6.3",
|
|
25
|
+
"@tailwindcss/vite": "^4.1.11",
|
|
26
|
+
"@types/node": "^24.0.13",
|
|
27
|
+
"@types/react": "^19.1.8",
|
|
28
|
+
"@types/react-dom": "^19.1.6",
|
|
29
|
+
"react-router-devtools": "^5.0.6",
|
|
30
|
+
"tailwindcss": "^4.1.11",
|
|
31
|
+
"typescript": "^5.8.3",
|
|
32
|
+
"vite": "^7.0.4",
|
|
33
|
+
"vite-tsconfig-paths": "^5.1.4"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
title: Hello World
|
|
3
|
-
description:
|
|
4
|
-
|
|
5
|
-
You'll love it!
|
|
3
|
+
description: Your favourite docs framework.
|
|
4
|
+
icon: Rocket
|
|
6
5
|
---
|
|
7
6
|
|
|
8
7
|
Hey there! Fumadocs is a docs framework built for Next.js, but do you know it also works on Tanstack Start?
|