# TanStack Router + Tailwind 4 Setup Complete ✅
## What's Been Configured
### 1. TanStack Router with File-Based Routing
- **Routes directory**: `frontend/src/routes/`
- **Root route**: `root.tsx` - Layout with header, footer, and outlet
- **Home route**: `index.tsx` - Welcome page with getting started cards
- **Articles route**: `articles.tsx` - Article list with card grid
- **Router configuration**: Uses `createRouter` with route tree
### 2. Tailwind CSS 4 (CSS-First)
- **Configuration**: In `src/styles.css` using `@import` and `@theme` directives
- **Vite integration**: `tailwindcss()` plugin in `vite.config.ts`
- **No config file needed**: Tailwind 4 CSS-first doesn't use `tailwind.config.js`
- **Shadcn/ui compatible**: CSS variables for theming
### 3. Routing Structure
```
frontend/src/routes/
├── root.tsx # Main layout (header, footer, )
├── index.tsx # Home page (/)
└── articles.tsx # Articles list (/articles)
```
### 4. Page Templates
#### Root Layout (`root.tsx`)
- Header with navigation (Home, Articles)
- Main content area with ``
- Footer with copyright
- Meta tags for SEO
- CSS import for Tailwind
#### Home Page (`index.tsx`)
- Welcome cards with:
- "Welcome" - Introduction
- "Get Started" - Feature list
- Centered layout with max-width container
#### Articles Page (`articles.tsx`)
- Grid of article cards (responsive: 1/2/3 columns)
- Loading state
- Error state
- Empty state (no articles)
- Each card shows:
- Featured image (if available)
- Title (truncated to 2 lines)
- Excerpt (truncated to 3 lines)
- Content preview (truncated to 4 lines)
- Date and view count
## How It Works
### 1. Route Configuration
```tsx
// src/routes/root.tsx
import { createRootRoute, Link, Outlet } from '@tanstack/react-router'
export const rootRoute = createRootRoute({
head: () => ({
meta: [
{
title: 'Placebo.mk - Sarcastic News from Macedonia',
description: 'Latest news and articles from Macedonia with a sarcastic twist',
},
],
links: [{ rel: 'stylesheet', href: '../../styles.css' }],
}),
component: () => (
),
})
```
### 2. Route Tree
```tsx
// src/main.tsx
import { createRouter } from '@tanstack/react-router'
import { rootRoute } from './routes/root'
import { indexRoute } from './routes/index'
import { articlesRoute } from './routes/articles'
const routeTree = rootRoute.addChildren([indexRoute, articlesRoute])
const router = createRouter({ routeTree, context: { queryClient } })
```
### 3. File-Based Routes
```tsx
// src/routes/index.tsx
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/')({
component: () => Home
,
})
```
```tsx
// src/routes/articles.tsx
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/articles')({
component: () => Articles
,
})
```
### 4. Tailwind 4 CSS-First Setup
#### In `src/styles.css`:
```css
@import "tailwindcss";
@theme {
--color-primary: oklch(0.647 0.22 0.23);
--font-sans: "Inter", sans-serif;
}
```
#### In `vite.config.ts`:
```ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import tailwindcss from 'tailwindcss'
import path from 'path'
export default defineConfig({
plugins: [react(), tailwindcss()],
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
},
},
})
```
## Running the App
```bash
cd frontend
npm run dev
```
Visit:
- Home: http://localhost:5173/
- Articles: http://localhost:5173/articles
## Adding New Routes
### Method 1: File-Based Routes (Recommended)
Create a new file in `src/routes/`:
```tsx
// src/routes/article-detail.tsx
import { createFileRoute } from '@tanstack/react-router'
import { useQuery } from '@tanstack/react-query'
import * as api from '../lib/api'
export const Route = createFileRoute('/articles/$id')({
component: () => {
const { id } = Route.useParams()
const { data } = useQuery({
queryKey: ['article', id],
queryFn: () => api.fetchArticleById(id),
})
return (
)
},
})
```
Then add to `src/main.tsx`:
```tsx
import { articleDetailRoute } from './routes/article-detail'
const routeTree = rootRoute.addChildren([indexRoute, articlesRoute, articleDetailRoute])
```
### Method 2: Using Link for Navigation
```tsx
import { Link } from '@tanstack/react-router'
// In your component
Read Article
```
## Adding Shadcn/ui Components
### Using the CLI (Recommended)
```bash
cd frontend
npx shadcn@latest add [component-name]
```
### Common Components to Add
```bash
npx shadcn@latest add button # (already installed)
npx shadcn@latest add badge # For article tags
npx shadcn@latest add input # For search
npx shadcn@latest add dialog # For article details
npx shadcn@latest add dropdown-menu
npx shadcn@latest add select
npx shadcn@latest add tabs # For content organization
npx shadcn@latest add separator # For visual separation
npx shadcn@latest add skeleton # For loading states
npx shadcn@latest add pagination # For article list navigation
```
### Using Components in Routes
```tsx
import { Button } from '@/components/ui/button'
export const Route = createFileRoute('/articles')({
component: () => (
),
})
```
## Customization
### Theme Colors
Edit `src/styles.css`:
```css
@theme {
--color-primary: oklch(0.647 0.22 0.23);
--color-secondary: oklch(0.8 0.15 0.1);
--font-sans: "Your Font", sans-serif;
}
```
### Adding Fonts
Edit `src/styles.css`:
```css
@theme {
--font-sans: "Inter", sans-serif;
}
@layer base {
* {
@apply font-sans;
}
}
```
### Dark Mode
Add dark mode toggle to header:
```tsx
import { useEffect } from 'react'
export const rootRoute = createRootRoute({
component: () => {
const toggleDarkMode = () => {
document.documentElement.classList.toggle('dark')
localStorage.setItem('theme',
document.documentElement.classList.contains('dark') ? 'dark' : 'light'
)
}
return (
)
},
})
```
## File Structure
```
frontend/
├── src/
│ ├── components/
│ │ └── ui/ # shadcn/ui components
│ ├── lib/
│ │ ├── api.ts # Backend API functions
│ │ ├── query-client.ts # TanStack Query configuration
│ │ └── utils.ts # cn() utility (for shadcn/ui)
│ ├── routes/ # TanStack Router routes
│ │ ├── root.tsx # Root layout
│ │ ├── index.tsx # Home page
│ │ └── articles.tsx # Articles list
│ ├── styles.css # Tailwind CSS + theme
│ └── main.tsx # App entry point
├── components.json # shadcn/ui configuration
├── vite.config.ts # Vite + Tailwind CSS plugin
├── tailwind.config.js # (Not used - CSS-first approach)
└── package.json
```
## Troubleshooting
### Routes Not Working
1. Check that route files are in `src/routes/`
2. Check export: `export const Route = createFileRoute(...)`
3. Check imports in `src/main.tsx`
4. Restart dev server
### Styles Not Applying
1. Check `src/styles.css` has `@import "tailwindcss"`
2. Check `vite.config.ts` has `tailwindcss()` plugin
3. Restart dev server
4. Hard refresh browser (Ctrl+Shift+R)
### Component Imports Not Working
1. Check `tsconfig.json` has `@/` paths configured
2. Check `vite.config.ts` has resolve alias for `@/`
3. Restart TypeScript server (VSCode: Cmd+Shift+P → "TypeScript: Restart TS Server")
### TanStack Query Not Fetching
1. Check backend is running: `http://localhost:3000`
2. Check `.env` has correct API URL
3. Check browser network tab for failed requests
4. Check CORS configuration in backend
## Best Practices
### 1. Route Organization
- Keep routes in `src/routes/` directory
- Use file-based routing for simple pages
- Use nested routes for related content
### 2. Component Reusability
- Create reusable components in `src/components/`
- Use shadcn/ui for consistent styling
- Extract common patterns (loading states, error states)
### 3. Data Fetching
- Use TanStack Query for all server state
- Implement proper loading and error states
- Use query keys consistently
### 4. Performance
- Use `lazy()` for code splitting large components
- Implement image lazy loading
- Use `defer` for non-critical resources
### 5. SEO
- Add meta tags to root route
- Add Open Graph tags
- Implement structured data
## Next Steps
1. **Restart dev server** to load new configuration
2. **Visit home page**: http://localhost:5173/
3. **Visit articles page**: http://localhost:5173/articles
4. **Add article detail page** with `$id` parameter
5. **Add shadcn/ui components** as needed
6. **Add dark mode toggle**
7. **Add search functionality**
8. **Add category/tag filtering**
## Resources
- [TanStack Router Docs](https://tanstack.com/router/latest/docs/framework/react/start/file-based-routing)
- [Tailwind CSS 4 Docs](https://tailwindcss.com/docs/installation/using-postcss)
- [Shadcn/ui Documentation](https://ui.shadcn.com)
- [TanStack Query Docs](https://tanstack.com/query/latest)