# Frontend Setup Complete - TanStack Router + Tailwind 4 ✅ ## Quick Start ```bash cd frontend npm run dev ``` Visit: - Home: http://localhost:5173/ - Articles: http://localhost:5173/articles ## Architecture ### Tech Stack - **React 19** - UI framework - **TanStack Router** - File-based routing - **TanStack Query** - Server state management - **Tailwind CSS 4** - CSS-first (v4 no config file) - **Shadcn/ui** - Pre-built components - **TypeScript** - Type safety ### Project Structure ``` frontend/ ├── src/ │ ├── components/ │ │ └── ui/ # shadcn/ui components │ │ ├── button.tsx │ │ └── card.tsx │ ├── lib/ │ │ ├── api.ts # Backend API functions │ │ ├── query-client.ts # TanStack Query config │ │ └── utils.ts # cn() utility │ ├── 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 ├── components.json # shadcn/ui config ├── vite.config.ts # Vite + Tailwind CSS plugin └── package.json ``` ## Pages & Routes ### Home Page (`/`) - Welcome message about Placebo.mk - "Welcome" card with intro - "Get Started" card with feature list - Centered layout with max-width container ### Articles Page (`/articles`) - Grid of article cards (responsive: 1/2/3 columns) - Each card shows: - Title (truncated to 2 lines) - Excerpt (truncated to 3 lines) - Content preview (truncated to 4 lines) - Creation date - View count - Loading state - Error state - Empty state when no articles ### Root Layout - Header with navigation (Home, Articles links) - Main content area with `` - Footer with copyright - SEO meta tags - Tailwind CSS import ## Components ### Card (`src/components/ui/card.tsx`) - Card - Main container - CardHeader - Header section - CardTitle - Title (h3 element) - CardDescription - Description (p element) - CardContent - Content area - CardFooter - Footer area ### Button (`src/components/ui/button.tsx`) - Variants: default, destructive, outline, secondary, ghost, link - Sizes: default, sm, lg, icon - Uses shadcn/ui theming system - Ready to use (not used yet) ## Utilities ### cn() Function (`src/lib/utils.ts`) ```tsx import { cn } from '@/lib/utils' // Merge Tailwind classes with conditional logic
``` ## Styling ### Tailwind CSS 4 (CSS-First) Configuration in `src/styles.css`: ```css @import "tailwindcss"; @theme { --color-primary: oklch(0.647 0.22 0.23); --font-sans: "Inter", sans-serif; } ``` ### Shadcn/ui Theme CSS variables in `src/styles.css`: - `--background` - Background color - `--foreground` - Text color - `--card` - Card background - `--primary` - Primary brand color - `--muted` - Muted text color - Dark mode support with `.dark` class ## Data Flow ### API Layer (`src/lib/api.ts`) - `fetchArticles()` - Get all articles with filters - `fetchArticleById()` - Get single article by ID - `fetchArticleBySlug()` - Get article by slug ### TanStack Query - Automatic caching - Refetch on window focus (disabled) - Stale time: 5 minutes - Retry: 1 attempt - Query client shared across app ## Backend Integration ### API Configuration ```typescript const API_BASE_URL = import.meta.env.VITE_API_URL || 'http://localhost:3000/api/v1' ``` ### Environment Variables Create `frontend/.env`: ```bash VITE_API_URL=http://localhost:3000/api/v1 ``` ## Adding New Pages ### Method 1: File-Based Routes (Current) Create new route file in `src/routes/`: ```tsx // src/routes/about.tsx import { createFileRoute } from '@tanstack/react-router' export const Route = createFileRoute('/about')({ component: () =>
About Page
, }) ``` Add to `src/main.tsx`: ```tsx import { aboutRoute } from './routes/about' const routeTree = rootRoute.addChildren([indexRoute, articlesRoute, aboutRoute]) ``` ### Method 2: Using TanStack Router Create routes dynamically in existing route files. ## Adding Shadcn/ui Components ### Using CLI (Recommended) ```bash cd frontend npx shadcn@latest add [component-name] ``` ### Recommended Components ```bash npx shadcn@latest add badge # Article tags npx shadcn@latest add input # Search box npx shadcn@latest add dialog # Article detail modal npx shadcn@latest add tabs # Content organization npx shadcn@latest add separator # Visual separation npx shadcn@latest add skeleton # Loading placeholder npx shadcn@latest add pagination # Article list navigation npx shadcn@latest add dropdown-menu # Menus and filters npx shadcn@latest add select # Dropdown selectors ``` ## Customization ### Changing Brand Colors Edit `src/styles.css`: ```css @theme { --color-primary: oklch(0.7 0.5 0.2); /* Your brand color */ --font-sans: "Your Font", sans-serif; } ``` ### Dark Mode Add toggle button to header: ```tsx // src/routes/root.tsx const toggleDarkMode = () => { document.documentElement.classList.toggle('dark') localStorage.setItem('theme', document.documentElement.classList.contains('dark') ? 'dark' : 'light' ) } // In component ``` ### Typography Edit `src/styles.css`: ```css @theme { --font-sans: "Your Custom Font", sans-serif; } @layer base { * { @apply font-sans; } } ``` ## Troubleshooting ### Routes Not Loading 1. Check route files exist in `src/routes/` 2. Check exports: `export const Route = createFileRoute(...)` 3. Check route tree in `src/main.tsx` 4. Restart dev server ### Styles Not Applying 1. Check `src/styles.css` has Tailwind directives 2. Check `vite.config.ts` has `tailwindcss()` plugin 3. Restart dev server 4. Hard refresh browser (Ctrl+Shift+R) ### Component Imports Failing 1. Check `tsconfig.json` has `@/` paths 2. Check import paths are correct: `@/components/ui/component` 3. Restart TypeScript server (VSCode: Cmd+Shift+P) ### Data Not Fetching 1. Check backend is running: `http://localhost:3000` 2. Check `.env` file exists and has correct API URL 3. Check browser network tab for failed requests 4. Check CORS in backend (`backend/src/main.ts`) ### TypeScript Errors 1. Run: `npm run type-check` 2. Restart TypeScript server (VSCode) 3. Clear Vite cache: `rm -rf node_modules/.vite` ## Performance Tips 1. **Code Splitting**: Use lazy() for large components 2. **Image Optimization**: Add loading="lazy" to article images 3. **Query Caching**: TanStack Query caches automatically 4. **Bundle Size**: Run `npm run build` and check size ## Development Workflow ### Adding New Article 1. Create article in Strapi CMS: http://localhost:1337/admin 2. Publish article 3. Sync to backend: `curl -X POST http://localhost:3000/api/v1/webhooks/strapi/sync/all` 4. Refresh frontend to see new article ### Running All Services ```bash # Terminal 1 - Backend cd backend npm run start:dev # Terminal 2 - Frontend cd frontend npm run dev # Terminal 3 - Strapi CMS (optional) cd cms/cms npm run develop ``` ## Testing ### Manual Testing ```bash # Test API curl http://localhost:3000/api/v1/articles # Test frontend npm run dev # Open http://localhost:5173 ``` ### Type Checking ```bash cd frontend npm run type-check ``` ## Next Steps 1. Add article detail page with `$id` parameter 2. Add search input for filtering articles 3. Add category/tag filtering 4. Add pagination for article lists 5. Add dark mode toggle 6. Add "about" page with site information 7. Add "contact" page or form 8. Add article comments system 9. Add social sharing buttons 10. Add analytics for article views ## Files to Edit | File | Purpose | |-------|---------| | `src/styles.css` | Theme colors, fonts, CSS variables | | `vite.config.ts` | Vite plugins, path aliases | | `components.json` | shadcn/ui configuration | | `tsconfig.json` | TypeScript paths | | `.env` | Environment variables | ## Resources - [TanStack Router Docs](https://tanstack.com/router/latest) - [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)