Getting Started
Set up Onedocs in your project
Getting Started
This guide walks you through setting up Onedocs from scratch.
Prerequisites
- Node.js 18+ or Bun 1.0+
- A TanStack Start project (or we'll create one)
Installation
bun add onedocsnpm install onedocspnpm add onedocsyarn add onedocsConfiguration
Create onedocs.config.ts in your project root:
import { defineConfig } from "onedocs/config";
export default defineConfig({
title: "My Docs",
description: "Documentation for my project",
nav: {
github: "username/repo",
},
});Project Structure
Create a content/docs folder for your markdown files:
your-project/
├── content/
│ └── docs/
│ ├── index.mdx # /docs
│ ├── getting-started.mdx # /docs/getting-started
│ └── guides/
│ ├── meta.json # Sidebar ordering
│ └── setup.mdx # /docs/guides/setup
├── src/
│ ├── routes/
│ │ ├── __root.tsx
│ │ ├── index.tsx
│ │ ├── docs.tsx
│ │ └── docs/
│ │ ├── index.tsx
│ │ └── $.tsx
│ ├── lib/
│ │ └── source.ts
│ └── router.tsx
├── onedocs.config.ts
├── source.config.ts
└── vite.config.tsSource Configuration
Create source.config.ts to define your content collection:
import { defineDocs } from "fumadocs-mdx/config";
export const docs = defineDocs({
dir: "content/docs",
});Vite Configuration
Set up your vite.config.ts:
import tailwindcss from "@tailwindcss/vite";
import { tanstackStart } from "@tanstack/react-start/plugin/vite";
import react from "@vitejs/plugin-react";
import mdx from "fumadocs-mdx/vite";
import { nitro } from "nitro/vite";
import { defineConfig } from "vite";
import tsconfigPaths from "vite-tsconfig-paths";
import * as MdxConfig from "./source.config";
export default defineConfig({
plugins: [
mdx(MdxConfig),
tsconfigPaths(),
tailwindcss(),
nitro(),
tanstackStart(),
react(),
],
resolve: {
dedupe: ["react", "react-dom"],
},
});Content Source
Create src/lib/source.ts to load your docs:
import { loader } from "fumadocs-core/source";
import { docs } from "../../.source/server";
export const source = loader({
baseUrl: "/docs",
source: docs.toFumadocsSource(),
});Routes
Root Route
import { RootProvider } from "fumadocs-ui/provider/tanstack";
import {
createRootRoute,
HeadContent,
Outlet,
Scripts,
} from "@tanstack/react-router";
import "fumadocs-ui/style.css";
export const Route = createRootRoute({
head: () => ({
meta: [
{ charSet: "utf-8" },
{ name: "viewport", content: "width=device-width, initial-scale=1" },
{ title: "My Docs" },
],
}),
shellComponent: RootDocument,
component: RootComponent,
});
function RootComponent() {
return (
<RootProvider>
<Outlet />
</RootProvider>
);
}
function RootDocument({ children }: { children: React.ReactNode }) {
return (
<html lang="en" suppressHydrationWarning>
<head>
<HeadContent />
</head>
<body>
{children}
<Scripts />
</body>
</html>
);
}Docs Layout
import { DocsLayout } from "onedocs";
import { createFileRoute, Outlet } from "@tanstack/react-router";
import { source } from "../lib/source";
import config from "../../onedocs.config";
export const Route = createFileRoute("/docs")({
component: DocsLayoutWrapper,
});
function DocsLayoutWrapper() {
return (
<DocsLayout config={config} pageTree={source.pageTree}>
<Outlet />
</DocsLayout>
);
}Docs Page
import { DocsPage } from "onedocs";
import { createFileRoute, notFound } from "@tanstack/react-router";
import { source } from "../../lib/source";
export const Route = createFileRoute("/docs/$")({
component: DocsPageComponent,
});
function DocsPageComponent() {
const params = Route.useParams();
const slugs = params._splat?.split("/").filter(Boolean) ?? [];
const page = source.getPage(slugs);
if (!page) {
throw notFound();
}
const MDXContent = page.data.body;
return (
<DocsPage toc={page.data.toc}>
<h1>{page.data.title}</h1>
{page.data.description && (
<p className="text-muted-foreground">{page.data.description}</p>
)}
<MDXContent />
</DocsPage>
);
}Running
Start the development server:
bun run devBuild for production:
bun run build