Orientation
Content Processing
Search Infrastructure
Rendering and UI
Developer Tooling
How It Works
The following files were used as context for generating this wiki page:
App Templates serve as the scaffolding engine for the Fumadocs ecosystem, enabling the rapid generation of consistent, production-ready documentation sites. By defining structured, framework-specific blueprints (e.g., Next.js, Waku, React Router, TanStack Start), these templates encapsulate complex configuration logic, dependency management, and routing setups into a unified, interactive CLI experience.
The primary problem solved by App Templates is the "first-mile" friction in modern web development. When starting a documentation project, developers face numerous choices regarding build systems, linter configurations, search providers, and AI integration. App Templates automate these decisions by allowing developers to select their preferred configuration during initialization, ensuring that the generated project adheres to project-wide best practices while significantly reducing manual setup time.
Architecturally, the template system acts as a plugin-based orchestration layer. When an app is generated, the system creates a context representing the destination directory and chosen template, then sequentially invokes registered plugins. Each plugin can manipulate the filesystem, modify package.json dependencies, or transform existing source code (e.g., injecting search dialog providers into a root layout) via an Abstract Syntax Tree (AST) transformer. This design facilitates extensibility; adding a new feature like AI chat or a specific linter becomes a matter of registering a plugin that hooks into the template lifecycle.
The template generation flow is managed by the create() function in packages/create-app/src/index.ts. The process follows a strict sequential pipeline that ensures modular, predictable output.
Sources: packages/create-app/src/bin.ts:56-282, packages/create-app/src/index.ts:64-126
Plugins are the primary extension mechanism for template modification. A TemplatePlugin defines lifecycle hooks that allow modifications at specific stages of the project generation lifecycle.
Sources: packages/create-app/src/index.ts:51-62
Tip
The afterWrite hook is the most powerful plugin lifecycle point. Because files are already persisted to the filesystem, plugins can reliably use AST transformers to inject imports or components into existing files.
To maintain project integrity during configuration, the system utilizes AST transformation (via ts-morph) rather than simple string injection. This ensures that generated code is syntactically correct and respects existing project structures.
The core transformer functionality is encapsulated in packages/create-app/src/transform/index.ts. For instance, when adding a search provider, the rootProvider function scans for a RootProvider component and safely injects the search prop without overwriting existing configuration.
// Example: Adding search dialog using AST injection
await rootProvider(this, (mod) => mod.addSearchDialog('@/components/search'));Sources: packages/create-app/src/transform/index.ts:17-55
Warning
AST injections verify if a property (e.g., search) already exists before attempting to inject a new one. This guard prevents duplicate definitions, which would cause runtime errors or configuration conflicts.
App Templates provide specialized logic for search implementations, most notably for Orama Cloud. This requires both client-side components and server-side synchronization scripts to ensure search indexes remain current.
The oramaCloud() plugin handles this by:
scripts/sync-content.ts utility that fetches the rendered static.json and pushes it to Orama Cloud via an authenticated request.Sources: packages/create-app/src/plugins/orama-cloud.ts:8-107
Dependency versions are centralized to ensure consistency across template variations. The packages/create-app/src/constants.ts file consolidates versioning from workspace packages, preventing version drift when a new dependency is introduced.
Sources: packages/create-app/src/constants.ts:8-88
Note
Workspace dependencies defined in package.json as workspace:* are automatically resolved to specific versions from depVersions during the initialization of package.json inside the create flow.
AI integration is implemented as an optional plugin that installs component dependencies via the CLI registry and modifies the documentation layout to include an AISearch component.
The addAIChat flow follows:
installer.install('ai/provider'): Installs specific UI components for the chosen AI provider.createSourceFile(filePath): Parses the existing layout file.element.setBodyText(...): Prepends the AISearch component to the DocsLayout content children.file.addImportDeclarations(...): Injects necessary components and hook imports.Sources: packages/create-app/src/plugins/ai.ts:39-109