├── .gitignore
├── README.md
├── eslint.config.mjs
├── next.config.ts
├── package-lock.json
├── package.json
├── postcss.config.mjs
├── public
├── profile.avif
└── projects
│ ├── blog-website.jpeg
│ ├── chat-app.png
│ ├── e-commerce-website.png
│ ├── expense-tracker.webp
│ ├── portfolio-website.jpg
│ ├── recipe-finder.png
│ ├── task-manager.webp
│ └── weather-app.png
├── src
├── app
│ ├── about
│ │ └── page.tsx
│ ├── api
│ │ └── contact
│ │ │ └── route.ts
│ ├── blogs
│ │ └── page.tsx
│ ├── components
│ │ ├── Blogs.tsx
│ │ ├── Footer.tsx
│ │ ├── Hero.tsx
│ │ ├── Navbar.tsx
│ │ ├── Newsletter.tsx
│ │ └── Projects.tsx
│ ├── contact
│ │ └── page.tsx
│ ├── context
│ │ └── ThemeContext.tsx
│ ├── favicon.ico
│ ├── globals.css
│ ├── layout.tsx
│ ├── page.tsx
│ └── projects
│ │ └── page.tsx
├── contents
│ ├── blogs.ts
│ └── projects.ts
├── types
│ └── index.ts
└── utils
│ └── animations.ts
└── tsconfig.json
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.*
7 | .yarn/*
8 | !.yarn/patches
9 | !.yarn/plugins
10 | !.yarn/releases
11 | !.yarn/versions
12 |
13 | # testing
14 | /coverage
15 |
16 | # next.js
17 | /.next/
18 | /out/
19 |
20 | # production
21 | /build
22 |
23 | # misc
24 | .DS_Store
25 | *.pem
26 |
27 | # debug
28 | npm-debug.log*
29 | yarn-debug.log*
30 | yarn-error.log*
31 | .pnpm-debug.log*
32 |
33 | # env files (can opt-in for committing if needed)
34 | .env*
35 |
36 | # vercel
37 | .vercel
38 |
39 | # typescript
40 | *.tsbuildinfo
41 | next-env.d.ts
42 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Devfolio
2 |
3 | Devfolio is a portfolio website built using Next.js, Tailwind CSS, and Framer Motion. It allows developers to showcase their projects, skills, and blogs in a visually appealing manner.
4 |
5 | ## Table of Contents
6 |
7 | - [Features](#features)
8 | - [Installation](#installation)
9 | - [Usage](#usage)
10 | - [Animations](#animations)
11 | - [Components](#components)
12 | - [Types](#types)
13 | - [Contributing](#contributing)
14 | - [License](#license)
15 |
16 | ## Features
17 |
18 | - Responsive design using Tailwind CSS
19 | - Smooth animations with Framer Motion
20 | - Dark mode support
21 | - Modular and reusable components
22 | - Easy to customize
23 |
24 | ## Installation
25 |
26 | To get started with Devfolio, follow these steps:
27 |
28 | 1. **Clone the repository:**
29 |
30 | ```bash
31 | git clone https://github.com/yourusername/devfolio.git
32 | cd devfolio
33 | ```
34 |
35 | 2. **Install the dependencies:**
36 |
37 | Make sure you have [Node.js](https://nodejs.org/) installed. Then, run the following command to install the necessary packages:
38 |
39 | ```bash
40 | npm install
41 | ```
42 |
43 | 3. **Run the development server:**
44 |
45 | Start the development server to view the project locally:
46 |
47 | ```bash
48 | npm run dev
49 | ```
50 |
51 | Open [http://localhost:3000](http://localhost:3000) in your browser to see the result.
52 |
53 | 4. **Build for production:**
54 |
55 | To create an optimized production build, run:
56 |
57 | ```bash
58 | npm run build
59 | ```
60 |
61 | 5. **Start the production server:**
62 |
63 | After building the project, you can start the production server with:
64 |
65 | ```bash
66 | npm start
67 | ```
68 |
69 | ## Usage
70 | The Devfolio project is structured to be intuitive and easy to navigate.
71 |
72 | By understanding the structure and components of Devfolio, you can easily customize and extend the project to fit your needs.
73 |
74 |
--------------------------------------------------------------------------------
/eslint.config.mjs:
--------------------------------------------------------------------------------
1 | import { dirname } from "path";
2 | import { fileURLToPath } from "url";
3 | import { FlatCompat } from "@eslint/eslintrc";
4 |
5 | const __filename = fileURLToPath(import.meta.url);
6 | const __dirname = dirname(__filename);
7 |
8 | const compat = new FlatCompat({
9 | baseDirectory: __dirname,
10 | });
11 |
12 | const eslintConfig = [
13 | ...compat.extends("next/core-web-vitals", "next/typescript"),
14 | ];
15 |
16 | export default eslintConfig;
17 |
--------------------------------------------------------------------------------
/next.config.ts:
--------------------------------------------------------------------------------
1 | import type { NextConfig } from "next";
2 |
3 | const nextConfig: NextConfig = {
4 | images: {
5 | remotePatterns: [
6 | {
7 | protocol: 'https',
8 | hostname: 'images.unsplash.com',
9 | port: '',
10 | pathname: '/**',
11 | },
12 | ],
13 | },
14 | };
15 |
16 | export default nextConfig;
17 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "portfolio-project-2",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "dev": "next dev --turbopack",
7 | "build": "next build",
8 | "start": "next start",
9 | "lint": "next lint"
10 | },
11 | "dependencies": {
12 | "@heroicons/react": "^2.2.0",
13 | "framer-motion": "^12.9.7",
14 | "next": "15.3.1",
15 | "react": "^19.0.0",
16 | "react-dom": "^19.0.0",
17 | "react-icons": "^5.5.0"
18 | },
19 | "devDependencies": {
20 | "@eslint/eslintrc": "^3",
21 | "@tailwindcss/postcss": "^4",
22 | "@types/node": "^20",
23 | "@types/react": "^19",
24 | "@types/react-dom": "^19",
25 | "eslint": "^9",
26 | "eslint-config-next": "15.3.1",
27 | "tailwindcss": "^4",
28 | "typescript": "^5"
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/postcss.config.mjs:
--------------------------------------------------------------------------------
1 | const config = {
2 | plugins: ["@tailwindcss/postcss"],
3 | };
4 |
5 | export default config;
6 |
--------------------------------------------------------------------------------
/public/profile.avif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mdalmamunit427/devfolio-nextjs-portfolio-website/5cfcf9e90e2caac0cebb56bfbea42a31347c243d/public/profile.avif
--------------------------------------------------------------------------------
/public/projects/blog-website.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mdalmamunit427/devfolio-nextjs-portfolio-website/5cfcf9e90e2caac0cebb56bfbea42a31347c243d/public/projects/blog-website.jpeg
--------------------------------------------------------------------------------
/public/projects/chat-app.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mdalmamunit427/devfolio-nextjs-portfolio-website/5cfcf9e90e2caac0cebb56bfbea42a31347c243d/public/projects/chat-app.png
--------------------------------------------------------------------------------
/public/projects/e-commerce-website.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mdalmamunit427/devfolio-nextjs-portfolio-website/5cfcf9e90e2caac0cebb56bfbea42a31347c243d/public/projects/e-commerce-website.png
--------------------------------------------------------------------------------
/public/projects/expense-tracker.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mdalmamunit427/devfolio-nextjs-portfolio-website/5cfcf9e90e2caac0cebb56bfbea42a31347c243d/public/projects/expense-tracker.webp
--------------------------------------------------------------------------------
/public/projects/portfolio-website.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mdalmamunit427/devfolio-nextjs-portfolio-website/5cfcf9e90e2caac0cebb56bfbea42a31347c243d/public/projects/portfolio-website.jpg
--------------------------------------------------------------------------------
/public/projects/recipe-finder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mdalmamunit427/devfolio-nextjs-portfolio-website/5cfcf9e90e2caac0cebb56bfbea42a31347c243d/public/projects/recipe-finder.png
--------------------------------------------------------------------------------
/public/projects/task-manager.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mdalmamunit427/devfolio-nextjs-portfolio-website/5cfcf9e90e2caac0cebb56bfbea42a31347c243d/public/projects/task-manager.webp
--------------------------------------------------------------------------------
/public/projects/weather-app.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mdalmamunit427/devfolio-nextjs-portfolio-website/5cfcf9e90e2caac0cebb56bfbea42a31347c243d/public/projects/weather-app.png
--------------------------------------------------------------------------------
/src/app/about/page.tsx:
--------------------------------------------------------------------------------
1 | 'use client'
2 |
3 | import { FaCode, FaLaptopCode, FaGraduationCap } from 'react-icons/fa'
4 | import { motion } from 'framer-motion'
5 | import {
6 | fadeInUp,
7 | fadeInDown,
8 | fadeIn,
9 | staggerContainer,
10 | cardHover,
11 | cardHoverSmall
12 | } from '@/utils/animations'
13 |
14 | export default function About() {
15 | return (
16 |
17 |
21 | About Me
22 |
23 |
24 | {/* Bio Section */}
25 |
29 |
30 | I'm a passionate Full Stack Developer with expertise in building modern web applications.
31 | With a strong foundation in both frontend and backend technologies, I create seamless
32 | user experiences and robust server-side solutions.
33 |
34 |
35 |
36 | {/* Skills Section */}
37 |
42 |
46 | Skills
47 |
48 |
54 |
59 |
60 | Frontend
61 |
62 | React / Next.js
63 | TypeScript
64 | Tailwind CSS
65 | HTML5 / CSS3
66 |
67 |
68 |
69 |
74 |
75 | Backend
76 |
77 | Node.js
78 | Express
79 | PostgreSQL
80 | MongoDB
81 |
82 |
83 |
84 |
89 |
90 | Tools & Others
91 |
92 | Git / GitHub
93 | Docker
94 | AWS
95 | CI/CD
96 |
97 |
98 |
99 |
100 |
101 | {/* Experience Section */}
102 |
107 |
111 | Experience
112 |
113 |
119 |
124 | Senior Full Stack Developer
125 | Company Name • 2020 - Present
126 |
127 | Led development of multiple web applications using React and Node.js
128 | Implemented CI/CD pipelines reducing deployment time by 50%
129 | Mentored junior developers and conducted code reviews
130 |
131 |
132 |
133 |
138 | Full Stack Developer
139 | Previous Company • 2018 - 2020
140 |
141 | Developed and maintained RESTful APIs
142 | Built responsive user interfaces with modern JavaScript frameworks
143 | Optimized database queries improving performance by 40%
144 |
145 |
146 |
147 |
148 |
149 | {/* Education Section */}
150 |
154 |
158 | Education
159 |
160 |
166 |
171 | Bachelor of Science in Computer Science
172 | University Name • 2014 - 2018
173 |
174 | Graduated with honors. Focused on software engineering and web development.
175 |
176 |
177 |
178 |
179 |
180 | )
181 | }
--------------------------------------------------------------------------------
/src/app/api/contact/route.ts:
--------------------------------------------------------------------------------
1 | import { NextResponse } from 'next/server'
2 |
3 | interface ContactRequestBody {
4 | name: string;
5 | email: string;
6 | message: string;
7 | }
8 |
9 | export async function POST(request: Request) {
10 | try {
11 | await request.json() as ContactRequestBody
12 | // Here you would typically:
13 | // 1. Validate the input
14 | // 2. Send an email using a service like SendGrid, AWS SES, etc.
15 | // 3. Store the message in a database if needed
16 |
17 | // For now, we'll just simulate a successful response
18 | return NextResponse.json(
19 | { message: 'Message sent successfully' },
20 | { status: 200 }
21 | )
22 | } catch (error: unknown) {
23 | const errorMessage = error instanceof Error ? error.message : 'Failed to send message'
24 | return NextResponse.json(
25 | { message: errorMessage },
26 | { status: 500 }
27 | )
28 | }
29 | }
--------------------------------------------------------------------------------
/src/app/blogs/page.tsx:
--------------------------------------------------------------------------------
1 | 'use client'
2 |
3 | import { blogs } from '@/contents/blogs'
4 | import Link from 'next/link'
5 | import { FaCalendarAlt, FaClock } from 'react-icons/fa'
6 | import { motion } from 'framer-motion'
7 | import { fadeInUp, staggerContainer, cardHoverSmall } from '@/utils/animations'
8 |
9 | export default function Blogs() {
10 | return (
11 |
12 |
18 | Blog Posts
19 |
20 |
21 |
27 | {blogs.map((blog, index) => (
28 |
34 |
35 |
40 |
41 | {blog.title}
42 |
43 |
44 |
45 |
51 | {blog.excerpt}
52 |
53 |
54 |
60 |
64 |
65 | {new Date(blog.date).toLocaleDateString()}
66 |
67 |
68 |
72 |
73 | {blog.readTime}
74 |
75 |
76 |
77 |
78 | ))}
79 |
80 |
81 | )
82 | }
--------------------------------------------------------------------------------
/src/app/components/Blogs.tsx:
--------------------------------------------------------------------------------
1 | 'use client'
2 |
3 | import { blogs } from '@/contents/blogs';
4 | import Link from 'next/link';
5 | import { FaCalendarAlt, FaClock } from 'react-icons/fa';
6 | import { motion } from 'framer-motion';
7 | import { fadeInUp, staggerContainer, cardHoverSmall } from '@/utils/animations';
8 |
9 | export default function Blogs() {
10 | return (
11 |
12 |
13 |
17 | Latest Blog Posts
18 |
19 |
20 |
26 | {blogs.map((blog) => (
27 |
33 |
34 |
39 | {blog.title}
40 |
41 |
42 |
48 | {blog.excerpt}
49 |
50 |
56 |
60 |
61 | {new Date(blog.date).toLocaleDateString()}
62 |
63 |
67 |
68 | {blog.readTime}
69 |
70 |
71 |
72 | ))}
73 |
74 |
75 |
81 |
85 |
89 | View All Posts
90 |
91 |
92 |
93 |
94 |
95 | );
96 | }
--------------------------------------------------------------------------------
/src/app/components/Footer.tsx:
--------------------------------------------------------------------------------
1 | import Link from 'next/link'
2 | import { FaGithub, FaTwitter, FaLinkedin } from 'react-icons/fa'
3 |
4 | export default function Footer() {
5 | return (
6 |
7 |
8 |
9 |
10 |
11 | Devfolio™
12 |
13 |
14 | © {new Date().getFullYear()} Devfolio. All rights reserved.
15 |
16 |
17 |
18 |
44 |
45 |
46 |
47 | )
48 | }
--------------------------------------------------------------------------------
/src/app/components/Hero.tsx:
--------------------------------------------------------------------------------
1 | 'use client'
2 |
3 | import Link from 'next/link';
4 | import Image from 'next/image';
5 | import { FaGithub, FaLinkedin, FaTwitter } from 'react-icons/fa';
6 | import { motion } from 'framer-motion';
7 | import { fadeInUp, fadeIn, scaleIn } from '@/utils/animations';
8 |
9 | export default function Hero() {
10 | return (
11 |
12 |
13 |
14 |
19 |
20 |
21 |
26 | Hi, I'm
31 | John Doe
32 |
33 |
34 |
39 | Full Stack Developer | UI/UX Enthusiast | Open Source Contributor
40 |
41 |
46 |
54 |
55 |
56 |
64 |
65 |
66 |
74 |
75 |
76 |
77 |
82 |
86 |
90 | View Projects
91 |
92 |
93 |
97 |
101 | Contact Me
102 |
103 |
104 |
105 |
106 |
107 |
108 | );
109 | }
--------------------------------------------------------------------------------
/src/app/components/Navbar.tsx:
--------------------------------------------------------------------------------
1 | 'use client'
2 | import Link from 'next/link'
3 | import { SunIcon, MoonIcon, Bars3Icon, XMarkIcon } from '@heroicons/react/24/outline'
4 | import { useTheme } from '../context/ThemeContext'
5 | import { motion, AnimatePresence } from 'framer-motion'
6 | import { useState } from 'react'
7 |
8 | export default function Navbar() {
9 | const { theme, toggleTheme } = useTheme();
10 | const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);
11 |
12 | const toggleMobileMenu = () => {
13 | setIsMobileMenuOpen(!isMobileMenuOpen);
14 | };
15 |
16 | const menuItems = [
17 | { href: '/', label: 'Home' },
18 | { href: '/about', label: 'About' },
19 | { href: '/projects', label: 'Projects' },
20 | { href: '/blogs', label: 'Blogs' },
21 | { href: '/contact', label: 'Contact' },
22 | ];
23 |
24 | return (
25 |
26 |
27 |
28 |
29 | Devfolio™
30 |
31 |
32 | {/* Desktop Menu */}
33 |
34 | {menuItems.map((item) => (
35 |
40 | {item.label}
41 |
42 | ))}
43 |
49 | {theme === 'dark' ? (
50 |
51 | ) : (
52 |
53 | )}
54 |
55 |
56 |
57 | {/* Mobile Menu Button */}
58 |
64 | {isMobileMenuOpen ? (
65 |
66 | ) : (
67 |
68 | )}
69 |
70 |
71 |
72 | {/* Mobile Menu */}
73 |
74 | {isMobileMenuOpen && (
75 |
82 |
83 | {menuItems.map((item, index) => (
84 |
90 | setIsMobileMenuOpen(false)}
94 | >
95 | {item.label}
96 |
97 |
98 | ))}
99 |
104 | {
106 | toggleTheme();
107 | setIsMobileMenuOpen(false);
108 | }}
109 | className="flex items-center py-2 hover:text-primary transition-colors"
110 | >
111 | {theme === 'dark' ? (
112 | <>
113 |
114 | Light Mode
115 | >
116 | ) : (
117 | <>
118 |
119 | Dark Mode
120 | >
121 | )}
122 |
123 |
124 |
125 |
126 | )}
127 |
128 |
129 |
130 | )
131 | }
--------------------------------------------------------------------------------
/src/app/components/Newsletter.tsx:
--------------------------------------------------------------------------------
1 | export default function Newsletter() {
2 | return (
3 |
4 |
5 |
6 |
7 |
8 |
9 |
Subscribe to My Newsletter
10 |
11 | Get the latest updates on my projects, blog posts, and tech insights delivered straight to your inbox.
12 |
13 |
14 |
28 |
29 |
30 |
31 |
32 |
33 | );
34 | }
--------------------------------------------------------------------------------
/src/app/components/Projects.tsx:
--------------------------------------------------------------------------------
1 | 'use client'
2 |
3 | import { projects } from '@/contents/projects'
4 | import Image from 'next/image'
5 | import { FaGithub, FaExternalLinkAlt } from 'react-icons/fa'
6 | import { motion } from 'framer-motion'
7 | import { fadeInUp, staggerContainer, cardHoverSmall } from '@/utils/animations'
8 |
9 | export default function Projects() {
10 | return (
11 |
12 |
13 |
17 | Featured Projects
18 |
19 |
20 |
26 | {projects.map((project) => (
27 |
33 |
34 |
41 |
42 |
47 | {project.title}
48 |
49 |
55 | {project.description}
56 |
57 |
63 | {project.technologies.map((tech) => (
64 |
70 | {tech}
71 |
72 | ))}
73 |
74 |
80 |
88 |
89 | Code
90 |
91 |
99 |
100 | Live Demo
101 |
102 |
103 |
104 | ))}
105 |
106 |
107 |
108 | )
109 | }
--------------------------------------------------------------------------------
/src/app/contact/page.tsx:
--------------------------------------------------------------------------------
1 | 'use client'
2 |
3 | import { useState } from 'react'
4 | import { FaEnvelope, FaPhone, FaMapMarkerAlt } from 'react-icons/fa'
5 | import { motion } from 'framer-motion'
6 | import { fadeInUp, fadeIn, slideInLeft, slideInRight } from '@/utils/animations'
7 |
8 | interface FormData {
9 | name: string;
10 | email: string;
11 | message: string;
12 | }
13 |
14 | type FormStatus = 'idle' | 'loading' | 'success' | 'error';
15 |
16 | export default function Contact() {
17 | const [formData, setFormData] = useState({
18 | name: '',
19 | email: '',
20 | message: ''
21 | })
22 | const [status, setStatus] = useState('idle')
23 |
24 | const handleSubmit = async (e: React.FormEvent) => {
25 | e.preventDefault()
26 | setStatus('loading')
27 |
28 | try {
29 | const response = await fetch('/api/contact', {
30 | method: 'POST',
31 | headers: {
32 | 'Content-Type': 'application/json',
33 | },
34 | body: JSON.stringify(formData),
35 | })
36 |
37 | if (!response.ok) throw new Error('Failed to send message')
38 |
39 | setStatus('success')
40 | setFormData({ name: '', email: '', message: '' })
41 | } catch {
42 | setStatus('error')
43 | }
44 | }
45 |
46 | const handleChange = (e: React.ChangeEvent) => {
47 | setFormData(prev => ({
48 | ...prev,
49 | [e.target.name]: e.target.value
50 | }))
51 | }
52 |
53 | return (
54 |
55 |
59 | Contact Me
60 |
61 |
62 |
63 | {/* Contact Information */}
64 |
68 |
69 | Get in Touch
70 |
71 | I'm always open to discussing new projects, creative ideas, or
72 | opportunities to be part of your visions.
73 |
74 |
75 |
76 |
82 |
88 |
89 |
95 |
96 |
97 |
103 |
104 |
110 |
111 |
112 |
118 |
119 |
120 |
Location
121 |
San Francisco, CA
122 |
123 |
124 |
125 |
126 |
127 | {/* Contact Form */}
128 |
132 |
139 |
140 |
141 | Name
142 |
143 |
152 |
153 |
154 |
155 |
156 | Email
157 |
158 |
167 |
168 |
169 |
170 |
171 | Message
172 |
173 |
182 |
183 |
184 |
191 | {status === 'loading' ? 'Sending...' : 'Send Message'}
192 |
193 |
194 | {status === 'success' && (
195 |
200 | Message sent successfully!
201 |
202 | )}
203 |
204 | {status === 'error' && (
205 |
210 | Failed to send message. Please try again.
211 |
212 | )}
213 |
214 |
215 |
216 |
217 | )
218 | }
--------------------------------------------------------------------------------
/src/app/context/ThemeContext.tsx:
--------------------------------------------------------------------------------
1 | "use client";
2 |
3 | import { createContext, useContext, useEffect, useState } from "react";
4 |
5 | type Theme = "light" | "dark";
6 |
7 | interface ThemeContextType {
8 | theme: Theme;
9 | toggleTheme: () => void;
10 | setTheme: (theme: Theme) => void;
11 | }
12 |
13 | const ThemeContext = createContext(undefined);
14 |
15 | export function ThemeProvider({ children }: { children: React.ReactNode }) {
16 | const [theme, setThemeState] = useState("light");
17 | const [mounted, setMounted] = useState(false);
18 |
19 | // Update theme
20 | const setTheme = (newTheme: Theme) => {
21 | setThemeState(newTheme);
22 | localStorage.setItem("theme", newTheme);
23 | document.documentElement.classList.toggle("dark", newTheme === "dark");
24 | };
25 |
26 | // Toggle theme
27 | const toggleTheme = () => {
28 | setTheme(theme === "light" ? "dark" : "light");
29 | console.log(theme);
30 | };
31 |
32 | // Initialize theme
33 | useEffect(() => {
34 | const savedTheme = localStorage.getItem("theme") as Theme | null;
35 | const systemTheme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
36 | const initialTheme = savedTheme || systemTheme;
37 |
38 | setThemeState(initialTheme);
39 | document.documentElement.classList.toggle("dark", initialTheme === "dark");
40 | setMounted(true);
41 | }, []);
42 |
43 | // Prevent flash of wrong theme
44 | if (!mounted) {
45 | return null;
46 | }
47 |
48 | return (
49 |
50 | {children}
51 |
52 | );
53 | }
54 |
55 | export function useTheme() {
56 | const context = useContext(ThemeContext);
57 | if (context === undefined) {
58 | throw new Error("useTheme must be used within a ThemeProvider");
59 | }
60 | return context;
61 | }
62 |
--------------------------------------------------------------------------------
/src/app/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mdalmamunit427/devfolio-nextjs-portfolio-website/5cfcf9e90e2caac0cebb56bfbea42a31347c243d/src/app/favicon.ico
--------------------------------------------------------------------------------
/src/app/globals.css:
--------------------------------------------------------------------------------
1 | @import "tailwindcss";
2 |
3 | @theme {
4 | --color-primary: #007AFF;
5 | --color-secondary: #6B7280;
6 | --color-dark: #1F2937;
7 | --color-light: #F9FAFB;
8 | --color-text: #000000;
9 | --color-bg: #ffffff;
10 |
11 | --font-sans: 'Inter', sans-serif;
12 |
13 | --animation-fade-in: fadeIn 0.5s ease-in-out;
14 | --animation-slide-up: slideUp 0.5s ease-in-out;
15 | }
16 |
17 |
18 | @custom-variant dark (&:where(.dark, .dark *));
19 |
20 | a {
21 | transition: all 0.2s ease;
22 | }
23 |
24 | @layer components {
25 | .container {
26 | @apply max-w-7xl mx-auto px-4 sm:px-6 lg:px-8;
27 | }
28 |
29 | .btn {
30 | @apply px-4 py-2 rounded-md font-medium transition-colors duration-200;
31 | }
32 |
33 | .btn-primary {
34 | @apply bg-primary text-white hover:bg-primary/90;
35 | }
36 |
37 | .btn-secondary {
38 | @apply bg-secondary text-white hover:bg-secondary/90;
39 | }
40 |
41 | .section-title {
42 | @apply text-3xl font-bold mb-8 text-center;
43 | }
44 | }
45 |
46 | @keyframes fadeIn {
47 | from {
48 | opacity: 0;
49 | }
50 | to {
51 | opacity: 1;
52 | }
53 | }
54 |
55 | @keyframes slideUp {
56 | from {
57 | transform: translateY(20px);
58 | opacity: 0;
59 | }
60 | to {
61 | transform: translateY(0);
62 | opacity: 1;
63 | }
64 | }
--------------------------------------------------------------------------------
/src/app/layout.tsx:
--------------------------------------------------------------------------------
1 | import type { Metadata } from "next";
2 | import { Geist, Geist_Mono } from "next/font/google";
3 | import "./globals.css";
4 | import { ThemeProvider } from "./context/ThemeContext";
5 | import Navbar from "./components/Navbar";
6 | import Footer from "./components/Footer";
7 |
8 | const geistSans = Geist({
9 | variable: "--font-geist-sans",
10 | subsets: ["latin"],
11 | });
12 |
13 | const geistMono = Geist_Mono({
14 | variable: "--font-geist-mono",
15 | subsets: ["latin"],
16 | });
17 |
18 | export const metadata: Metadata = {
19 | title: "Devfolio | Portfolio Website using Next.js, Tailwind CSS, and Framer Motion",
20 | description: "Devfolio is a portfolio website for developers to showcase their projects and skills.",
21 | };
22 |
23 | export default function RootLayout({
24 | children,
25 | }: Readonly<{
26 | children: React.ReactNode;
27 | }>) {
28 | return (
29 |
30 |
31 |
32 |
33 |
34 | {children}
35 |
36 |
37 |
38 |
39 |
40 | );
41 | }
42 |
--------------------------------------------------------------------------------
/src/app/page.tsx:
--------------------------------------------------------------------------------
1 | import Blogs from "./components/Blogs";
2 | import Hero from "./components/Hero";
3 | import Newsletter from "./components/Newsletter";
4 | import Projects from "./components/Projects";
5 |
6 |
7 | export default function Home() {
8 | return (
9 |
10 |
11 |
12 |
13 |
14 |
15 | );
16 | }
--------------------------------------------------------------------------------
/src/app/projects/page.tsx:
--------------------------------------------------------------------------------
1 | 'use client'
2 |
3 | import { projects } from '@/contents/projects'
4 | import Image from 'next/image'
5 | import { FaGithub, FaExternalLinkAlt } from 'react-icons/fa'
6 | import { motion } from 'framer-motion'
7 | import { fadeInUp, staggerContainer, cardHoverSmall } from '@/utils/animations'
8 |
9 | export default function Projects() {
10 | return (
11 |
12 |
18 | My Projects
19 |
20 |
26 | Here are some of my recent projects. Click on the links to view the code or live demo.
27 |
28 |
29 |
35 | {projects.map((project, index) => (
36 |
42 |
47 |
54 |
55 |
56 |
57 |
62 | {project.title}
63 |
64 |
70 | {project.description}
71 |
72 |
73 |
79 | {project.technologies.map((tech, techIndex) => (
80 |
86 | {tech}
87 |
88 | ))}
89 |
90 |
91 |
97 |
105 |
106 | Code
107 |
108 |
116 |
117 | Live Demo
118 |
119 |
120 |
121 |
122 | ))}
123 |
124 |
125 | )
126 | }
--------------------------------------------------------------------------------
/src/contents/blogs.ts:
--------------------------------------------------------------------------------
1 | import { Blog } from "@/types";
2 |
3 | export const blogs: Blog[] = [
4 | {
5 | title: 'Getting Started with Next.js 14',
6 | excerpt: 'Learn about the new features and improvements in Next.js 14.',
7 | date: '2024-03-15',
8 | readTime: '5 min read',
9 | slug: 'getting-started-with-nextjs-14',
10 | },
11 | {
12 | title: 'Mastering TypeScript for React',
13 | excerpt: 'A comprehensive guide to using TypeScript with React applications.',
14 | date: '2024-03-10',
15 | readTime: '8 min read',
16 | slug: 'mastering-typescript-for-react',
17 | },
18 | {
19 | title: 'Building Responsive Layouts with Tailwind CSS',
20 | excerpt: 'Tips and tricks for creating responsive designs using Tailwind CSS.',
21 | date: '2024-03-05',
22 | readTime: '6 min read',
23 | slug: 'building-responsive-layouts-with-tailwind-css',
24 | },
25 | {
26 | title: 'Understanding React Hooks',
27 | excerpt: 'A deep dive into React Hooks and how to use them effectively.',
28 | date: '2024-03-01',
29 | readTime: '7 min read',
30 | slug: 'understanding-react-hooks',
31 | },
32 | {
33 | title: 'Deploying Next.js Applications on Vercel',
34 | excerpt: 'Step-by-step guide to deploying your Next.js applications on Vercel.',
35 | date: '2024-02-25',
36 | readTime: '4 min read',
37 | slug: 'deploying-nextjs-applications-on-vercel',
38 | },
39 | {
40 | title: 'Building a RESTful API with Node.js and Express',
41 | excerpt: 'Learn how to create a RESTful API using Node.js and Express.',
42 | date: '2024-02-20',
43 | readTime: '10 min read',
44 | slug: 'building-a-restful-api-with-nodejs-and-express',
45 | },
46 | ];
--------------------------------------------------------------------------------
/src/contents/projects.ts:
--------------------------------------------------------------------------------
1 | import { Project } from "@/types";
2 |
3 |
4 | export const projects: Project[] = [
5 | {
6 | title: 'E-commerce Platform',
7 | description: 'A full-stack e-commerce platform built with Next.js, TypeScript, and Tailwind CSS.',
8 | technologies: ['Next.js', 'TypeScript', 'Tailwind CSS', 'Stripe'],
9 | githubLink: 'https://github.com',
10 | demoLink: 'https://demo.com',
11 | image: '/projects/e-commerce-website.png',
12 | },
13 | {
14 | title: 'Task Management App',
15 | description: 'A collaborative task management application with real-time updates.',
16 | technologies: ['React', 'Node.js', 'MongoDB', 'Socket.io'],
17 | githubLink: 'https://github.com',
18 | demoLink: 'https://demo.com',
19 | image: '/projects/task-manager.webp',
20 | },
21 | {
22 | title: 'Portfolio Website',
23 | description: 'My personal portfolio website showcasing my projects and skills.',
24 | technologies: ['Next.js', 'Tailwind CSS', 'Framer Motion'],
25 | githubLink: 'https://github.com',
26 | demoLink: 'https://demo.com',
27 | image: '/projects/portfolio-website.jpg',
28 | },
29 | {
30 | title: 'Blog Platform',
31 | description: 'A blogging platform with user authentication and markdown support.',
32 | technologies: ['Gatsby', 'GraphQL', 'Contentful'],
33 | githubLink: 'https://github.com',
34 | demoLink: 'https://demo.com',
35 | image: '/projects/blog-website.jpeg',
36 | },
37 | {
38 | title: 'Weather App',
39 | description: 'A weather application that provides real-time weather updates.',
40 | technologies: ['React', 'OpenWeatherMap API'],
41 | githubLink: 'https://github.com',
42 | demoLink: 'https://demo.com',
43 | image: '/projects/weather-app.png',
44 | },
45 | {
46 | title: 'Chat Application',
47 | description: 'A real-time chat application using WebSocket technology.',
48 | technologies: ['React', 'Node.js', 'Socket.io'],
49 | githubLink: 'https://github.com',
50 | demoLink: 'https://demo.com',
51 | image: '/projects/chat-app.png',
52 | },
53 | {
54 | title: 'Recipe Finder',
55 | description: 'A recipe search application using the Edamam API.',
56 | technologies: ['React', 'Edamam API'],
57 | githubLink: 'https://github.com',
58 | demoLink: 'https://demo.com',
59 | image: '/projects/recipe-finder.png',
60 | },
61 | {
62 | title: 'Expense Tracker',
63 | description: 'A personal finance tracker to manage expenses and income.',
64 | technologies: ['React', 'Firebase'],
65 | githubLink: 'https://github.com',
66 | demoLink: 'https://demo.com',
67 | image: '/projects/expense-tracker.webp',
68 | }
69 | ];
--------------------------------------------------------------------------------
/src/types/index.ts:
--------------------------------------------------------------------------------
1 | export interface Project {
2 | title: string;
3 | description: string;
4 | technologies: string[];
5 | githubLink: string;
6 | demoLink: string;
7 | image: string;
8 | }
9 |
10 | export interface Blog {
11 | title: string;
12 | excerpt: string;
13 | date: string;
14 | readTime: string;
15 | slug: string;
16 | }
17 |
--------------------------------------------------------------------------------
/src/utils/animations.ts:
--------------------------------------------------------------------------------
1 | export const fadeInUp = {
2 | initial: { opacity: 0, y: 20 },
3 | animate: { opacity: 1, y: 0 },
4 | transition: { duration: 0.5 }
5 | }
6 |
7 | export const fadeInDown = {
8 | initial: { opacity: 0, y: -20 },
9 | animate: { opacity: 1, y: 0 },
10 | transition: { duration: 0.5 }
11 | }
12 |
13 | export const fadeIn = {
14 | initial: { opacity: 0 },
15 | animate: { opacity: 1 },
16 | transition: { duration: 0.5 }
17 | }
18 |
19 | export const staggerContainer = {
20 | animate: {
21 | transition: {
22 | staggerChildren: 0.1
23 | }
24 | }
25 | }
26 |
27 | export const cardHover = {
28 | whileHover: { scale: 1.05 },
29 | transition: { type: "spring", stiffness: 300 }
30 | }
31 |
32 | export const cardHoverSmall = {
33 | whileHover: { scale: 1.02 },
34 | transition: { type: "spring", stiffness: 300 }
35 | }
36 |
37 | export const pageTransition = {
38 | initial: { opacity: 0 },
39 | animate: { opacity: 1 },
40 | exit: { opacity: 0 },
41 | transition: { duration: 0.5 }
42 | }
43 |
44 | export const slideInLeft = {
45 | initial: { x: -60, opacity: 0 },
46 | animate: { x: 0, opacity: 1 },
47 | transition: { duration: 0.5 }
48 | }
49 |
50 | export const slideInRight = {
51 | initial: { x: 60, opacity: 0 },
52 | animate: { x: 0, opacity: 1 },
53 | transition: { duration: 0.5 }
54 | }
55 |
56 | export const scaleIn = {
57 | initial: { scale: 0.8, opacity: 0 },
58 | animate: { scale: 1, opacity: 1 },
59 | transition: { duration: 0.5 }
60 | }
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES2017",
4 | "lib": ["dom", "dom.iterable", "esnext"],
5 | "allowJs": true,
6 | "skipLibCheck": true,
7 | "strict": true,
8 | "noEmit": true,
9 | "esModuleInterop": true,
10 | "module": "esnext",
11 | "moduleResolution": "bundler",
12 | "resolveJsonModule": true,
13 | "isolatedModules": true,
14 | "jsx": "preserve",
15 | "incremental": true,
16 | "plugins": [
17 | {
18 | "name": "next"
19 | }
20 | ],
21 | "paths": {
22 | "@/*": ["./src/*"]
23 | }
24 | },
25 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
26 | "exclude": ["node_modules"]
27 | }
28 |
--------------------------------------------------------------------------------