8.3 KiB
8.3 KiB
Frontend Setup Complete - TanStack Router + Tailwind 4 ✅
Quick Start
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
<Outlet /> - 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)
import { cn } from '@/lib/utils'
// Merge Tailwind classes with conditional logic
<div className={cn(
'base-class',
isActive && 'active-class',
className
)}>
Styling
Tailwind CSS 4 (CSS-First)
Configuration in src/styles.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
.darkclass
Data Flow
API Layer (src/lib/api.ts)
fetchArticles()- Get all articles with filtersfetchArticleById()- Get single article by IDfetchArticleBySlug()- 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
const API_BASE_URL = import.meta.env.VITE_API_URL || 'http://localhost:3000/api/v1'
Environment Variables
Create frontend/.env:
VITE_API_URL=http://localhost:3000/api/v1
Adding New Pages
Method 1: File-Based Routes (Current)
Create new route file in src/routes/:
// src/routes/about.tsx
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/about')({
component: () => <div>About Page</div>,
})
Add to src/main.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)
cd frontend
npx shadcn@latest add [component-name]
Recommended Components
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:
@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:
// src/routes/root.tsx
const toggleDarkMode = () => {
document.documentElement.classList.toggle('dark')
localStorage.setItem('theme',
document.documentElement.classList.contains('dark') ? 'dark' : 'light'
)
}
// In component
<button onClick={toggleDarkMode}>Toggle Theme</button>
Typography
Edit src/styles.css:
@theme {
--font-sans: "Your Custom Font", sans-serif;
}
@layer base {
* {
@apply font-sans;
}
}
Troubleshooting
Routes Not Loading
- Check route files exist in
src/routes/ - Check exports:
export const Route = createFileRoute(...) - Check route tree in
src/main.tsx - Restart dev server
Styles Not Applying
- Check
src/styles.csshas Tailwind directives - Check
vite.config.tshastailwindcss()plugin - Restart dev server
- Hard refresh browser (Ctrl+Shift+R)
Component Imports Failing
- Check
tsconfig.jsonhas@/paths - Check import paths are correct:
@/components/ui/component - Restart TypeScript server (VSCode: Cmd+Shift+P)
Data Not Fetching
- Check backend is running:
http://localhost:3000 - Check
.envfile exists and has correct API URL - Check browser network tab for failed requests
- Check CORS in backend (
backend/src/main.ts)
TypeScript Errors
- Run:
npm run type-check - Restart TypeScript server (VSCode)
- Clear Vite cache:
rm -rf node_modules/.vite
Performance Tips
- Code Splitting: Use lazy() for large components
- Image Optimization: Add loading="lazy" to article images
- Query Caching: TanStack Query caches automatically
- Bundle Size: Run
npm run buildand check size
Development Workflow
Adding New Article
- Create article in Strapi CMS: http://localhost:1337/admin
- Publish article
- Sync to backend:
curl -X POST http://localhost:3000/api/v1/webhooks/strapi/sync/all - Refresh frontend to see new article
Running All Services
# 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
# Test API
curl http://localhost:3000/api/v1/articles
# Test frontend
npm run dev
# Open http://localhost:5173
Type Checking
cd frontend
npm run type-check
Next Steps
- Add article detail page with
$idparameter - Add search input for filtering articles
- Add category/tag filtering
- Add pagination for article lists
- Add dark mode toggle
- Add "about" page with site information
- Add "contact" page or form
- Add article comments system
- Add social sharing buttons
- 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 |