Skip to content

Getting Started

Add static React documentation with Ardo, either through an agent-guided adoption or a small standalone project.

For an existing repository, start with Adopt Ardo in an Existing Project. It gives a coding agent a safe, reference-project-based path without replacing your application setup. The standalone CLI remains useful for an empty directory when its default shape is already what you want.

Existing project

Give your coding agent the URL https://ardo-docs.dev/llms.txt and the adoption guide. It will inspect the repository, select the closest reference project, and propose the smallest change before editing files.

Prerequisites

You'll need:

  • Node.js version 22.22.1 or higher
  • pnpm (recommended) or npm/yarn

Empty-directory convenience

Use create-ardo only when you want its opinionated, complete starter shape — configuration, example content, and a GitHub Pages workflow — in a new empty directory.

pnpm create ardo@latest my-docs
cd my-docs
pnpm install
pnpm dev

Open http://localhost:5173 and you'll see your site. Add an MDX file to app/routes/, and Ardo includes it in the generated navigation.

Manual Installation

If you want to add Ardo to an existing workspace or understand the scaffold, follow the manual setup. The split is simple: Vite handles build-time configuration, React handles UI configuration.

1. Create a new project

mkdir my-docs
cd my-docs
pnpm init

2. Install dependencies

pnpm add ardo lucide-react react react-dom react-router isbot
pnpm add -D @react-router/dev @tailwindcss/vite tailwindcss typescript vite @types/react @types/react-dom

3. Add package scripts

React Router owns the dev server, production build, and local preview commands:

{
  "scripts": {
    "dev": "react-router dev",
    "build": "react-router build",
    "preview": "vite preview"
  }
}

When you use pnpm, add the same build-script allowlist that the scaffold ships so esbuild can prepare Vite's native dependency:

# pnpm-workspace.yaml
packages:
  - "."

allowBuilds:
  esbuild: true

4. Create Vite configuration

The ardo() plugin handles build-time configuration. UI configuration (navigation, sidebar, footer) is done via JSX props in root.tsx:

import { defineConfig } from "vite"
import tailwindcss from "@tailwindcss/vite"
import { ardo } from "ardo/vite"

export default defineConfig({
  plugins: [
    tailwindcss(),
    ardo({
      title: "My Documentation",
      description: "My awesome documentation site",
    }),
  ],
})

5. Create React Router configuration

Ardo uses React Router 8 under the hood. For a static documentation site, you want pre-rendering enabled and SSR off:

import type { Config } from "@react-router/dev/config"

export default {
  ssr: false,
  prerender: true,
} satisfies Config

6. Create app files

These are standard React Router entry files plus Ardo's root component. If you've worked with React Router before, the shape should feel familiar.

app/root.tsx:

import {
  ArdoGeneratedSidebar,
  ArdoHeader,
  ArdoNav,
  ArdoNavLink,
  ArdoRoot,
  ArdoRootLayout,
  ArdoSidebar,
  ArdoSidebarSection,
} from "ardo/ui"
import config from "virtual:ardo/config"
import "./app.css"
import "ardo/ui/styles.css"

export function Layout({ children }: { children: React.ReactNode }) {
  return <ArdoRootLayout>{children}</ArdoRootLayout>
}

export default function Root() {
  return (
    <ArdoRoot config={config}>
      <ArdoHeader>
        <ArdoNav>
          <ArdoNavLink to="/guide/getting-started">Guide</ArdoNavLink>
        </ArdoNav>
      </ArdoHeader>

      <ArdoSidebar>
        <ArdoSidebarSection id="guide" label="Guide" to="/guide/getting-started">
          <ArdoGeneratedSidebar section="guide" />
        </ArdoSidebarSection>
      </ArdoSidebar>
    </ArdoRoot>
  )
}

app/app.css:

@layer theme, base, components, utilities;
@import "tailwindcss/theme.css" layer(theme);
@import "tailwindcss/utilities.css" layer(utilities);

app/entry.client.tsx:

import { startTransition, StrictMode } from "react"
import { hydrateRoot } from "react-dom/client"
import { HydratedRouter } from "react-router/dom"

startTransition(() => {
  hydrateRoot(
    document,
    <StrictMode>
      <HydratedRouter />
    </StrictMode>
  )
})

app/entry.server.tsx:

import type { EntryContext } from "react-router"
import { ServerRouter } from "react-router"
import { renderToReadableStream } from "react-dom/server"
import { isbot } from "isbot"

export default async function handleRequest(
  request: Request,
  responseStatusCode: number,
  responseHeaders: Headers,
  routerContext: EntryContext
) {
  const userAgent = request.headers.get("user-agent")

  const stream = await renderToReadableStream(
    <ServerRouter context={routerContext} url={request.url} />,
    {
      onError(error: unknown) {
        console.error(error)
        responseStatusCode = 500
      },
    }
  )

  if (userAgent && isbot(userAgent)) {
    await stream.allReady
  }

  responseHeaders.set("Content-Type", "text/html")

  return new Response(stream, {
    status: responseStatusCode,
    headers: responseHeaders,
  })
}

7. Create your first document

Create app/routes/guide/getting-started.mdx:

---
title: Getting Started
---

# Getting Started

Welcome to your documentation site!

That's it. Run pnpm dev and you've got a documentation site.

The create-ardo CLI generates all of these files automatically — use it when you want to skip the boilerplate and get straight to writing.

Development

Start the development server:

pnpm dev

Your site will be running at http://localhost:5173. Changes to MDX and TSX routes flow through Vite's development server.

Production Build

When you're ready to publish:

pnpm build

The output lands in build/client/ — a fully static site ready for any hosting platform. Preview it locally before deploying:

pnpm preview

Project Structure

Here's what an Ardo project looks like. If you've worked with React Router, the layout will feel natural:

my-docs/
├── app/
│   ├── routes/                  # Your MDX/MD content files
│   │   ├── guide/
│   │   │   └── getting-started.mdx
│   │   └── home.tsx             # Home page
│   ├── root.tsx                 # Root layout
│   ├── entry.client.tsx         # Client entry
│   ├── entry.server.tsx         # Server entry
│   └── app.css                  # Tailwind v4 utility layers
├── vite.config.ts               # Vite + Ardo configuration
├── react-router.config.ts       # React Router configuration
├── pnpm-workspace.yaml          # pnpm build-script allowlist, when using pnpm
├── tsconfig.json
└── package.json

The repository also includes runnable examples for common layouts: basic, library, and monorepo. For Markdown owned outside app/routes/, start with the content sources reference.

Next Steps

Your site is running. Now make it yours: