diff --git a/client/src/App.jsx b/client/src/App.jsx
index f67355a..c7b613f 100644
--- a/client/src/App.jsx
+++ b/client/src/App.jsx
@@ -1,35 +1,29 @@
-import { useState } from 'react'
-import reactLogo from './assets/react.svg'
-import viteLogo from '/vite.svg'
+import { Routes, Route } from 'react-router-dom'
+import Header from './components/Header'
+import Footer from './components/Footer'
+import About from './pages/About'
+import Blog from './pages/Blog'
+import Post from './pages/Post'
+import Projects from './pages/Projects'
+import NotFound from './pages/NotFound'
import './App.css'
function App() {
- const [count, setCount] = useState(0)
-
return (
- <>
-
- Vite + React
-
-
-
- Edit src/App.jsx
and save to test HMR
-
-
-
- Click on the Vite and React logos to learn more
-
- >
+
+
+
+
+ } />
+ } />
+ } />
+ } />
+ } />
+
+
+
+
)
}
-export default App
+export default App
\ No newline at end of file
diff --git a/client/src/components/Footer.jsx b/client/src/components/Footer.jsx
new file mode 100644
index 0000000..2d338e1
--- /dev/null
+++ b/client/src/components/Footer.jsx
@@ -0,0 +1,20 @@
+import './Footer.css'
+
+function Footer() {
+ const currentYear = new Date().getFullYear()
+
+ return (
+
+ )
+}
+
+export default Footer
\ No newline at end of file
diff --git a/client/src/components/Headers.jsx b/client/src/components/Headers.jsx
new file mode 100644
index 0000000..aa37c2f
--- /dev/null
+++ b/client/src/components/Headers.jsx
@@ -0,0 +1,21 @@
+import { NavLink } from 'react-router-dom'
+import './Header.css'
+
+function Header() {
+ return (
+
+
+
Your Name
+
+
+
+ )
+}
+
+export default Header
\ No newline at end of file
diff --git a/client/src/main.jsx b/client/src/main.jsx
index b9a1a6d..f4fa3e5 100644
--- a/client/src/main.jsx
+++ b/client/src/main.jsx
@@ -1,10 +1,13 @@
-import { StrictMode } from 'react'
-import { createRoot } from 'react-dom/client'
-import './index.css'
+import React from 'react'
+import ReactDOM from 'react-dom/client'
+import { BrowserRouter } from 'react-router-dom'
import App from './App.jsx'
+import './index.css'
-createRoot(document.getElementById('root')).render(
-
-
- ,
+ReactDOM.createRoot(document.getElementById('root')).render(
+
+
+
+
+ ,
)
diff --git a/client/src/pages/About.jsx b/client/src/pages/About.jsx
new file mode 100644
index 0000000..4d8ea7b
--- /dev/null
+++ b/client/src/pages/About.jsx
@@ -0,0 +1,44 @@
+import './About.css'
+
+function About() {
+ return (
+
+
+
About Me
+
+
+

+
+
+
+ Hello, I'm [Your Name]. I'm a [Your Profession] based in [Your Location].
+ I specialize in [Your Skills/Specialties].
+
+
+ I've worked on various projects, from [Type of Project] to [Type of Project].
+ My goal is to [Your Professional Goal].
+
+
+ When I'm not coding, I enjoy [Your Hobbies/Interests].
+
+
+
Skills
+
+ - JavaScript (React, Node.js)
+ - HTML & CSS
+ - Python
+ {/* Add more skills as needed */}
+
+
+
+
+
+
+
+ )
+}
+
+export default About
\ No newline at end of file
diff --git a/client/src/pages/Blog.jsx b/client/src/pages/Blog.jsx
new file mode 100644
index 0000000..96bd4c7
--- /dev/null
+++ b/client/src/pages/Blog.jsx
@@ -0,0 +1,109 @@
+import { useState, useEffect } from 'react'
+import { Link } from 'react-router-dom'
+import axios from 'axios'
+import { format } from 'date-fns'
+import './Blog.css'
+
+function Blog() {
+ const [posts, setPosts] = useState([])
+ const [loading, setLoading] = useState(true)
+ const [error, setError] = useState(null)
+ const [selectedTag, setSelectedTag] = useState(null)
+
+ useEffect(() => {
+ const fetchPosts = async () => {
+ try {
+ const response = await axios.get('http://localhost:5000/api/posts')
+ setPosts(response.data)
+ setLoading(false)
+ } catch (err) {
+ console.error('Error fetching posts:', err)
+ setError('Failed to load blog posts. Please try again later.')
+ setLoading(false)
+ }
+ }
+
+ fetchPosts()
+ }, [])
+
+ // Extract all unique tags from posts
+ const allTags = posts.reduce((tags, post) => {
+ if (post.tags) {
+ post.tags.forEach(tag => {
+ if (!tags.includes(tag)) {
+ tags.push(tag)
+ }
+ })
+ }
+ return tags
+ }, [])
+
+ // Filter posts by selected tag
+ const filteredPosts = selectedTag
+ ? posts.filter(post => post.tags && post.tags.includes(selectedTag))
+ : posts
+
+ if (loading) return Loading posts...
+ if (error) return {error}
+
+ return (
+
+
+
Blog
+
+ {allTags.length > 0 && (
+
+ Filter by tag:
+
+ {allTags.map(tag => (
+
+ ))}
+
+ )}
+
+
+ {filteredPosts.length === 0 ? (
+
No posts found.
+ ) : (
+ filteredPosts.map(post => (
+
+
+ {post.title}
+
+
+
+ {post.tags && (
+
+ {post.tags.map(tag => (
+ setSelectedTag(tag)}>
+ {tag}
+
+ ))}
+
+ )}
+
+ {post.excerpt}
+
+ Read more →
+
+
+ ))
+ )}
+
+
+
+ )
+}
+
+export default Blog
\ No newline at end of file
diff --git a/client/src/pages/NotFound.jsx b/client/src/pages/NotFound.jsx
new file mode 100644
index 0000000..580f909
--- /dev/null
+++ b/client/src/pages/NotFound.jsx
@@ -0,0 +1,21 @@
+import { Link } from 'react-router-dom'
+import './NotFound.css'
+
+function NotFound() {
+ return (
+
+
+
404
+
Page Not Found
+
+ Oops! The page you're looking for doesn't exist or has been moved.
+
+
+ Go back to homepage
+
+
+
+ )
+}
+
+export default NotFound
\ No newline at end of file
diff --git a/client/src/pages/Post.jsx b/client/src/pages/Post.jsx
new file mode 100644
index 0000000..3a2d650
--- /dev/null
+++ b/client/src/pages/Post.jsx
@@ -0,0 +1,72 @@
+import { useState, useEffect } from 'react'
+import { useParams, Link, useNavigate } from 'react-router-dom'
+import axios from 'axios'
+import { format } from 'date-fns'
+import './Post.css'
+
+function Post() {
+ const { slug } = useParams()
+ const navigate = useNavigate()
+ const [post, setPost] = useState(null)
+ const [loading, setLoading] = useState(true)
+ const [error, setError] = useState(null)
+
+ useEffect(() => {
+ const fetchPost = async () => {
+ try {
+ const response = await axios.get(`http://localhost:5000/api/posts/${slug}`)
+ setPost(response.data)
+ setLoading(false)
+ } catch (err) {
+ console.error(`Error fetching post with slug ${slug}:`, err)
+ setError('Post not found or unable to load.')
+ setLoading(false)
+ }
+ }
+
+ fetchPost()
+ }, [slug])
+
+ if (loading) return Loading post...
+ if (error) return {error}
+ if (!post) return Post not found
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
+
+export default Post
\ No newline at end of file
diff --git a/client/src/pages/Projects.jsx b/client/src/pages/Projects.jsx
new file mode 100644
index 0000000..2d4eeb4
--- /dev/null
+++ b/client/src/pages/Projects.jsx
@@ -0,0 +1,104 @@
+import { useState, useEffect } from 'react'
+import axios from 'axios'
+import './Projects.css'
+
+function ProjectCard({ project }) {
+ return (
+
+ {project.image && (
+
+

+
+ )}
+
+
{project.title}
+
{project.description}
+
+ {project.technologies.map(tech => (
+ {tech}
+ ))}
+
+
+
+
+ )
+}
+
+function Projects() {
+ const [projects, setProjects] = useState([])
+ const [loading, setLoading] = useState(true)
+ const [error, setError] = useState(null)
+
+ useEffect(() => {
+ const fetchProjects = async () => {
+ try {
+ const response = await axios.get('http://localhost:5000/api/projects')
+ setProjects(response.data)
+ setLoading(false)
+ } catch (err) {
+ console.error('Error fetching projects:', err)
+ setError('Failed to load projects. Please try again later.')
+ setLoading(false)
+ }
+ }
+
+ fetchProjects()
+ }, [])
+
+ // Sort projects to show featured ones first
+ const sortedProjects = [...projects].sort((a, b) => {
+ if (a.featured && !b.featured) return -1
+ if (!a.featured && b.featured) return 1
+ return 0
+ })
+
+ if (loading) return Loading projects...
+ if (error) return {error}
+
+ return (
+
+
+
Projects
+
+ Here are some of the projects I've worked on. Check out my
+
+ GitHub profile
+ for more.
+
+
+
+ {sortedProjects.length === 0 ? (
+
No projects found.
+ ) : (
+ sortedProjects.map(project => (
+
+ ))
+ )}
+
+
+
+ )
+}
+
+export default Projects
\ No newline at end of file