Building a Modern Blog Platform with React 19, TypeScript, and shadcn/ui
In this article, I'll walk you through building a complete blog platform using the latest web technologies. We'll create a feature-rich application with authentication, role-based access control, and a beautiful, responsive UI.
🔗 Full Source Code: You can find the complete project on GitHub: blog-ts Repository
🚀 Project Overview
Our blog platform includes:
- Modern Authentication System with login/register modals
- Role-Based Access Control (Admin, Author, Reader)
- Blog Management with posts, authors, and tags
- Responsive Design with Tailwind CSS
- Type-Safe Development with strict TypeScript
- Modern UI Components using shadcn/ui and Radix UI
🛠 Tech Stack
Core Technologies
- React 19 - Latest React with improved performance
- TypeScript 5.8 - Strict typing for better development experience
- Vite - Lightning-fast build tool
- pnpm - Efficient package management
UI & Styling
- Tailwind CSS 4.1 - Utility-first CSS framework
- shadcn/ui - Beautiful, accessible UI components
- Radix UI - Unstyled, accessible components
- Lucide React - Beautiful icon library
State Management & Data
- React Query (TanStack) - Powerful data fetching and caching
- React Auth Kit - Complete authentication solution
- Custom Hooks - Reusable business logic
📁 Project Structure
blog-ts/
├── src/
│ ├── components/
│ │ ├── ui/ # shadcn/ui components
│ │ ├── auth/ # Authentication components
│ │ ├── blog/ # Blog-specific components
│ │ └── layout/ # Layout components
│ ├── hooks/ # Custom React hooks
│ ├── services/ # API services
│ ├── types/ # TypeScript type definitions
│ ├── lib/ # Utility functions
│ └── data/ # Mock data
├── public/ # Static assets
└── package.json
🔧 Key Features Implementation
1. Authentication System
The authentication system uses React Auth Kit with custom hooks for a seamless user experience.
Type Definitions (src/types/auth.ts
):
export interface User {
id: string
email: string
name: string
avatar?: string
role: UserRole
createdAt: string
lastLoginAt?: string
}
export type UserRole = 'admin' | 'author' | 'reader'
export interface LoginCredentials {
email: string
password: string
rememberMe?: boolean
}
export interface RegisterCredentials {
email: string
password: string
confirmPassword: string
name: string
acceptTerms: boolean
}
Permission System:
export const PERMISSIONS = {
POSTS: {
CREATE: 'posts:create',
EDIT: 'posts:edit',
DELETE: 'posts:delete',
PUBLISH: 'posts:publish'
},
USERS: {
VIEW: 'users:view',
EDIT: 'users:edit',
DELETE: 'users:delete'
},
ADMIN: {
ACCESS: 'admin:access'
}
} as const
export const ROLE_PERMISSIONS: Record<UserRole, string[]> = {
admin: [
PERMISSIONS.POSTS.CREATE,
PERMISSIONS.POSTS.EDIT,
PERMISSIONS.POSTS.DELETE,
PERMISSIONS.POSTS.PUBLISH,
PERMISSIONS.USERS.VIEW,
PERMISSIONS.USERS.EDIT,
PERMISSIONS.USERS.DELETE,
PERMISSIONS.ADMIN.ACCESS
],
author: [
PERMISSIONS.POSTS.CREATE,
PERMISSIONS.POSTS.EDIT,
PERMISSIONS.POSTS.PUBLISH
],
reader: []
}
2. Blog Data Models
Blog Post Interface (src/types/blog.ts
):
export interface BlogPost {
id: string;
title: string;
content: string;
excerpt: string;
author: Author;
publishedAt: string;
updatedAt?: string;
tags: string[];
featuredImage?: string;
readingTime: number;
isPublished: boolean;
slug: string;
views?: number;
}
export interface Author {
id: string;
name: string;
email: string;
avatar?: string;
bio?: string;
social?: {
twitter?: string;
linkedin?: string;
github?: string;
};
}
3. Main Application Component
The main App.tsx
showcases the integration of all features:
import { useState, memo } from 'react'
import { AuthModal } from '@/components/auth/AuthModal'
import { Button } from '@/components/ui/button'
import { Badge } from '@/components/ui/badge'
import { LoadingSpinner } from '@/components/ui/LoadingSpinner'
import { useAuth } from '@/hooks/useAuth'
import { useBlogData } from '@/hooks/useBlog'
export default memo(function App() {
const [authModalOpen, setAuthModalOpen] = useState(false)
const [authMode, setAuthMode] = useState<'login' | 'register'>('login')
const { isAuthenticated, isCheckingAuth, user, logout, isLoggingOut } = useAuth()
const { posts, authors, isLoading } = useBlogData()
// Component implementation...
})
4. Custom Hooks
Authentication Hook:
// Custom hook for authentication logic
const { isAuthenticated, isCheckingAuth, user, logout, isLoggingOut } = useAuth()
Blog Data Hook:
// Custom hook for blog data fetching with React Query
const { posts, authors, isLoading } = useBlogData()
🎨 UI Components
The project uses a comprehensive set of UI components:
- Authentication: Modal-based login/register forms
- Navigation: Responsive header with user status
- Cards: Blog post cards with hover effects
- Buttons: Various button variants and states
- Badges: Role indicators and tags
- Loading States: Spinners and skeleton loaders
Component Architecture
// Memoized component for performance
const AuthButtons = memo(function AuthButtons() {
if (isCheckingAuth) {
return <LoadingSpinner size="sm" />
}
if (isAuthenticated && user) {
return (
<div className="flex items-center gap-3">
<div className="flex items-center gap-2">
<User className="h-4 w-4" />
<span className="text-sm font-medium">{user.name}</span>
<Badge variant="secondary" className="text-xs">
{user.role}
</Badge>
</div>
{/* Logout and settings buttons */}
</div>
)
}
return (
<div className="flex items-center gap-2">
<Button variant="ghost" size="sm" onClick={handleLoginClick}>
Se connecter
</Button>
<Button variant="default" size="sm" onClick={handleRegisterClick}>
S'inscrire
</Button>
</div>
)
})
🚀 Getting Started
Prerequisites
- Node.js 18+
- pnpm (recommended package manager)
Installation
- Clone the repository:
git clone https://github.com/VincentCapek/blog-ts.git
cd blog-ts
pnpm install
- Development:
pnpm dev
- Build for production:
pnpm build
pnpm preview
Configuration
The project uses pnpm exclusively with these key scripts:
{
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
"lint": "eslint .",
"preview": "vite preview"
}
}
📦 Key Dependencies
{
"dependencies": {
"react": "^19.1.0",
"react-dom": "^19.1.0",
"@tanstack/react-query": "^5.81.5",
"react-auth-kit": "^3.1.3",
"@tailwindcss/vite": "^4.1.11",
"tailwindcss": "^4.1.11",
"@radix-ui/react-avatar": "^1.1.10",
"@radix-ui/react-dialog": "^1.1.14",
"lucide-react": "^0.525.0",
"clsx": "^2.1.1",
"tailwind-merge": "^3.3.1"
}
}
🔑 Key Features Breakdown
Authentication Flow
- Modal-based auth - Clean UX with overlays
- Persistent sessions - Remember user login state
- Role-based UI - Different interfaces per user role
- Secure logout - Proper token cleanup
Blog Features
- Article listing - Grid layout with excerpts
- Author profiles - Author information display
- Tag system - Categorization and filtering
- Reading time - Calculated reading estimates
- Responsive design - Mobile-first approach
Developer Experience
- TypeScript strict mode - Maximum type safety
- ESLint configuration - Code quality enforcement
- Component organization - Clear separation of concerns
- Custom hooks - Reusable business logic
- Performance optimization - React.memo for components
🎯 Best Practices Implemented
React Patterns
-
Memoization with
React.memo
for performance - Custom hooks for business logic separation
- Compound components for complex UI elements
- Controlled components for form handling
TypeScript Excellence
-
Strict typing with no
any
types - Interface definitions for all data structures
- Type guards for runtime safety
- Generic components for reusability
Code Organization
- Feature-based structure - Components grouped by functionality
- Barrel exports - Clean import statements
- Consistent naming - Clear, descriptive names
- Separation of concerns - Logic, UI, and data layers
🔮 Future Enhancements
Planned features for the next iterations:
- Rich Text Editor - For creating and editing posts
- Comment System - User engagement features
- Search Functionality - Full-text search across posts
- Social Sharing - Share buttons for posts
- Admin Dashboard - Content management interface
- SEO Optimization - Meta tags and structured data
- Dark Mode - Theme switching capability
- Infinite Scroll - Performance optimization for large lists
💡 Key Takeaways
This project demonstrates:
- Modern React development with the latest features
- Type-safe development with comprehensive TypeScript usage
- Component architecture with reusable, composable pieces
- Authentication patterns for real-world applications
- Performance optimization through memoization and code splitting
- User experience focus with loading states and responsive design
🤝 Contributing
The codebase is structured for easy contribution:
- Clear separation of UI, business logic, and data
- TypeScript interfaces for all contracts
- Consistent patterns throughout the application
- Comprehensive linting to maintain code quality
📚 Resources
- 🔗 Project Repository - Complete source code
- React 19 Documentation
- TypeScript Handbook
- shadcn/ui Components
- Tailwind CSS
- React Query Guide
This blog platform showcases how modern web development tools can come together to create a robust, scalable, and maintainable application. The combination of React 19, TypeScript, and modern tooling provides an excellent foundation for building complex web applications.
Top comments (0)