11import path from "node:path" ;
2- import { log } from "@clack/prompts" ;
2+ import { isCancel , log , select , spinner } from "@clack/prompts" ;
33import consola from "consola" ;
44import { execa } from "execa" ;
55import fs from "fs-extra" ;
66import pc from "picocolors" ;
77import type { ProjectConfig } from "../../types" ;
8+ import { exitCancelled } from "../../utils/errors" ;
89import { getPackageExecutionCommand } from "../../utils/package-runner" ;
910
11+ type FumadocsTemplate =
12+ | "next-mdx"
13+ | "waku"
14+ | "react-router"
15+ | "react-router-spa"
16+ | "tanstack-start" ;
17+
18+ const TEMPLATES = {
19+ "next-mdx" : {
20+ label : "Next.js: Fumadocs MDX" ,
21+ hint : "Recommended template with MDX support" ,
22+ value : "+next+fuma-docs-mdx" ,
23+ } ,
24+ waku : {
25+ label : "Waku: Content Collections" ,
26+ hint : "Template using Waku with content collections" ,
27+ value : "waku" ,
28+ } ,
29+ "react-router" : {
30+ label : "React Router: MDX Remote" ,
31+ hint : "Template for React Router with MDX remote" ,
32+ value : "react-router" ,
33+ } ,
34+ "react-router-spa" : {
35+ label : "React Router: SPA" ,
36+ hint : "Template for React Router SPA" ,
37+ value : "react-router-spa" ,
38+ } ,
39+ "tanstack-start" : {
40+ label : "Tanstack Start: MDX Remote" ,
41+ hint : "Template for Tanstack Start with MDX remote" ,
42+ value : "tanstack-start" ,
43+ } ,
44+ } as const ;
45+
1046export async function setupFumadocs ( config : ProjectConfig ) {
1147 const { packageManager, projectDir } = config ;
1248
1349 try {
1450 log . info ( "Setting up Fumadocs..." ) ;
1551
16- const commandWithArgs = `create-fumadocs-app@latest fumadocs --src --no-install --pm ${ packageManager } --no-eslint --no-biome --no-git` ;
52+ const template = await select < FumadocsTemplate > ( {
53+ message : "Choose a template" ,
54+ options : Object . entries ( TEMPLATES ) . map ( ( [ key , template ] ) => ( {
55+ value : key as FumadocsTemplate ,
56+ label : template . label ,
57+ hint : template . hint ,
58+ } ) ) ,
59+ initialValue : "next-mdx" ,
60+ } ) ;
61+
62+ if ( isCancel ( template ) ) return exitCancelled ( "Operation cancelled" ) ;
63+
64+ const templateArg = TEMPLATES [ template ] . value ;
65+
66+ // love you to use @latest here but the cli updates too many times and breaks stuff
67+ const commandWithArgs = `create-fumadocs-app@16.0.4 fumadocs --template ${ templateArg } --src --pm ${ packageManager } --no-git` ;
1768
1869 const fumadocsInitCommand = getPackageExecutionCommand (
1970 packageManager ,
@@ -23,13 +74,16 @@ export async function setupFumadocs(config: ProjectConfig) {
2374 const appsDir = path . join ( projectDir , "apps" ) ;
2475 await fs . ensureDir ( appsDir ) ;
2576
77+ const s = spinner ( ) ;
78+ s . start ( "Setting up Fumadocs..." ) ;
79+
2680 await execa ( fumadocsInitCommand , {
2781 cwd : appsDir ,
2882 env : { CI : "true" } ,
2983 shell : true ,
30- stdio : "inherit" ,
3184 } ) ;
3285
86+
3387 const fumadocsDir = path . join ( projectDir , "apps" , "fumadocs" ) ;
3488 const packageJsonPath = path . join ( fumadocsDir , "package.json" ) ;
3589
@@ -40,11 +94,11 @@ export async function setupFumadocs(config: ProjectConfig) {
4094 if ( packageJson . scripts ?. dev ) {
4195 packageJson . scripts . dev = `${ packageJson . scripts . dev } --port=4000` ;
4296 }
43-
97+
4498 await fs . writeJson ( packageJsonPath , packageJson , { spaces : 2 } ) ;
4599 }
46-
47- log . success ( "Fumadocs setup successfully !" ) ;
100+
101+ s . stop ( "Fumadocs setup complete !" ) ;
48102 } catch ( error ) {
49103 log . error ( pc . red ( "Failed to set up Fumadocs" ) ) ;
50104 if ( error instanceof Error ) {
0 commit comments