A minimal dashboard template with Better Auth authentication already configured. This starter includes no actual dashboard functionality—it's a clean foundation for building your own.
Includes:
- Authentication: Better Auth (magic link authentication)
- Routing: TanStack Router (file-based routing)
- Data Fetching: TanStack Query
- UI Components: shadcn/ui + Tailwind CSS v4
- Development Tools: Biome (linting/formatting), Vitest + Testing Library, TanStack Devtools
- Database: PostgreSQL-ready with Better Auth migrations
- Node ≥ 18.17
- pnpm ≥ 8
- Tailwind CSS v4 with the official Vite plugin (PostCSS 8+)
- Vite: vitejs.dev
- React: react.dev
- Better Auth: betterauth.dev
- TanStack Router: tanstack.com/router
- TanStack Query: tanstack.com/query
- shadcn/ui: ui.shadcn.com
- Tailwind CSS v4: tailwindcss.com
- Biome: biomejs.dev
- Vitest: vitest.dev
pnpm install
pnpm dev # starts dev server on http://localhost:3000This template uses Better Auth with PostgreSQL. Set up your database:
Option 1: Local Docker
docker run --name dashboard-postgres \
-e POSTGRES_USER=user \
-e POSTGRES_PASSWORD=password \
-e POSTGRES_DB=dashboard \
-p 5432:5432 \
-d postgres:16-alpineOption 2: External Database
Add to .env:
DATABASE_URL=postgresql://user:password@host:5432/database_name
Initialize Better Auth:
pnpm db:migrate # Run migrationspnpm build # Build for production
pnpm serve # Preview production build locally| Script | Purpose |
|---|---|
dev |
Start dev server |
build |
Build for production + typecheck |
serve |
Preview production build |
test |
Run Vitest |
lint |
Lint with Biome |
format |
Format with Biome |
check |
Check & fix with Biome |
typecheck |
TypeScript check only |
db:migrate |
Run Better Auth migrations |
db:generate |
Generate Better Auth types |
src/
main.tsx # Bootstrap
styles.css # Tailwind v4 + theme tokens
routeTree.gen.ts # Auto-generated by Router plugin
router.tsx # Router config
middleware/
auth.ts # Auth middleware
lib/
auth-client.ts # Better Auth client
auth.ts # Better Auth config
components/
app-sidebar.tsx # Dashboard sidebar
site-header.tsx # Header
login-form.tsx # Login form
ui/ # shadcn/ui components
integrations/
tanstack-query/
root-provider.tsx # Query client setup
devtools.tsx # Query devtools
routes/
__root.tsx # Root layout
index.tsx # Home route
login.tsx # Login route
api/
auth/ # Auth API routes
components.json # shadcn/ui config
vite.config.ts # Vite config with Router + Tailwind v4
biome.json # Code quality config
tsconfig.json # TypeScript config
Better Auth is pre-configured with magic link authentication (invitation-only, no public signup).
Key files:
- lib/auth.ts — Better Auth server config
- lib/auth-client.ts — Client-side auth client
- routes/login.tsx — Login page
- routes/api/auth/$.ts — Auth API routes
Tailwind CSS v4 with the official Vite plugin. Design tokens defined in src/styles.css using CSS custom properties.
Components styled with shadcn/ui (CVA + Tailwind).
File-based routing via TanStack Router. Add routes by creating files in src/routes/.
Example route:
import { createFileRoute } from "@tanstack/react-router";
export const Route = createFileRoute("/example")({
component: () => <div>Example Page</div>,
});Link to route:
import { Link } from "@tanstack/react-router";
export function Nav() {
return <Link to="/example">Example</Link>;
}Root layout is src/routes/__root.tsx. Use <Outlet /> to render active routes.
Use TanStack Query for server-side data:
import { useQuery } from "@tanstack/react-query";
export function MyComponent() {
const { data } = useQuery({
queryKey: ["my-key"],
queryFn: async () => {
const res = await fetch("/api/endpoint");
return res.json();
},
});
return <div>{data}</div>;
}Query Devtools available for debugging (enabled in dev).
- Linting:
pnpm lint(Biome) - Formatting:
pnpm format(Biome) - Type checking:
pnpm typecheck(TypeScript) - Testing:
pnpm test(Vitest + Testing Library)
pnpm build # vite build + tsc --noEmit
pnpm previewArtifacts in dist/.
src/routeTree.gen.tsis generated. Don’t edit it by hand. Add tofiles.readonlyIncludein VS Code if desired.