# 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 (

{data?.title}

) }, }) ``` 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)