Skip to content

Repository files navigation

TanStack Start Theme

Read this in other languages: 中文.

A modern full-stack React application based on TanStack Start that demonstrates how to implement a complete light/dark theme switching functionality. This project provides a plug-and-play theme system that can be easily integrated into other projects.

✨ Features

  • 🌓 Complete theme system - Supports light/dark/system themes with automatic system preference detection
  • 🚀 Modern tech stack - Built on React 19, TanStack Start, Tailwind CSS v4
  • 🎨 Beautiful UI components - Integrated shadcn/ui component library with New York style
  • Flicker-free switching - Elegant theme switching animations that prevent page flickering
  • 📱 Responsive design - Mobile-first responsive layout
  • 🔧 Full TypeScript coverage - Complete type safety
  • 🌳 SSR/SSG support - Full server-side rendering support

🛠️ Tech Stack

  • Framework: TanStack Start (full-stack React framework)
  • Routing: TanStack Router
  • Styling: Tailwind CSS
  • UI Components: shadcn/ui
  • Icons: Lucide React
  • Build Tools: Vite + TypeScript

📦 Installation & Running

# Clone the project
git clone <repository-url>
cd tanstack-start-theme

# Install dependencies
pnpm install

# Start development server
pnpm dev

Visit http://localhost:3000 to see the demo.

📁 Project Structure

tanstack-start-theme/
├── src/
│   ├── components/
│   │   ├── theme.tsx          # 🌟 Theme system core file (directly reusable)
│   │   ├── Header.tsx         # Page header component
│   │   └── ui/                # shadcn/ui component library
│   ├── routes/
│   │   ├── __root.tsx         # 🌟 Root route component (needs modification)
│   │   └── index.tsx          # Homepage component
│   ├── router.tsx             # 🌟 Router configuration (needs modification)
│   ├── styles.css             # 🌟 Global styles and theme variables
│   └── lib/utils.ts           # Utility functions
├── components.json             # shadcn/ui configuration
└── README.md

🎯 How to Use in Other Projects

1. Directly Reusable Files

The following files can be directly copied to other projects:

# Theme system core
cp src/components/theme.tsx your-project/src/components/

2. Files That Need Modification

The following files need to be adapted according to your project:

router.tsx - Router Configuration

In your project, you need to integrate the ThemeProvider into the routing system:

// src/router.tsx
import { ThemeProvider } from '@/components/theme'

export const getRouter = () => {
  const router = createRouter({
    routeTree,
    scrollRestoration: true,
    defaultPreloadStaleTime: 0,
    Wrap: (props: { children: React.ReactNode }) => {
      return <ThemeProvider>{props.children}</ThemeProvider>
    }
  })
  return router
}

__root.tsx - Root Route Component

Add anti-flicker script:

// src/routes/__root.tsx
export const Route = createRootRoute({
  // ... route configuration

  shellComponent: RootDocument,
})

function RootDocument({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en" suppressHydrationWarning>
      <head>
        <HeadContent />
        {/* 🌟 Key: Anti-flicker script */}
        <script>
          {`
          if (typeof window !== 'undefined') {
            let isDark = localStorage.getItem('theme') === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches);
            document.documentElement.classList.toggle('dark', isDark);
          }
          `}
        </script>
      </head>
      <body>
        <Header />
        {children}
        <Scripts />
      </body>
    </html>
  )
}

3. Using the Theme System

Using Theme in Components

import { useTheme, ThemeToggle } from '@/components/theme'

function MyComponent() {
  const { theme, setTheme } = useTheme()

  return (
    <div>
      {/* Theme toggle button */}
      <ThemeToggle />

      {/* Programmatic switch */}
      <button onClick={() => setTheme('dark')}>
        Switch to dark mode
      </button>
    </div>
  )
}

🔧 Theme System Deep Dive

Core Features

  1. Isomorphic functions - Use createIsomorphicFn for server/client compatibility
  2. Local storage - Use localStorage to persist user preferences
  3. System theme - Support following system theme settings
  4. Reactive switching - Listen to system theme changes and update in real-time

API Reference

ThemeProvider

Theme context provider, needs to wrap the application root:

<ThemeProvider>
  <App />
</ThemeProvider>

useTheme()

Theme state Hook:

const { theme, setTheme, systemTheme } = useTheme()

// theme: 'light' | 'dark' | 'system' - current theme
// setTheme: (theme: Theme) => void - set theme
// systemTheme: 'light' | 'dark' - system theme

ThemeToggle

Ready-to-use theme toggle button component:

<ThemeToggle />

🌟 Why Choose This Theme System?

  1. Zero flicker - Apply theme immediately on page load to avoid visual flicker
  2. SSR friendly - Full server-side rendering support
  3. Type safe - Complete TypeScript support
  4. Performance optimized - CSS Variables-based theme switching
  5. Easy integration - Minimal configuration, plug and play
  6. Modern - Using latest web standards and best practices

🤝 Contributing

Issues and Pull Requests are welcome!

📄 License

MIT License

About

A TanStack Start theme toggle demo

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Contributors

Languages