Template guides
A template is a set of pages, the provider they share and an adapter to your backend. You mount the pages on your own routes.
The templates
- Auth & onboarding:
npx shadcn@latest add @snow-ui-pro/auth, and its mock backend@snow-ui-pro/mock-auth. - SaaS settings & billing:
npx shadcn@latest add @snow-ui-pro/settings, and its mock backend@snow-ui-pro/mock-settings. - Commerce admin:
npx shadcn@latest add @snow-ui-pro/commerce, and its mock backend@snow-ui-pro/mock-commerce. - CRM:
npx shadcn@latest add @snow-ui-pro/crm, and its mock backend@snow-ui-pro/mock-crm. - Analytics:
npx shadcn@latest add @snow-ui-pro/analytics, and its mock backend@snow-ui-pro/mock-analytics.
How every template is mounted
- Add the template, and its mock backend to try the pages before yours is ready. The template brings its pages, blocks and the snow-ui components they use.
- Put the template’s provider (
AuthTemplateProvider,SettingsTemplateProvider…) in the layout that wraps its routes. It is a client component and takes the adapter, your router’snavigateand link component, and your routes (each has a default). - Add one route per page that renders the page component with its data: the guide of each template lists the pages, their props and suggested routes.
- Replace the mock adapter with your own: its interface is in
components/snow-ui-pro/lib/<template>-types.ts, and each guide describes it.
Templates never call the network themselves and don’t depend on a framework: the guides show the Next.js App Router, and the same components work with any router.
React Router (Vite)
A Vite app needs Tailwind CSS v4 (the @tailwindcss/vite plugin) and the @ import alias in vite.config.ts and tsconfig.json before shadcn init, as in the shadcn/ui guide for Vite. Then follow the installation. Pass React Router’s link to the templates:
// src/router-link.tsx
import { Link } from 'react-router'
import type { LinkComponent } from '@/components/snow-ui-pro/lib/navigation'
/** The templates render their links with your router's link. */
export const RouterLink: LinkComponent = ({ href, ...props }) => (
<Link to={href} {...props} />
)The provider goes in a layout route, around an <Outlet />; navigate is React Router’s:
// src/auth.tsx — a layout route with the provider, one route per page
import { useMemo } from 'react'
import { Outlet, useNavigate } from 'react-router'
import { SnowUIProvider } from '@/components/snow-ui/components/SnowUIProvider/SnowUIProvider'
import { createMockAuthAdapter } from '@/components/snow-ui-pro/mock/auth' // or your AuthAdapter
import { AuthTemplateProvider } from '@/components/snow-ui-pro/templates/auth/AuthTemplate'
import { RouterLink } from './router-link'
export function AuthLayout() {
const navigate = useNavigate()
const adapter = useMemo(() => createMockAuthAdapter(), [])
return (
<SnowUIProvider>
<AuthTemplateProvider
adapter={adapter}
navigate={navigate}
linkAs={RouterLink}
routes={{ app: '/' }}
>
<Outlet />
</AuthTemplateProvider>
</SnowUIProvider>
)
}Pages that take URL values read them with useParams and useSearchParams where Next.js passes params and searchParams:
// src/App.tsx (main.tsx wraps <App /> in <BrowserRouter>)
import { Route, Routes, useParams, useSearchParams } from 'react-router'
import { OnboardingPage } from '@/components/snow-ui-pro/templates/auth/OnboardingPage'
import { PasswordResetPage } from '@/components/snow-ui-pro/templates/auth/PasswordResetPage'
import { SignInPage } from '@/components/snow-ui-pro/templates/auth/SignInPage'
import { SignUpPage } from '@/components/snow-ui-pro/templates/auth/SignUpPage'
import { AuthLayout } from './auth'
function ResetPassword() {
const [params] = useSearchParams()
return <PasswordResetPage token={params.get('token') ?? undefined} />
}
function Onboarding() {
const { step = 'about-you' } = useParams()
return <OnboardingPage step={step} />
}
export default function App() {
return (
<Routes>
<Route element={<AuthLayout />}>
<Route path="sign-in" element={<SignInPage />} />
<Route path="sign-up" element={<SignUpPage />} />
<Route path="reset-password" element={<ResetPassword />} />
<Route path="onboarding/:step" element={<Onboarding />} />
{/* …verify, two-factor, two-factor/setup: the guide lists them */}
</Route>
</Routes>
)
}Without server rendering, what the Next.js layouts read on the server is read in the browser: the sidebar state with readSidebarState(document.cookie) (from components/snow-ui/components/Sidebar/sidebar-cookie), and now from new Date().