TanStack Start
A guide for installing and using Yamada UI with TanStack Start projects.
Installation
- 1
Create application
Create TanStack Start application.
pnpm create @tanstack/start my-appnpx create @tanstack/start my-appyarn create @tanstack/start my-appbun create @tanstack/start my-app - 2
Setup
Running the command will create the necessary files and folders in your project.
pnpm dlx @yamada-ui/cli initnpx @yamada-ui/cli inityarn dlx @yamada-ui/cli initbunx @yamada-ui/cli init - 3
Install the package
Install
@workspaces/uito your application.pnpm add "@workspaces/ui@workspace:*"npm install "@workspaces/ui@workspace:*"yarn add "@workspaces/ui@workspace:*"bun add "@workspaces/ui@workspace:*" - 4
Add provider
After installing, add
UIProviderto the root of your application. To suppress hydration errors, addsuppressHydrationWarningto thehtmlandbodytags.__root.tsx
import { HeadContent, Scripts, createRootRoute } from "@tanstack/react-router" import { TanStackRouterDevtoolsPanel } from "@tanstack/react-router-devtools" import { TanStackDevtools } from "@tanstack/react-devtools" import { UIProvider } from "@workspaces/ui" export const Route = createRootRoute({ head: () => ({ meta: [ { charSet: "utf-8" }, { name: "viewport", content: "width=device-width, initial-scale=1" }, { title: "TanStack Start Starter" }, ], }), shellComponent: RootDocument, }) function RootDocument({ children }: { children: React.ReactNode }) { return ( <html lang="en" suppressHydrationWarning> <head> <HeadContent /> </head> <body suppressHydrationWarning> <UIProvider>{children}</UIProvider> <TanStackDevtools config={{ position: "bottom-right" }} plugins={[ { name: "Tanstack Router", render: <TanStackRouterDevtoolsPanel />, }, ]} /> <Scripts /> </body> </html> ) } - 5
Use components
After adding
UIProvider, you can use the components in your application.index.tsx
import { createFileRoute } from "@tanstack/react-router" import { Button } from "@workspaces/ui" export const Route = createFileRoute("/")({ component: App }) function App() { return <Button>Click me!</Button> }That's it! You've successfully set up Yamada UI.
Scripts
ColorModeScript
To use Color Mode, you need to add ColorModeScript to the body to ensure it works correctly.
This is because color mode is implemented using localStorage or cookies, and adding the script ensures proper synchronization when the page loads.
__root.tsx
import { HeadContent, Scripts, createRootRoute } from "@tanstack/react-router"
import { TanStackRouterDevtoolsPanel } from "@tanstack/react-router-devtools"
import { TanStackDevtools } from "@tanstack/react-devtools"
import { ColorModeScript, UIProvider } from "@workspaces/ui"
import { createServerFn } from "@tanstack/react-start"
import { getRequestHeader } from "@tanstack/react-start/server"
const getCookie = createServerFn({ method: "GET" }).handler(async () => {
return getRequestHeader("cookie") ?? ""
})
export const Route = createRootRoute({
loader: async () => ({
cookie: await getCookie(),
}),
head: () => ({
meta: [
{ charSet: "utf-8" },
{ name: "viewport", content: "width=device-width, initial-scale=1" },
{ title: "TanStack Start Starter" },
],
}),
shellComponent: RootDocument,
})
function RootDocument({ children }: { children: React.ReactNode }) {
const { cookie } = Route.useLoaderData()
return (
<html lang="en" suppressHydrationWarning>
<head>
<HeadContent />
</head>
<body suppressHydrationWarning>
<ColorModeScript type="cookie" />
<UIProvider cookie={cookie}>{children}</UIProvider>
<TanStackDevtools
config={{ position: "bottom-right" }}
plugins={[
{
name: "Tanstack Router",
render: <TanStackRouterDevtoolsPanel />,
},
]}
/>
<Scripts />
</body>
</html>
)
}
If you change the defaultColorMode in your config, set the defaultValue prop on ColorModeScript.
__root.tsx
import { HeadContent, Scripts, createRootRoute } from "@tanstack/react-router"
import { TanStackRouterDevtoolsPanel } from "@tanstack/react-router-devtools"
import { TanStackDevtools } from "@tanstack/react-devtools"
import { ColorModeScript, UIProvider } from "@workspaces/ui"
import { createServerFn } from "@tanstack/react-start"
import { getRequestHeader } from "@tanstack/react-start/server"
import { config } from "@workspaces/theme"
const getCookie = createServerFn({ method: "GET" }).handler(async () => {
return getRequestHeader("cookie") ?? ""
})
export const Route = createRootRoute({
loader: async () => ({
cookie: await getCookie(),
}),
head: () => ({
meta: [
{ charSet: "utf-8" },
{ name: "viewport", content: "width=device-width, initial-scale=1" },
{ title: "TanStack Start Starter" },
],
}),
shellComponent: RootDocument,
})
function RootDocument({ children }: { children: React.ReactNode }) {
const { cookie } = Route.useLoaderData()
return (
<html lang="en" suppressHydrationWarning>
<head>
<HeadContent />
</head>
<body suppressHydrationWarning>
<ColorModeScript type="cookie" defaultValue={config.defaultColorMode} />
<UIProvider config={config} cookie={cookie}>
{children}
</UIProvider>
<TanStackDevtools
config={{ position: "bottom-right" }}
plugins={[
{
name: "Tanstack Router",
render: <TanStackRouterDevtoolsPanel />,
},
]}
/>
<Scripts />
</body>
</html>
)
}
ThemeSchemeScript
To use theme switching, you need to add ThemeSchemeScript to the body to ensure it works correctly.
This is because theme switching is implemented using localStorage or cookies, and adding the script ensures proper synchronization when the page loads.
__root.tsx
import { HeadContent, Scripts, createRootRoute } from "@tanstack/react-router"
import { TanStackRouterDevtoolsPanel } from "@tanstack/react-router-devtools"
import { TanStackDevtools } from "@tanstack/react-devtools"
import { ThemeSchemeScript, UIProvider } from "@workspaces/ui"
import { createServerFn } from "@tanstack/react-start"
import { getRequestHeader } from "@tanstack/react-start/server"
const getCookie = createServerFn({ method: "GET" }).handler(async () => {
return getRequestHeader("cookie") ?? ""
})
export const Route = createRootRoute({
loader: async () => ({
cookie: await getCookie(),
}),
head: () => ({
meta: [
{ charSet: "utf-8" },
{ name: "viewport", content: "width=device-width, initial-scale=1" },
{ title: "TanStack Start Starter" },
],
}),
shellComponent: RootDocument,
})
function RootDocument({ children }: { children: React.ReactNode }) {
const { cookie } = Route.useLoaderData()
return (
<html lang="en" suppressHydrationWarning>
<head>
<HeadContent />
</head>
<body suppressHydrationWarning>
<ThemeSchemeScript type="cookie" />
<UIProvider cookie={cookie}>{children}</UIProvider>
<TanStackDevtools
config={{ position: "bottom-right" }}
plugins={[
{
name: "Tanstack Router",
render: <TanStackRouterDevtoolsPanel />,
},
]}
/>
<Scripts />
</body>
</html>
)
}
If you change the defaultThemeScheme in your config, set the defaultValue prop on ThemeSchemeScript.
__root.tsx
import { HeadContent, Scripts, createRootRoute } from "@tanstack/react-router"
import { TanStackRouterDevtoolsPanel } from "@tanstack/react-router-devtools"
import { TanStackDevtools } from "@tanstack/react-devtools"
import { ThemeSchemeScript, UIProvider } from "@workspaces/ui"
import { createServerFn } from "@tanstack/react-start"
import { getRequestHeader } from "@tanstack/react-start/server"
import { config } from "@workspaces/theme"
const getCookie = createServerFn({ method: "GET" }).handler(async () => {
return getRequestHeader("cookie") ?? ""
})
export const Route = createRootRoute({
loader: async () => ({
cookie: await getCookie(),
}),
head: () => ({
meta: [
{ charSet: "utf-8" },
{ name: "viewport", content: "width=device-width, initial-scale=1" },
{ title: "TanStack Start Starter" },
],
}),
shellComponent: RootDocument,
})
function RootDocument({ children }: { children: React.ReactNode }) {
const { cookie } = Route.useLoaderData()
return (
<html lang="en" suppressHydrationWarning>
<head>
<HeadContent />
</head>
<body suppressHydrationWarning>
<ThemeSchemeScript
type="cookie"
defaultValue={config.defaultThemeScheme}
/>
<UIProvider config={config} cookie={cookie}>
{children}
</UIProvider>
<TanStackDevtools
config={{ position: "bottom-right" }}
plugins={[
{
name: "Tanstack Router",
render: <TanStackRouterDevtoolsPanel />,
},
]}
/>
<Scripts />
</body>
</html>
)
}
Component Integration
You can integrate TanStack Start components such as Link with Yamada UI components.
Link
import type { LinkComponent } from "@tanstack/react-router"
import { createLink } from "@tanstack/react-router"
import { Button, IconButton, Link } from "@workspaces/ui"
const CreatedLink = createLink(Link)
export const RouterLink: LinkComponent<typeof CreatedLink> = (props) => {
return <CreatedLink {...props} />
}
const CreatedLinkButton = createLink(Button)
export const RouterLinkButton: LinkComponent<typeof CreatedLinkButton> = (
props,
) => {
return <CreatedLinkButton {...props} />
}
const CreatedLinkIconButton = createLink(IconButton)
export const RouterLinkIconButton: LinkComponent<
typeof CreatedLinkIconButton
> = (props) => {
return <CreatedLinkIconButton {...props} />
}