This project is a responsive blog website built with React, Vite, and Tailwind CSS. The website includes a Home page, About page, Blog List page, and Blog Post Detail page. It fetches posts from the JSONPlaceholder API and uses the Lorem Picsum API for random images.
git clone https://github.com/yourusername/your-repo.git
cd your-repo
npm install
npm run dev
http://localhost:3000
in your browser to see the website.my-blog/
├── node_modules/
├── public/
├── src/
│ ├── components/
│ │ ├── Navbar.jsx
│ │ ├── PostCard.jsx
│ │ ├── Image.jsx
│ │ └── ErrorBoundary.jsx
│ ├── data/
│ │ └── posts.json
│ ├── hooks/
│ │ └── useFetchPosts.js
│ ├── pages/
│ │ ├── Home.jsx
│ │ ├── About.jsx
│ │ ├── BlogList.jsx
│ │ └── BlogPostDetail.jsx
│ ├── App.jsx
│ ├── index.css
│ ├── main.jsx
│ └── api-client.js
├── .env
├── tailwind.config.js
├── index.html
└── package.json
src/components/Navbar.jsx
A responsive navigation bar with links to the Home, About, and Blog pages. It also includes a button to toggle dark mode.
src/components/PostCard.jsx
A component that displays individual blog post previews, including the title, excerpt, and a "Read More" button. It uses the Image
component to display a post image.
src/components/Image.jsx
A component that handles lazy loading of images and displays a placeholder while the image is loading or an error message if the image fails to load.
src/components/ErrorBoundary.jsx
A component that catches JavaScript errors in any child component tree and displays a fallback UI.
src/hooks/useFetchPosts.js
A custom hook that fetches blog posts from the JSONPlaceholder API and assigns random images from the Lorem Picsum API.
import { useState, useEffect } from 'react';
import { fetchFromAPI } from '../api-client';
const LOREM_PICSUM_API_URL = 'https://picsum.photos/300/200?random=';
export const useFetchPosts = () => {
const [posts, setPosts] = useState([]);
useEffect(() => {
const fetchData = async () => {
try {
const postsData = await fetchFromAPI('posts');
const postsWithImages = postsData.slice(0, 10).map(post => ({
...post,
imageUrl: `${LOREM_PICSUM_API_URL}${post.id}`
}));
setPosts(postsWithImages);
} catch (error) {
console.error('Error fetching posts:', error);
}
};
fetchData();
}, []);
return posts;
};
src/api-client.js
A utility function to fetch data from the JSONPlaceholder API.
const API_BASE_URL = 'https://jsonplaceholder.typicode.com';
export const fetchFromAPI = async (endpoint) => {
const response = await fetch(`${API_BASE_URL}/${endpoint}`);
if (!response.ok) {
throw new Error('Network response was not ok');
}
return response.json();
};
Displays a welcome message and the latest blog posts.
Provides information about the blog and includes a contact form. Submitted data is displayed below the form.
Displays a list of all blog posts with pagination or infinite scrolling (if implemented).
Displays the full content of a blog post, including author information and a comments section.