Начало работы: TanStack Start
SSR на Vite: стили — ссылкой в head() корневого маршрута, тема — на <html> в shellComponent, поэтому первая отрисовка уже в теме
1. Создайте приложение
Флаг --blank даёт минимальный шаблон. В полном шаблоне есть свой скрипт темы: он пишет data-theme="light|dark" на <html> и конфликтует с темой ValyroUI — его пришлось бы удалять. Проверено с TanStack Start 1.169.
npx @tanstack/cli@latest create my-app --framework React --blank --package-manager npm --no-git --no-intent --no-toolchain --non-interactive
cd my-app
2. Установите пакет
Подходят react и react-dom 17, 18 и 19 (на React 17 id из useId появляются сразу после монтирования). Пакет — ES-модули (плюс CommonJS-копия для require()), без runtime-зависимостей, по файлу на модуль: в бандл попадают только импортированные компоненты, а как грузить и CSS только их — в разделе «Только нужный CSS» ниже. Шрифты — отдельные файлы: тема vercel (по умолчанию в ThemeProvider) использует Geist, поэтому рядом со стилями импортируйте valyro-ui/fonts/geist.css и valyro-ui/fonts/geist-mono.css, иначе текст будет системным шрифтом; glass использует системные шрифты, ей файлы не нужны. Пока пакет не опубликован, соберите и упакуйте его в репозитории (npm run build:core && npm pack ./dist/core) и установите tarball из корня репозитория: npm install /path/to/ValyroUI/valyro-ui-0.1.0.tgz.
npm install valyro-ui
3. Стили и тема в корневом маршруте
Импорт с ?url превращает CSS в <link> в <head> серверного HTML — так подключён и CSS самого шаблона, и порядок явный: сначала ValyroUI, потом ваши стили. Обычный import 'valyro-ui/styles.css' тоже даёт ссылку в <head>, но после ссылок из links, и тогда стили ValyroUI перебивают ваши. Атрибуты темы — на <html>, ThemeProvider с теми же значениями — вокруг children. При SSR задайте locale в ThemeProvider: иначе числа и даты форматируются по локали сервера, а в браузере — по локали пользователя, и гидрация падает на несовпадении текста («1,200» против «1 200»).
import { HeadContent, Scripts, createRootRoute } from '@tanstack/react-router'
import { ThemeProvider } from 'valyro-ui'
import valyroCss from 'valyro-ui/styles.css?url'
import appCss from '../styles.css?url'
export const Route = createRootRoute({
head: () => ({
meta: [
{ charSet: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ title: 'ValyroUI on TanStack Start' },
],
links: [
{ rel: 'stylesheet', href: valyroCss },
{ rel: 'stylesheet', href: appCss },
],
}),
shellComponent: RootDocument,
})
function RootDocument({ children }: { children: React.ReactNode }) {
return (
<html lang="en" data-theme="glass" data-mode="light">
<head>
<HeadContent />
</head>
<body>
<ThemeProvider theme="glass" mode="light" locale="en-US">
{children}
</ThemeProvider>
<Scripts />
</body>
</html>
)
}
4. Уберите шрифт и вёрстку шаблона
Шаблонный font-family на body перебивает шрифт темы, а правило для main меняет вёрстку страниц. Оставьте только сброс.
* {
box-sizing: border-box;
}
body {
margin: 0;
}
5. Маршрут
Showcase — компонент из гайда по Next.js, без изменений (директиву 'use client' TanStack Start пропускает молча).
import { createFileRoute } from '@tanstack/react-router'
import { Showcase } from '../Showcase'
export const Route = createFileRoute('/')({ component: Home })
function Home() {
return <Showcase />
}
6. Соберите и запустите
npm run preview отдаёт SSR из production-сборки. Для деплоя на Node нужен адаптер хостинга из документации TanStack Start.
npx tsc --noEmit
npm run build
npm run preview