Replace FastAPI with React portfolio
Browse files- .gitignore +21 -0
- Dockerfile +24 -0
- README.md +168 -1
- netlify.toml +11 -0
- package.json +49 -0
- postcss.config.js +6 -0
- public/index.html +23 -0
- src/App.css +62 -0
- src/App.js +39 -0
- src/components/BlogCard.js +0 -0
- src/components/EducationCard.js +23 -0
- src/components/ExperienceCard.js +20 -0
- src/components/Footer.js +36 -0
- src/components/Header.js +51 -0
- src/components/Navigation.js +36 -0
- src/components/ProjectCard.js +20 -0
- src/components/PublicationCard.js +28 -0
- src/components/Section.js +26 -0
- src/components/SkillTag.js +11 -0
- src/data/about.js +30 -0
- src/data/blogs.js +77 -0
- src/data/education.js +33 -0
- src/data/experience.js +44 -0
- src/data/projects.js +34 -0
- src/data/publications.js +60 -0
- src/data/skills.js +8 -0
- src/index.css +44 -0
- src/index.js +14 -0
- src/pages/Blog.js +35 -0
- src/pages/Home.js +92 -0
- src/pages/Projects.js +42 -0
- src/pages/Publications.js +60 -0
- src/pages/Resume.js +155 -0
- tailwind.config.js +55 -0
.gitignore
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# dependencies
|
2 |
+
/node_modules
|
3 |
+
/.pnp
|
4 |
+
.pnp.js
|
5 |
+
|
6 |
+
# testing
|
7 |
+
/coverage
|
8 |
+
|
9 |
+
# production
|
10 |
+
/build
|
11 |
+
|
12 |
+
# misc
|
13 |
+
.DS_Store
|
14 |
+
.env.local
|
15 |
+
.env.development.local
|
16 |
+
.env.test.local
|
17 |
+
.env.production.local
|
18 |
+
|
19 |
+
npm-debug.log*
|
20 |
+
yarn-debug.log*
|
21 |
+
yarn-error.log*
|
Dockerfile
ADDED
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
FROM node:18
|
2 |
+
|
3 |
+
WORKDIR /app
|
4 |
+
|
5 |
+
# Copy package.json and package-lock.json
|
6 |
+
COPY package*.json ./
|
7 |
+
|
8 |
+
# Install dependencies
|
9 |
+
RUN npm install
|
10 |
+
|
11 |
+
# Copy the rest of the code
|
12 |
+
COPY . .
|
13 |
+
|
14 |
+
# Build the React app
|
15 |
+
RUN npm run build
|
16 |
+
|
17 |
+
# Install a simple server to serve the static files
|
18 |
+
RUN npm install -g serve
|
19 |
+
|
20 |
+
# Expose the port
|
21 |
+
EXPOSE 7860
|
22 |
+
|
23 |
+
# Start the server
|
24 |
+
CMD ["serve", "-s", "build", "-l", "7860"]
|
README.md
CHANGED
@@ -7,4 +7,171 @@ sdk: docker
|
|
7 |
pinned: false
|
8 |
---
|
9 |
|
10 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
7 |
pinned: false
|
8 |
---
|
9 |
|
10 |
+
# Nawaf Portfolio Website
|
11 |
+
|
12 |
+
A modern, responsive personal website built with React for academic and professional portfolios.
|
13 |
+
|
14 |
+
## Features
|
15 |
+
|
16 |
+
- 📱 Fully responsive design
|
17 |
+
- 📝 Markdown support for blog posts and publications
|
18 |
+
- 🎨 Modern UI with customizable theme
|
19 |
+
- 📊 Sections for publications, projects, experience, and education
|
20 |
+
- 🔍 SEO optimized
|
21 |
+
- 💻 Easy to deploy on Hugging Face Spaces
|
22 |
+
|
23 |
+
## Repository Structure
|
24 |
+
|
25 |
+
```
|
26 |
+
nawaf-portfolio/
|
27 |
+
├── .gitignore
|
28 |
+
├── README.md
|
29 |
+
├── app.py # Gradio server for HF Spaces
|
30 |
+
├── package.json # Project dependencies
|
31 |
+
├── requirements.txt # Python dependencies for Gradio
|
32 |
+
├── public/
|
33 |
+
│ ├── favicon.ico
|
34 |
+
│ ├── index.html
|
35 |
+
│ ├── manifest.json
|
36 |
+
│ └── assets/
|
37 |
+
│ └── img/
|
38 |
+
│ ├── profile.jpg
|
39 |
+
│ └── ...
|
40 |
+
└── src/
|
41 |
+
├── index.js # Entry point
|
42 |
+
├── App.js # Main App component
|
43 |
+
├── theme.js # Theme configuration
|
44 |
+
├── data/ # All content in JSON format
|
45 |
+
│ ├── about.js
|
46 |
+
│ ├── education.js
|
47 |
+
│ ├── experience.js
|
48 |
+
│ ├── projects.js
|
49 |
+
│ ├── publications.js
|
50 |
+
│ ├── skills.js
|
51 |
+
│ └── blogs.js
|
52 |
+
├── components/ # Reusable components
|
53 |
+
│ ├── Header.js
|
54 |
+
│ ├── Footer.js
|
55 |
+
│ ├── Navigation.js
|
56 |
+
│ ├── EducationCard.js
|
57 |
+
│ ├── ExperienceCard.js
|
58 |
+
│ ├── ProjectCard.js
|
59 |
+
│ ├── PublicationCard.js
|
60 |
+
│ ├── BlogCard.js
|
61 |
+
│ ├── Section.js
|
62 |
+
│ └── SkillTag.js
|
63 |
+
└── pages/ # Page components
|
64 |
+
├── Home.js
|
65 |
+
├── Publications.js
|
66 |
+
├── Projects.js
|
67 |
+
├── Blog.js
|
68 |
+
└── Resume.js
|
69 |
+
```
|
70 |
+
|
71 |
+
## Installation
|
72 |
+
|
73 |
+
1. Clone this repository:
|
74 |
+
```bash
|
75 |
+
git clone https://github.com/yourusername/nawaf-portfolio.git
|
76 |
+
cd nawaf-portfolio
|
77 |
+
```
|
78 |
+
|
79 |
+
2. Install dependencies:
|
80 |
+
```bash
|
81 |
+
npm install
|
82 |
+
```
|
83 |
+
|
84 |
+
3. Start the development server:
|
85 |
+
```bash
|
86 |
+
npm start
|
87 |
+
```
|
88 |
+
|
89 |
+
## Deployment on Hugging Face Spaces
|
90 |
+
|
91 |
+
### Option 1: Using the Gradio Interface (Recommended)
|
92 |
+
|
93 |
+
1. Create a new Space on Hugging Face:
|
94 |
+
- Go to [Hugging Face Spaces](https://huggingface.co/spaces)
|
95 |
+
- Click "Create new Space"
|
96 |
+
- Choose a name (e.g., "nawaf-portfolio")
|
97 |
+
- Select "Gradio" as the SDK
|
98 |
+
- Choose "Public" visibility
|
99 |
+
- Click "Create Space"
|
100 |
+
|
101 |
+
2. Push your code to the Space's repository:
|
102 |
+
```bash
|
103 |
+
git remote add space https://huggingface.co/spaces/yourusername/nawaf-portfolio
|
104 |
+
git push space main
|
105 |
+
```
|
106 |
+
|
107 |
+
3. The Space will automatically build and deploy your application.
|
108 |
+
|
109 |
+
### Option 2: Using Static React Build
|
110 |
+
|
111 |
+
1. Build your React application:
|
112 |
+
```bash
|
113 |
+
npm run build
|
114 |
+
```
|
115 |
+
|
116 |
+
2. Create a new Space on Hugging Face with "Static" as the SDK.
|
117 |
+
|
118 |
+
3. Push your build folder to the Space's repository.
|
119 |
+
|
120 |
+
## Customization
|
121 |
+
|
122 |
+
### Content
|
123 |
+
|
124 |
+
All content is stored in the `src/data` directory. Edit these files to update your personal information:
|
125 |
+
|
126 |
+
- `about.js` - Bio, contact info, and social links
|
127 |
+
- `education.js` - Academic history
|
128 |
+
- `experience.js` - Work experience
|
129 |
+
- `projects.js` - Research projects
|
130 |
+
- `publications.js` - Academic publications
|
131 |
+
- `skills.js` - Technical skills
|
132 |
+
- `blogs.js` - Blog posts in markdown format
|
133 |
+
|
134 |
+
### Theme
|
135 |
+
|
136 |
+
Edit `src/theme.js` to customize colors, fonts, and other styling variables.
|
137 |
+
|
138 |
+
### Adding Blog Posts
|
139 |
+
|
140 |
+
To add a new blog post:
|
141 |
+
|
142 |
+
1. Create a new entry in `src/data/blogs.js`:
|
143 |
+
```javascript
|
144 |
+
{
|
145 |
+
id: "unique-id",
|
146 |
+
title: "Your Blog Title",
|
147 |
+
date: "March 9, 2025",
|
148 |
+
excerpt: "Short description of your blog post",
|
149 |
+
content: `
|
150 |
+
# Your Blog Title
|
151 |
+
|
152 |
+
This is the content of your blog post in Markdown format.
|
153 |
+
|
154 |
+
## Subheading
|
155 |
+
|
156 |
+
More content here...
|
157 |
+
`
|
158 |
+
}
|
159 |
+
```
|
160 |
+
|
161 |
+
### Adding Publications
|
162 |
+
|
163 |
+
Add new publications to `src/data/publications.js`:
|
164 |
+
```javascript
|
165 |
+
{
|
166 |
+
id: "unique-id",
|
167 |
+
title: "Publication Title",
|
168 |
+
authors: "Author 1, Author 2, et al.",
|
169 |
+
venue: "Journal or Conference Name",
|
170 |
+
year: "2025",
|
171 |
+
link: "https://doi.org/..."
|
172 |
+
}
|
173 |
+
```
|
174 |
+
|
175 |
+
## License
|
176 |
+
|
177 |
+
MIT
|
netlify.toml
ADDED
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
[build]
|
2 |
+
command = "npm run build"
|
3 |
+
publish = "build"
|
4 |
+
|
5 |
+
[build.environment]
|
6 |
+
NODE_VERSION = "18"
|
7 |
+
|
8 |
+
[[redirects]]
|
9 |
+
from = "/*"
|
10 |
+
to = "/index.html"
|
11 |
+
status = 200
|
package.json
ADDED
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"name": "nawaf-portfolio",
|
3 |
+
"version": "0.1.0",
|
4 |
+
"private": true,
|
5 |
+
"dependencies": {
|
6 |
+
"@tailwindcss/typography": "^0.5.10",
|
7 |
+
"@testing-library/jest-dom": "^5.16.5",
|
8 |
+
"@testing-library/react": "^13.4.0",
|
9 |
+
"@testing-library/user-event": "^13.5.0",
|
10 |
+
"react": "^18.2.0",
|
11 |
+
"react-dom": "^18.2.0",
|
12 |
+
"react-icons": "^4.8.0",
|
13 |
+
"react-markdown": "^8.0.7",
|
14 |
+
"react-router-dom": "^6.11.1",
|
15 |
+
"react-scripts": "^5.0.1",
|
16 |
+
"react-syntax-highlighter": "^15.5.0",
|
17 |
+
"remark-gfm": "^3.0.1",
|
18 |
+
"tailwindcss": "^3.3.2",
|
19 |
+
"web-vitals": "^2.1.4"
|
20 |
+
},
|
21 |
+
"scripts": {
|
22 |
+
"start": "react-scripts start",
|
23 |
+
"build": "react-scripts build",
|
24 |
+
"test": "react-scripts test",
|
25 |
+
"eject": "react-scripts eject"
|
26 |
+
},
|
27 |
+
"eslintConfig": {
|
28 |
+
"extends": [
|
29 |
+
"react-app",
|
30 |
+
"react-app/jest"
|
31 |
+
]
|
32 |
+
},
|
33 |
+
"browserslist": {
|
34 |
+
"production": [
|
35 |
+
">0.2%",
|
36 |
+
"not dead",
|
37 |
+
"not op_mini all"
|
38 |
+
],
|
39 |
+
"development": [
|
40 |
+
"last 1 chrome version",
|
41 |
+
"last 1 firefox version",
|
42 |
+
"last 1 safari version"
|
43 |
+
]
|
44 |
+
},
|
45 |
+
"devDependencies": {
|
46 |
+
"autoprefixer": "^10.4.14",
|
47 |
+
"postcss": "^8.4.23"
|
48 |
+
}
|
49 |
+
}
|
postcss.config.js
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
module.exports = {
|
2 |
+
plugins: {
|
3 |
+
tailwindcss: {},
|
4 |
+
autoprefixer: {},
|
5 |
+
},
|
6 |
+
};
|
public/index.html
ADDED
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html lang="en">
|
3 |
+
<head>
|
4 |
+
<meta charset="utf-8" />
|
5 |
+
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
|
6 |
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
7 |
+
<meta name="theme-color" content="#4a148c" />
|
8 |
+
<meta
|
9 |
+
name="description"
|
10 |
+
content="Nawaf Alampara - Doctoral Researcher in Machine Learning"
|
11 |
+
/>
|
12 |
+
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
|
13 |
+
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
14 |
+
<title>Nawaf Alampara | ML Researcher</title>
|
15 |
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
16 |
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
17 |
+
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
|
18 |
+
</head>
|
19 |
+
<body>
|
20 |
+
<noscript>You need to enable JavaScript to run this app.</noscript>
|
21 |
+
<div id="root"></div>
|
22 |
+
</body>
|
23 |
+
</html>
|
src/App.css
ADDED
@@ -0,0 +1,62 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/* App-wide styles */
|
2 |
+
.app {
|
3 |
+
min-height: 100vh;
|
4 |
+
display: flex;
|
5 |
+
flex-direction: column;
|
6 |
+
}
|
7 |
+
|
8 |
+
main {
|
9 |
+
flex-grow: 1;
|
10 |
+
}
|
11 |
+
|
12 |
+
/* Dark mode styles */
|
13 |
+
.app.dark {
|
14 |
+
background-color: var(--dark);
|
15 |
+
color: var(--text);
|
16 |
+
}
|
17 |
+
|
18 |
+
.app.dark .bg-white {
|
19 |
+
background-color: var(--dark);
|
20 |
+
}
|
21 |
+
|
22 |
+
.app.dark nav {
|
23 |
+
background-color: var(--dark);
|
24 |
+
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
25 |
+
}
|
26 |
+
|
27 |
+
.app.dark .text-gray-600 {
|
28 |
+
color: rgba(255, 255, 255, 0.75);
|
29 |
+
}
|
30 |
+
|
31 |
+
.app.dark .text-gray-700 {
|
32 |
+
color: rgba(255, 255, 255, 0.9);
|
33 |
+
}
|
34 |
+
|
35 |
+
.app.dark .shadow {
|
36 |
+
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.5), 0 1px 2px 0 rgba(0, 0, 0, 0.6);
|
37 |
+
}
|
38 |
+
|
39 |
+
.app.dark .border-gray-200 {
|
40 |
+
border-color: rgba(255, 255, 255, 0.1);
|
41 |
+
}
|
42 |
+
|
43 |
+
/* Transitions */
|
44 |
+
.transition-colors {
|
45 |
+
transition-property: color, background-color, border-color;
|
46 |
+
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
47 |
+
transition-duration: 150ms;
|
48 |
+
}
|
49 |
+
|
50 |
+
.transition-all {
|
51 |
+
transition-property: all;
|
52 |
+
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
53 |
+
transition-duration: 150ms;
|
54 |
+
}
|
55 |
+
|
56 |
+
/* Fix for mobile responsiveness */
|
57 |
+
@media (max-width: 640px) {
|
58 |
+
.container {
|
59 |
+
padding-left: 1rem;
|
60 |
+
padding-right: 1rem;
|
61 |
+
}
|
62 |
+
}
|
src/App.js
ADDED
@@ -0,0 +1,39 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import React, { useState } from 'react';
|
2 |
+
import { Routes, Route, useLocation } from 'react-router-dom';
|
3 |
+
import Header from './components/Header';
|
4 |
+
import Navigation from './components/Navigation';
|
5 |
+
import Footer from './components/Footer';
|
6 |
+
import Home from './pages/Home';
|
7 |
+
import Publications from './pages/Publications';
|
8 |
+
import Projects from './pages/Projects';
|
9 |
+
import Blog from './pages/Blog';
|
10 |
+
import Resume from './pages/Resume';
|
11 |
+
import './App.css';
|
12 |
+
|
13 |
+
function App() {
|
14 |
+
const location = useLocation();
|
15 |
+
const [theme, setTheme] = useState('light');
|
16 |
+
|
17 |
+
const toggleTheme = () => {
|
18 |
+
setTheme(theme === 'light' ? 'dark' : 'light');
|
19 |
+
};
|
20 |
+
|
21 |
+
return (
|
22 |
+
<div className={`app ${theme}`}>
|
23 |
+
<Header toggleTheme={toggleTheme} theme={theme} />
|
24 |
+
<Navigation currentPath={location.pathname} />
|
25 |
+
<main className="container mx-auto px-4 py-8">
|
26 |
+
<Routes>
|
27 |
+
<Route path="/" element={<Home />} />
|
28 |
+
<Route path="/publications" element={<Publications />} />
|
29 |
+
<Route path="/projects" element={<Projects />} />
|
30 |
+
{/* <Route path="/blog" element={<Blog />} /> */}
|
31 |
+
<Route path="/resume" element={<Resume />} />
|
32 |
+
</Routes>
|
33 |
+
</main>
|
34 |
+
<Footer />
|
35 |
+
</div>
|
36 |
+
);
|
37 |
+
}
|
38 |
+
|
39 |
+
export default App;
|
src/components/BlogCard.js
ADDED
File without changes
|
src/components/EducationCard.js
ADDED
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import React from 'react';
|
2 |
+
|
3 |
+
const EducationCard = ({ education }) => {
|
4 |
+
return (
|
5 |
+
<div className="bg-white rounded-lg shadow p-6 transition-all hover:shadow-lg">
|
6 |
+
<div className="flex justify-between flex-wrap">
|
7 |
+
<h3 className="font-bold text-lg">{education.degree}</h3>
|
8 |
+
<span className="text-gray-600">{education.period}</span>
|
9 |
+
</div>
|
10 |
+
<p className="text-primary font-medium">{education.institution}</p>
|
11 |
+
{education.gpa && <p className="text-gray-600 mt-1">GPA: {education.gpa}</p>}
|
12 |
+
{education.description.length > 0 && (
|
13 |
+
<ul className="mt-2 list-disc list-inside text-gray-700">
|
14 |
+
{education.description.map((item, idx) => (
|
15 |
+
<li key={idx}>{item}</li>
|
16 |
+
))}
|
17 |
+
</ul>
|
18 |
+
)}
|
19 |
+
</div>
|
20 |
+
);
|
21 |
+
};
|
22 |
+
|
23 |
+
export default EducationCard;
|
src/components/ExperienceCard.js
ADDED
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import React from 'react';
|
2 |
+
|
3 |
+
const ExperienceCard = ({ experience }) => {
|
4 |
+
return (
|
5 |
+
<div className="bg-white rounded-lg shadow p-6 transition-all hover:shadow-lg">
|
6 |
+
<div className="flex justify-between flex-wrap">
|
7 |
+
<h3 className="font-bold text-lg">{experience.position}</h3>
|
8 |
+
<span className="text-gray-600">{experience.period}</span>
|
9 |
+
</div>
|
10 |
+
<p className="text-primary font-medium">{experience.company}</p>
|
11 |
+
<ul className="mt-2 list-disc list-inside text-gray-700">
|
12 |
+
{experience.description.map((item, idx) => (
|
13 |
+
<li key={idx}>{item}</li>
|
14 |
+
))}
|
15 |
+
</ul>
|
16 |
+
</div>
|
17 |
+
);
|
18 |
+
};
|
19 |
+
|
20 |
+
export default ExperienceCard;
|
src/components/Footer.js
ADDED
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import React from 'react';
|
2 |
+
import { Link } from 'react-router-dom';
|
3 |
+
|
4 |
+
const Navigation = ({ currentPath }) => {
|
5 |
+
const navItems = [
|
6 |
+
{ path: '/', label: 'Home' },
|
7 |
+
{ path: '/publications', label: 'Publications' },
|
8 |
+
{ path: '/projects', label: 'Projects' },
|
9 |
+
{ path: '/blog', label: 'Blog' },
|
10 |
+
{ path: '/resume', label: 'Resume' }
|
11 |
+
];
|
12 |
+
|
13 |
+
return (
|
14 |
+
<nav className="bg-white shadow-md sticky top-0 z-10">
|
15 |
+
<div className="container mx-auto px-4">
|
16 |
+
<div className="flex overflow-x-auto py-2 space-x-6">
|
17 |
+
{navItems.map((item) => (
|
18 |
+
<Link
|
19 |
+
key={item.path}
|
20 |
+
to={item.path}
|
21 |
+
className={`px-3 py-2 font-medium whitespace-nowrap ${
|
22 |
+
currentPath === item.path
|
23 |
+
? 'text-primary border-b-2 border-primary'
|
24 |
+
: 'text-gray-600 hover:text-primary'
|
25 |
+
}`}
|
26 |
+
>
|
27 |
+
{item.label}
|
28 |
+
</Link>
|
29 |
+
))}
|
30 |
+
</div>
|
31 |
+
</div>
|
32 |
+
</nav>
|
33 |
+
);
|
34 |
+
};
|
35 |
+
|
36 |
+
export default Navigation;
|
src/components/Header.js
ADDED
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import React from 'react';
|
2 |
+
import { FaEnvelope, FaMapMarkerAlt, FaGithub, FaLinkedinIn, FaMoon, FaSun } from 'react-icons/fa';
|
3 |
+
import about from '../data/about';
|
4 |
+
|
5 |
+
const Header = ({ toggleTheme, theme }) => {
|
6 |
+
return (
|
7 |
+
<header className="bg-primary text-white">
|
8 |
+
<div className="container mx-auto px-4 py-16">
|
9 |
+
<div className="flex flex-col md:flex-row items-start md:items-center justify-between">
|
10 |
+
<div>
|
11 |
+
<h1 className="text-4xl font-bold">{about.name}</h1>
|
12 |
+
<p className="mt-2 text-xl">{about.title}</p>
|
13 |
+
</div>
|
14 |
+
<div className="flex flex-col gap-2 mt-4 md:mt-0">
|
15 |
+
<div className="flex items-center">
|
16 |
+
<FaEnvelope className="mr-2" />
|
17 |
+
<a href={`mailto:${about.email}`} className="hover:underline">
|
18 |
+
{about.email}
|
19 |
+
</a>
|
20 |
+
</div>
|
21 |
+
<div className="flex items-center">
|
22 |
+
<FaMapMarkerAlt className="mr-2" />
|
23 |
+
<span>{about.location}</span>
|
24 |
+
</div>
|
25 |
+
<div className="flex items-center">
|
26 |
+
<FaGithub className="mr-2" />
|
27 |
+
<a href={`https://github.com/${about.github}`} target="_blank" rel="noopener noreferrer" className="hover:underline">
|
28 |
+
{about.github}
|
29 |
+
</a>
|
30 |
+
</div>
|
31 |
+
<div className="flex items-center">
|
32 |
+
<FaLinkedinIn className="mr-2" />
|
33 |
+
<a href={`https://www.linkedin.com/in/${about.linkedin}`} target="_blank" rel="noopener noreferrer" className="hover:underline">
|
34 |
+
{about.linkedin}
|
35 |
+
</a>
|
36 |
+
</div>
|
37 |
+
</div>
|
38 |
+
<button
|
39 |
+
onClick={toggleTheme}
|
40 |
+
className="fixed top-4 right-4 z-50 p-2 bg-secondary text-white rounded-full"
|
41 |
+
aria-label="Toggle theme"
|
42 |
+
>
|
43 |
+
{theme === 'light' ? <FaMoon /> : <FaSun />}
|
44 |
+
</button>
|
45 |
+
</div>
|
46 |
+
</div>
|
47 |
+
</header>
|
48 |
+
);
|
49 |
+
};
|
50 |
+
|
51 |
+
export default Header;
|
src/components/Navigation.js
ADDED
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import React from 'react';
|
2 |
+
import { Link } from 'react-router-dom';
|
3 |
+
|
4 |
+
const Navigation = ({ currentPath }) => {
|
5 |
+
const navItems = [
|
6 |
+
{ path: '/', label: 'Home' },
|
7 |
+
{ path: '/publications', label: 'Publications' },
|
8 |
+
{ path: '/projects', label: 'Projects' },
|
9 |
+
{ path: '/blog', label: 'Blog' },
|
10 |
+
{ path: '/resume', label: 'Resume' }
|
11 |
+
];
|
12 |
+
|
13 |
+
return (
|
14 |
+
<nav className="bg-white shadow-md sticky top-0 z-10">
|
15 |
+
<div className="container mx-auto px-4">
|
16 |
+
<div className="flex overflow-x-auto py-2 space-x-6">
|
17 |
+
{navItems.map((item) => (
|
18 |
+
<Link
|
19 |
+
key={item.path}
|
20 |
+
to={item.path}
|
21 |
+
className={`px-3 py-2 font-medium whitespace-nowrap ${
|
22 |
+
currentPath === item.path
|
23 |
+
? 'text-primary border-b-2 border-primary'
|
24 |
+
: 'text-gray-600 hover:text-primary'
|
25 |
+
}`}
|
26 |
+
>
|
27 |
+
{item.label}
|
28 |
+
</Link>
|
29 |
+
))}
|
30 |
+
</div>
|
31 |
+
</div>
|
32 |
+
</nav>
|
33 |
+
);
|
34 |
+
};
|
35 |
+
|
36 |
+
export default Navigation;
|
src/components/ProjectCard.js
ADDED
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import React from 'react';
|
2 |
+
|
3 |
+
const ProjectCard = ({ project }) => {
|
4 |
+
return (
|
5 |
+
<div className="bg-white rounded-lg shadow p-6 transition-all hover:shadow-lg">
|
6 |
+
<div className="flex justify-between flex-wrap">
|
7 |
+
<h3 className="font-bold text-lg">{project.title}</h3>
|
8 |
+
<span className="text-gray-600">{project.period}</span>
|
9 |
+
</div>
|
10 |
+
<p className="text-primary font-medium">{project.organization}</p>
|
11 |
+
<ul className="mt-2 list-disc list-inside text-gray-700">
|
12 |
+
{project.description.map((item, idx) => (
|
13 |
+
<li key={idx}>{item}</li>
|
14 |
+
))}
|
15 |
+
</ul>
|
16 |
+
</div>
|
17 |
+
);
|
18 |
+
};
|
19 |
+
|
20 |
+
export default ProjectCard;
|
src/components/PublicationCard.js
ADDED
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import React from 'react';
|
2 |
+
|
3 |
+
const PublicationCard = ({ publication }) => {
|
4 |
+
return (
|
5 |
+
<div className="bg-white rounded-lg shadow p-6 transition-all hover:shadow-lg">
|
6 |
+
<h3 className="font-bold text-lg">{publication.title}</h3>
|
7 |
+
<p className="text-gray-700 italic mt-1">{publication.authors}</p>
|
8 |
+
<div className="flex justify-between items-center mt-2">
|
9 |
+
<p className="text-primary font-medium">{publication.venue}</p>
|
10 |
+
<span className="text-gray-600">{publication.year}</span>
|
11 |
+
</div>
|
12 |
+
{publication.link && (
|
13 |
+
<div className="mt-3">
|
14 |
+
<a
|
15 |
+
href={publication.link}
|
16 |
+
target="_blank"
|
17 |
+
rel="noopener noreferrer"
|
18 |
+
className="text-primary hover:underline"
|
19 |
+
>
|
20 |
+
View Publication
|
21 |
+
</a>
|
22 |
+
</div>
|
23 |
+
)}
|
24 |
+
</div>
|
25 |
+
);
|
26 |
+
};
|
27 |
+
|
28 |
+
export default PublicationCard;
|
src/components/Section.js
ADDED
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import React, { useState } from 'react';
|
2 |
+
import { FaChevronDown, FaChevronUp } from 'react-icons/fa';
|
3 |
+
|
4 |
+
const Section = ({ title, icon, children, defaultExpanded = true }) => {
|
5 |
+
const [isExpanded, setIsExpanded] = useState(defaultExpanded);
|
6 |
+
|
7 |
+
return (
|
8 |
+
<div className="mb-8">
|
9 |
+
<div
|
10 |
+
className="flex items-center justify-between cursor-pointer mb-4"
|
11 |
+
onClick={() => setIsExpanded(!isExpanded)}
|
12 |
+
>
|
13 |
+
<h2 className="text-2xl font-bold flex items-center">
|
14 |
+
{icon}
|
15 |
+
<span className="ml-2">{title}</span>
|
16 |
+
</h2>
|
17 |
+
<div className="text-gray-500">
|
18 |
+
{isExpanded ? <FaChevronUp /> : <FaChevronDown />}
|
19 |
+
</div>
|
20 |
+
</div>
|
21 |
+
{isExpanded && children}
|
22 |
+
</div>
|
23 |
+
);
|
24 |
+
};
|
25 |
+
|
26 |
+
export default Section;
|
src/components/SkillTag.js
ADDED
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import React from 'react';
|
2 |
+
|
3 |
+
const SkillTag = ({ skill }) => {
|
4 |
+
return (
|
5 |
+
<span className="px-3 py-1 bg-light text-primary rounded-full text-sm">
|
6 |
+
{skill}
|
7 |
+
</span>
|
8 |
+
);
|
9 |
+
};
|
10 |
+
|
11 |
+
export default SkillTag;
|
src/data/about.js
ADDED
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
const about = {
|
2 |
+
name: "Nawaf Alampara",
|
3 |
+
title: "Doctoral Researcher in Machine Learning",
|
4 |
+
email: "[email protected]",
|
5 |
+
location: "Jena, Germany",
|
6 |
+
github: "n0w0f",
|
7 |
+
linkedin: "nawaf-a-78731612b",
|
8 |
+
bio: `I am a second-year PhD student at Friedrich-Schiller-Universität Jena, advised by Dr. Kevin Maik Jablonka.
|
9 |
+
I work on developing machine learning methods to accelerate scientific discovery.
|
10 |
+
I enjoy tackling projects that combine novel research ideas with practical engineering implementation.`,
|
11 |
+
researchInterests: [
|
12 |
+
"Evaluation and development of foundation models for science",
|
13 |
+
"Agent workflows for scientific discovery",
|
14 |
+
"Task Adaptibility",
|
15 |
+
"Computational material science",
|
16 |
+
"Scientific software development"
|
17 |
+
],
|
18 |
+
awards: [
|
19 |
+
{
|
20 |
+
title: "Inspire Fellowship",
|
21 |
+
organization: "Department of Science and Technology, Government of India"
|
22 |
+
},
|
23 |
+
{
|
24 |
+
title: "Summer Research Fellowship",
|
25 |
+
organization: "Indian Academy of Sciences (SRF 2016)"
|
26 |
+
}
|
27 |
+
]
|
28 |
+
};
|
29 |
+
|
30 |
+
export default about;
|
src/data/blogs.js
ADDED
@@ -0,0 +1,77 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
const blogs = [
|
2 |
+
{
|
3 |
+
id: "llm-scientific-tasks",
|
4 |
+
title: "Evaluating LLMs for Scientific Tasks",
|
5 |
+
date: "February 15, 2025",
|
6 |
+
excerpt: "How effective are large language models at handling specialized scientific concepts?",
|
7 |
+
content: `# Evaluating LLMs for Scientific Tasks
|
8 |
+
|
9 |
+
Scientists and researchers are increasingly turning to Large Language Models (LLMs) to accelerate their work. But how good are these models at truly understanding scientific concepts?
|
10 |
+
|
11 |
+
In our recent work, we developed a framework to evaluate LLMs on tasks specific to material science and chemistry. Here are some key findings:
|
12 |
+
|
13 |
+
1. LLMs trained on general text corpora struggle with specialized scientific reasoning
|
14 |
+
2. Domain-specific fine-tuning significantly improves performance
|
15 |
+
3. There's still a gap between the best models and human experts
|
16 |
+
|
17 |
+
## Methodology
|
18 |
+
|
19 |
+
We created a benchmark consisting of:
|
20 |
+
- Multiple-choice questions from graduate-level textbooks
|
21 |
+
- Reasoning tasks requiring chemical intuition
|
22 |
+
- Structure prediction tasks
|
23 |
+
- Literature-based synthesis tasks
|
24 |
+
|
25 |
+
Read our full paper for detailed results!`
|
26 |
+
},
|
27 |
+
{
|
28 |
+
id: "multimodal-materials",
|
29 |
+
title: "The Promise of Multi-Modal Models in Materials Science",
|
30 |
+
date: "January 10, 2025",
|
31 |
+
excerpt: "Exploring how multi-modal AI can transform materials research and discovery.",
|
32 |
+
content: `# The Promise of Multi-Modal Models in Materials Science
|
33 |
+
|
34 |
+
Modern materials research generates diverse data types - text, images, spectra, crystal structures, and more. Multi-modal models that can process all these data types simultaneously represent an exciting frontier.
|
35 |
+
|
36 |
+
## Current Limitations
|
37 |
+
|
38 |
+
While multi-modal models show promise, our recent work highlights several limitations:
|
39 |
+
- Visual chemical reasoning often fails for complex reactions
|
40 |
+
- Understanding of spatial relationships in crystal structures is limited
|
41 |
+
- Integration of spectroscopic data remains challenging
|
42 |
+
|
43 |
+
## Future Directions
|
44 |
+
|
45 |
+
We're exploring several promising approaches:
|
46 |
+
- Structure-aware pretraining objectives
|
47 |
+
- Specialized tokenization for materials data
|
48 |
+
- Physics-informed neural architectures
|
49 |
+
|
50 |
+
Stay tuned for our upcoming paper!`
|
51 |
+
},
|
52 |
+
{
|
53 |
+
id: "gnn-materials",
|
54 |
+
title: "Geometric Deep Learning for Materials Science",
|
55 |
+
date: "December 5, 2024",
|
56 |
+
excerpt: "How graph neural networks are revolutionizing computational materials discovery.",
|
57 |
+
content: `# Geometric Deep Learning for Materials Science
|
58 |
+
|
59 |
+
Graph Neural Networks (GNNs) have emerged as powerful tools for materials science, offering a natural way to represent atomic structures and predict properties.
|
60 |
+
|
61 |
+
## Advantages of GNNs for Materials
|
62 |
+
|
63 |
+
- **Natural structural representation**: Atoms as nodes, bonds as edges
|
64 |
+
- **Invariance to rotation and translation**: Critical for molecular properties
|
65 |
+
- **Hierarchical information processing**: From atomic to global properties
|
66 |
+
- **Computational efficiency**: Faster than traditional DFT methods
|
67 |
+
|
68 |
+
## Current Research
|
69 |
+
|
70 |
+
Our lab is developing specialized GNN architectures that incorporate physical constraints and uncertainty quantification for high-throughput materials screening.
|
71 |
+
|
72 |
+
|
73 |
+
Our current research focuses on incorporating physical constraints and uncertainty quantification into these architectures.`
|
74 |
+
}
|
75 |
+
];
|
76 |
+
|
77 |
+
export default blogs;
|
src/data/education.js
ADDED
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
const education = [
|
2 |
+
{
|
3 |
+
id: "phd",
|
4 |
+
degree: "PhD Machine Learning",
|
5 |
+
institution: "Friedrich-Schiller-Universität Jena",
|
6 |
+
period: "Oct 2023 – 2026",
|
7 |
+
description: [
|
8 |
+
"Evaluation and development of foundation models for scientific applications",
|
9 |
+
"Advisor: Dr. Kevin Maik Jablonka"
|
10 |
+
]
|
11 |
+
},
|
12 |
+
{
|
13 |
+
id: "masters",
|
14 |
+
degree: "MSc Energy Science",
|
15 |
+
institution: "Indian Institute of Technology Bombay",
|
16 |
+
period: "2018 – 2020",
|
17 |
+
gpa: "8.55/10.0",
|
18 |
+
description: [
|
19 |
+
"Thesis: Defects and Dopants in Cu₂O - DFT study",
|
20 |
+
"Advisor: Prof. K R Balasubramaniam"
|
21 |
+
]
|
22 |
+
},
|
23 |
+
{
|
24 |
+
id: "bachelors",
|
25 |
+
degree: "BSc Physics",
|
26 |
+
institution: "Birla Institute of Technology Mesra",
|
27 |
+
period: "2015 – 2018",
|
28 |
+
gpa: "8.5/10.0",
|
29 |
+
description: []
|
30 |
+
}
|
31 |
+
];
|
32 |
+
|
33 |
+
export default education;
|
src/data/experience.js
ADDED
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
const experience = [
|
2 |
+
{
|
3 |
+
id: "phd-research",
|
4 |
+
position: "PhD Research",
|
5 |
+
company: "Friedrich-Schiller-Universität Jena",
|
6 |
+
period: "Nov 2023 – present",
|
7 |
+
description: [
|
8 |
+
"Developed benchmarking tools and datasets to finetune and evaluate LLMs' performance in material science.",
|
9 |
+
"Created evaluation framework to assess LLMs' chemical reasoning, intuition and knowledge against human experts.",
|
10 |
+
"Built multi-modal AI benchmarks for scientific data extraction, visual comprehension, and laboratory safety assessment."
|
11 |
+
]
|
12 |
+
},
|
13 |
+
{
|
14 |
+
id: "stability-ai",
|
15 |
+
position: "AI Research Contractor",
|
16 |
+
company: "Stability AI",
|
17 |
+
period: "Nov 2023 – Apr 2024",
|
18 |
+
description: [
|
19 |
+
"Dataset preparation for domain specific LLM for chemistry and benchmarking frontier models on domain specific tasks."
|
20 |
+
]
|
21 |
+
},
|
22 |
+
{
|
23 |
+
id: "qpivolta",
|
24 |
+
position: "Principal Engineer",
|
25 |
+
company: "QpiVolta Technologies",
|
26 |
+
period: "Jun 2022 – Sept 2023",
|
27 |
+
description: [
|
28 |
+
"Led development of a cloud platform for material simulation using geometric deep learning models.",
|
29 |
+
"Built uncertainty-aware, physics-informed GNN workflows for high-throughput solid-state electrolyte screening."
|
30 |
+
]
|
31 |
+
},
|
32 |
+
{
|
33 |
+
id: "qpiai",
|
34 |
+
position: "Research Engineer",
|
35 |
+
company: "QpiAI Technologies",
|
36 |
+
period: "Jun 2021 – Jun 2022",
|
37 |
+
description: [
|
38 |
+
"Built DeepStream containers and C++ Gstreamer plugins for real-time video analytics; integrated monocular depth estimation models in safety violation detection pipelines.",
|
39 |
+
"Implemented object detection micro-service for video analytics platform."
|
40 |
+
]
|
41 |
+
}
|
42 |
+
];
|
43 |
+
|
44 |
+
export default experience;
|
src/data/projects.js
ADDED
@@ -0,0 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
const projects = [
|
2 |
+
{
|
3 |
+
id: "energynet",
|
4 |
+
title: "EnergyNet",
|
5 |
+
organization: "TCS Research",
|
6 |
+
period: "Mar 2021 – Oct 2021",
|
7 |
+
description: [
|
8 |
+
"Implemented supervised pretraining of pertrubed crystal structures and transfer learning on modified PointNet++ architecture for predicting relaxed energy from unrelaxed structures. (Advisor: Mayank Baranwal)",
|
9 |
+
"Within top 7 models in NeurIPs OC20 Competition"
|
10 |
+
]
|
11 |
+
},
|
12 |
+
{
|
13 |
+
id: "cu2o-defects",
|
14 |
+
title: "Ab-initio Thermodynamics of Defects in Cu₂O",
|
15 |
+
organization: "IIT Bombay",
|
16 |
+
period: "Jan 2020 – Dec 2020",
|
17 |
+
description: [
|
18 |
+
"Characterized energetics and defect levels of intrinsic defects and dopants in Cu₂O, leading to discovery and experimental validation of new defect formation.",
|
19 |
+
"Performed DFT calculations using Quantum ESPRESSO; and Boltzmann transport. (Advisor: Dayadeep Monder)"
|
20 |
+
]
|
21 |
+
},
|
22 |
+
{
|
23 |
+
id: "topological-materials",
|
24 |
+
title: "Tight Binding Models for Topological Materials",
|
25 |
+
organization: "IIT Bombay",
|
26 |
+
period: "Jun 2020 – Dec 2020",
|
27 |
+
description: [
|
28 |
+
"Studied band structures of graphene nanoribbons via tight-binding; analyzed width and edge effects",
|
29 |
+
"Developed python-based SSH chain model to investigate topological phases and energy eigenvalues. (Advisor: Bhaskaran Muralidharan)"
|
30 |
+
]
|
31 |
+
}
|
32 |
+
];
|
33 |
+
|
34 |
+
export default projects;
|
src/data/publications.js
ADDED
@@ -0,0 +1,60 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
const publications = [
|
2 |
+
{
|
3 |
+
id: "mattext",
|
4 |
+
title: "MatText: Do Language Models Need More than Text & Scale for Materials Modeling?",
|
5 |
+
authors: "Nawaf Alampara, Santiago Miret, Kevin Maik Jablonka",
|
6 |
+
venue: "AI4Mat-Vienna 2024 spotlight presentation",
|
7 |
+
year: "2024",
|
8 |
+
link: "#"
|
9 |
+
},
|
10 |
+
{
|
11 |
+
id: "llm-chemists",
|
12 |
+
title: "Are large language models superhuman chemists?",
|
13 |
+
authors: "Adrian Mirza, Nawaf Alampara, et al.",
|
14 |
+
venue: "Nature Chemistry",
|
15 |
+
year: "2025",
|
16 |
+
link: "#"
|
17 |
+
},
|
18 |
+
{
|
19 |
+
id: "multimodal-limitations",
|
20 |
+
title: "Probing the limitations of multimodal language models for chemistry and materials research",
|
21 |
+
authors: "Nawaf Alampara, et al.",
|
22 |
+
venue: "AI4Mat-NeurIPs 2024 spotlight",
|
23 |
+
year: "2024",
|
24 |
+
link: "#"
|
25 |
+
},
|
26 |
+
{
|
27 |
+
id: "defect-cluster",
|
28 |
+
title: "Formation of an extended defect cluster in cuprous oxide",
|
29 |
+
authors: "G Aggarwal, S Chawla, AJ Singh, Nawaf Alampara, et al.",
|
30 |
+
venue: "Materials Science Journal",
|
31 |
+
year: "2023",
|
32 |
+
link: "#"
|
33 |
+
}
|
34 |
+
];
|
35 |
+
|
36 |
+
const patents = [
|
37 |
+
{
|
38 |
+
id: "uncertainty-sims",
|
39 |
+
title: "Uncertainty Aware Simulations",
|
40 |
+
description: "System and method for performing accelerated molecular dynamics with uncertainty-aware neural networks",
|
41 |
+
id_number: "US Patent Application US20240153595A1",
|
42 |
+
year: "2024"
|
43 |
+
},
|
44 |
+
{
|
45 |
+
id: "lfp-cathode",
|
46 |
+
title: "LFP Cathode Materials",
|
47 |
+
description: "Novel method for deposition of lithium iron phosphate cathode materials",
|
48 |
+
id_number: "US Patent Application US20240072257A1",
|
49 |
+
year: "2024"
|
50 |
+
},
|
51 |
+
{
|
52 |
+
id: "sensor-opt",
|
53 |
+
title: "Sensor Optimization",
|
54 |
+
description: "System and method for sensor position optimization in autonomous vehicles",
|
55 |
+
id_number: "US Patent Application US20230214553A1",
|
56 |
+
year: "2023"
|
57 |
+
}
|
58 |
+
];
|
59 |
+
|
60 |
+
export { publications, patents };
|
src/data/skills.js
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
const skills = {
|
2 |
+
Programming: ["Python", "Golang", "JavaScript"],
|
3 |
+
"ML & AI": ["PyTorch", "PyG", "HuggingFace", "PyTorch Lightning", "OpenCV", "DeepStream"],
|
4 |
+
"DevOps & Tools": ["Git", "Docker", "FastAPI", "MLflow", "Flyte", "CI/CD"],
|
5 |
+
"Scientific Computing": ["Quantum Espresso", "VASP", "ASE", "Pymatgen"]
|
6 |
+
};
|
7 |
+
|
8 |
+
export default skills;
|
src/index.css
ADDED
@@ -0,0 +1,44 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
@tailwind base;
|
2 |
+
@tailwind components;
|
3 |
+
@tailwind utilities;
|
4 |
+
|
5 |
+
:root {
|
6 |
+
--primary: #4a148c;
|
7 |
+
--secondary: #6a1b9a;
|
8 |
+
--accent: #9c27b0;
|
9 |
+
--light: #f3e5f5;
|
10 |
+
--dark: #1a1a1a;
|
11 |
+
--text: #333333;
|
12 |
+
--background: #ffffff;
|
13 |
+
}
|
14 |
+
|
15 |
+
body {
|
16 |
+
margin: 0;
|
17 |
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
18 |
+
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
19 |
+
sans-serif;
|
20 |
+
-webkit-font-smoothing: antialiased;
|
21 |
+
-moz-osx-font-smoothing: grayscale;
|
22 |
+
background-color: var(--background);
|
23 |
+
color: var(--text);
|
24 |
+
}
|
25 |
+
|
26 |
+
code {
|
27 |
+
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
28 |
+
monospace;
|
29 |
+
}
|
30 |
+
|
31 |
+
.app.dark {
|
32 |
+
--primary: #bb86fc;
|
33 |
+
--secondary: #3700b3;
|
34 |
+
--accent: #03dac6;
|
35 |
+
--light: #2d2d2d;
|
36 |
+
--dark: #121212;
|
37 |
+
--text: #e0e0e0;
|
38 |
+
--background: #121212;
|
39 |
+
}
|
40 |
+
|
41 |
+
.app.dark body {
|
42 |
+
background-color: var(--dark);
|
43 |
+
color: var(--text);
|
44 |
+
}
|
src/index.js
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import React from 'react';
|
2 |
+
import ReactDOM from 'react-dom/client';
|
3 |
+
import { BrowserRouter } from 'react-router-dom';
|
4 |
+
import './index.css';
|
5 |
+
import App from './App';
|
6 |
+
|
7 |
+
const root = ReactDOM.createRoot(document.getElementById('root'));
|
8 |
+
root.render(
|
9 |
+
<React.StrictMode>
|
10 |
+
<BrowserRouter>
|
11 |
+
<App />
|
12 |
+
</BrowserRouter>
|
13 |
+
</React.StrictMode>
|
14 |
+
);
|
src/pages/Blog.js
ADDED
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import React from 'react';
|
2 |
+
import BlogCard from '../components/BlogCard';
|
3 |
+
import blogs from '../data/blogs.js'; // Added .js extension
|
4 |
+
|
5 |
+
const Blog = () => {
|
6 |
+
return (
|
7 |
+
<div className="space-y-8">
|
8 |
+
<div className="bg-white rounded-lg shadow p-6">
|
9 |
+
<h1 className="text-3xl font-bold mb-4">Blog</h1>
|
10 |
+
<p className="text-gray-700">
|
11 |
+
Thoughts, insights, and updates on my research in machine learning,
|
12 |
+
materials science, and AI for scientific applications.
|
13 |
+
</p>
|
14 |
+
</div>
|
15 |
+
|
16 |
+
<div className="space-y-8">
|
17 |
+
{blogs.map((blog) => (
|
18 |
+
<BlogCard key={blog.id} blog={blog} />
|
19 |
+
))}
|
20 |
+
</div>
|
21 |
+
|
22 |
+
<div className="bg-white rounded-lg shadow p-6 border-2 border-dashed border-gray-300 flex flex-col items-center justify-center">
|
23 |
+
<h3 className="font-bold text-xl mb-2 text-gray-500">Add New Blog Post</h3>
|
24 |
+
<p className="text-gray-500 text-center mb-4">
|
25 |
+
Use markdown to easily add new blog posts by updating the blogs.js file
|
26 |
+
</p>
|
27 |
+
<button className="px-4 py-2 bg-primary text-white rounded-md hover:bg-secondary transition-colors">
|
28 |
+
Add Post
|
29 |
+
</button>
|
30 |
+
</div>
|
31 |
+
</div>
|
32 |
+
);
|
33 |
+
};
|
34 |
+
|
35 |
+
export default Blog;
|
src/pages/Home.js
ADDED
@@ -0,0 +1,92 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import React from 'react';
|
2 |
+
import { FaGraduationCap, FaBriefcase, FaStar, FaCode } from 'react-icons/fa';
|
3 |
+
import Section from '../components/Section';
|
4 |
+
import EducationCard from '../components/EducationCard';
|
5 |
+
import ExperienceCard from '../components/ExperienceCard';
|
6 |
+
import SkillTag from '../components/SkillTag';
|
7 |
+
import about from '../data/about.js'; // Added .js extension
|
8 |
+
import education from '../data/education.js'; // Added .js extension
|
9 |
+
import experience from '../data/experience.js'; // Added .js extension
|
10 |
+
import skills from '../data/skills.js'; // Added .js extension
|
11 |
+
|
12 |
+
const Home = () => {
|
13 |
+
return (
|
14 |
+
<div className="space-y-8">
|
15 |
+
{/* Bio Section */}
|
16 |
+
<div className="bg-white rounded-lg shadow p-6">
|
17 |
+
<h2 className="text-2xl font-bold mb-4">About Me</h2>
|
18 |
+
<p className="text-gray-700 leading-relaxed">{about.bio}</p>
|
19 |
+
</div>
|
20 |
+
|
21 |
+
{/* Research Interests */}
|
22 |
+
<div className="bg-white rounded-lg shadow p-6">
|
23 |
+
<h2 className="text-2xl font-bold mb-4">Research Interests</h2>
|
24 |
+
<ul className="list-disc list-inside text-gray-700 space-y-2">
|
25 |
+
{about.researchInterests.map((interest, index) => (
|
26 |
+
<li key={index}>{interest}</li>
|
27 |
+
))}
|
28 |
+
</ul>
|
29 |
+
</div>
|
30 |
+
|
31 |
+
{/* Awards */}
|
32 |
+
<Section
|
33 |
+
title="Honors & Awards"
|
34 |
+
icon={<FaStar className="text-primary" />}
|
35 |
+
>
|
36 |
+
<div className="space-y-4">
|
37 |
+
{about.awards.map((award, index) => (
|
38 |
+
<div key={index} className="bg-white rounded-lg shadow p-6">
|
39 |
+
<h3 className="font-bold text-lg">{award.title}</h3>
|
40 |
+
<p className="text-primary">{award.organization}</p>
|
41 |
+
</div>
|
42 |
+
))}
|
43 |
+
</div>
|
44 |
+
</Section>
|
45 |
+
|
46 |
+
{/* Education Section */}
|
47 |
+
<Section
|
48 |
+
title="Education"
|
49 |
+
icon={<FaGraduationCap className="text-primary" />}
|
50 |
+
>
|
51 |
+
<div className="space-y-4">
|
52 |
+
{education.map((edu) => (
|
53 |
+
<EducationCard key={edu.id} education={edu} />
|
54 |
+
))}
|
55 |
+
</div>
|
56 |
+
</Section>
|
57 |
+
|
58 |
+
{/* Experience Section */}
|
59 |
+
<Section
|
60 |
+
title="Experience"
|
61 |
+
icon={<FaBriefcase className="text-primary" />}
|
62 |
+
>
|
63 |
+
<div className="space-y-4">
|
64 |
+
{experience.map((exp) => (
|
65 |
+
<ExperienceCard key={exp.id} experience={exp} />
|
66 |
+
))}
|
67 |
+
</div>
|
68 |
+
</Section>
|
69 |
+
|
70 |
+
{/* Skills Section */}
|
71 |
+
<Section
|
72 |
+
title="Skills"
|
73 |
+
icon={<FaCode className="text-primary" />}
|
74 |
+
>
|
75 |
+
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
76 |
+
{Object.entries(skills).map(([category, skillList]) => (
|
77 |
+
<div key={category} className="bg-white rounded-lg shadow p-6">
|
78 |
+
<h3 className="font-bold text-lg mb-2">{category}</h3>
|
79 |
+
<div className="flex flex-wrap gap-2">
|
80 |
+
{skillList.map((skill, idx) => (
|
81 |
+
<SkillTag key={idx} skill={skill} />
|
82 |
+
))}
|
83 |
+
</div>
|
84 |
+
</div>
|
85 |
+
))}
|
86 |
+
</div>
|
87 |
+
</Section>
|
88 |
+
</div>
|
89 |
+
);
|
90 |
+
};
|
91 |
+
|
92 |
+
export default Home;
|
src/pages/Projects.js
ADDED
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import React from 'react';
|
2 |
+
import { FaFlask } from 'react-icons/fa';
|
3 |
+
import Section from '../components/Section';
|
4 |
+
import ProjectCard from '../components/ProjectCard';
|
5 |
+
import projects from '../data/projects.js'; // Added .js extension
|
6 |
+
|
7 |
+
const Projects = () => {
|
8 |
+
return (
|
9 |
+
<div className="space-y-8">
|
10 |
+
<div className="bg-white rounded-lg shadow p-6">
|
11 |
+
<h1 className="text-3xl font-bold mb-4">Research Projects</h1>
|
12 |
+
<p className="text-gray-700">
|
13 |
+
An overview of my research projects in computational materials science,
|
14 |
+
machine learning, and AI for scientific applications.
|
15 |
+
</p>
|
16 |
+
</div>
|
17 |
+
|
18 |
+
<Section
|
19 |
+
title="Featured Projects"
|
20 |
+
icon={<FaFlask className="text-primary" />}
|
21 |
+
>
|
22 |
+
<div className="space-y-4">
|
23 |
+
{projects.map((project) => (
|
24 |
+
<ProjectCard key={project.id} project={project} />
|
25 |
+
))}
|
26 |
+
</div>
|
27 |
+
</Section>
|
28 |
+
|
29 |
+
<div className="bg-white rounded-lg shadow p-6 border-2 border-dashed border-gray-300 flex flex-col items-center justify-center">
|
30 |
+
<h3 className="font-bold text-xl mb-2 text-gray-500">Add New Project</h3>
|
31 |
+
<p className="text-gray-500 text-center mb-4">
|
32 |
+
Update the projects.js file to add new research projects to your portfolio
|
33 |
+
</p>
|
34 |
+
<button className="px-4 py-2 bg-primary text-white rounded-md hover:bg-secondary transition-colors">
|
35 |
+
Add Project
|
36 |
+
</button>
|
37 |
+
</div>
|
38 |
+
</div>
|
39 |
+
);
|
40 |
+
};
|
41 |
+
|
42 |
+
export default Projects;
|
src/pages/Publications.js
ADDED
@@ -0,0 +1,60 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import React from 'react';
|
2 |
+
import { FaBook, FaFileAlt } from 'react-icons/fa';
|
3 |
+
import Section from '../components/Section';
|
4 |
+
import PublicationCard from '../components/PublicationCard';
|
5 |
+
import { publications, patents } from '../data/publications.js'; // Added .js extension
|
6 |
+
|
7 |
+
const Publications = () => {
|
8 |
+
return (
|
9 |
+
<div className="space-y-8">
|
10 |
+
<div className="bg-white rounded-lg shadow p-6">
|
11 |
+
<h1 className="text-3xl font-bold mb-4">Publications & Patents</h1>
|
12 |
+
<p className="text-gray-700">
|
13 |
+
A collection of my academic publications and patent applications in the fields of
|
14 |
+
materials science, machine learning, and computational chemistry.
|
15 |
+
</p>
|
16 |
+
</div>
|
17 |
+
|
18 |
+
<Section
|
19 |
+
title="Publications"
|
20 |
+
icon={<FaBook className="text-primary" />}
|
21 |
+
>
|
22 |
+
<div className="space-y-4">
|
23 |
+
{publications.map((pub) => (
|
24 |
+
<PublicationCard key={pub.id} publication={pub} />
|
25 |
+
))}
|
26 |
+
</div>
|
27 |
+
</Section>
|
28 |
+
|
29 |
+
<Section
|
30 |
+
title="Patents"
|
31 |
+
icon={<FaFileAlt className="text-primary" />}
|
32 |
+
>
|
33 |
+
<div className="space-y-4">
|
34 |
+
{patents.map((patent) => (
|
35 |
+
<div key={patent.id} className="bg-white rounded-lg shadow p-6 transition-all hover:shadow-lg">
|
36 |
+
<h3 className="font-bold text-lg">{patent.title}</h3>
|
37 |
+
<p className="text-gray-700 mt-1">{patent.description}</p>
|
38 |
+
<div className="flex justify-between items-center mt-2">
|
39 |
+
<p className="text-primary font-medium">{patent.id_number}</p>
|
40 |
+
<span className="text-gray-600">{patent.year}</span>
|
41 |
+
</div>
|
42 |
+
</div>
|
43 |
+
))}
|
44 |
+
</div>
|
45 |
+
</Section>
|
46 |
+
|
47 |
+
<div className="bg-white rounded-lg shadow p-6 border-2 border-dashed border-gray-300 flex flex-col items-center justify-center">
|
48 |
+
<h3 className="font-bold text-xl mb-2 text-gray-500">Add New Publication</h3>
|
49 |
+
<p className="text-gray-500 text-center mb-4">
|
50 |
+
Update the publications.js file to add new publications to your portfolio
|
51 |
+
</p>
|
52 |
+
<button className="px-4 py-2 bg-primary text-white rounded-md hover:bg-secondary transition-colors">
|
53 |
+
Add Publication
|
54 |
+
</button>
|
55 |
+
</div>
|
56 |
+
</div>
|
57 |
+
);
|
58 |
+
};
|
59 |
+
|
60 |
+
export default Publications;
|
src/pages/Resume.js
ADDED
@@ -0,0 +1,155 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import React from 'react';
|
2 |
+
import { FaDownload, FaGraduationCap, FaBriefcase, FaFlask, FaCode, FaAward } from 'react-icons/fa';
|
3 |
+
import about from '../data/about.js'; // Added .js extension
|
4 |
+
import education from '../data/education.js'; // Added .js extension
|
5 |
+
import experience from '../data/experience.js'; // Added .js extension
|
6 |
+
import projects from '../data/projects.js'; // Added .js extension
|
7 |
+
import skills from '../data/skills.js'; // Added .js extension
|
8 |
+
import { publications } from '../data/publications.js'; // Added .js extension
|
9 |
+
|
10 |
+
const Resume = () => {
|
11 |
+
return (
|
12 |
+
<div className="space-y-8">
|
13 |
+
<div className="bg-white rounded-lg shadow p-6 flex justify-between items-center">
|
14 |
+
<div>
|
15 |
+
<h1 className="text-3xl font-bold mb-2">Resume</h1>
|
16 |
+
<p className="text-gray-700">
|
17 |
+
A comprehensive overview of my academic and professional experience
|
18 |
+
</p>
|
19 |
+
</div>
|
20 |
+
<button className="px-4 py-2 bg-primary text-white rounded-md hover:bg-secondary transition-colors flex items-center">
|
21 |
+
<FaDownload className="mr-2" />
|
22 |
+
Download PDF
|
23 |
+
</button>
|
24 |
+
</div>
|
25 |
+
|
26 |
+
{/* Professional Summary */}
|
27 |
+
<div className="bg-white rounded-lg shadow p-6">
|
28 |
+
<h2 className="text-2xl font-bold mb-4">Professional Summary</h2>
|
29 |
+
<p className="text-gray-700 leading-relaxed">{about.bio}</p>
|
30 |
+
</div>
|
31 |
+
|
32 |
+
{/* Education */}
|
33 |
+
<div className="bg-white rounded-lg shadow p-6">
|
34 |
+
<h2 className="text-2xl font-bold mb-4 flex items-center">
|
35 |
+
<FaGraduationCap className="mr-2 text-primary" />
|
36 |
+
Education
|
37 |
+
</h2>
|
38 |
+
<div className="space-y-6">
|
39 |
+
{education.map((edu, index) => (
|
40 |
+
<div key={edu.id} className={index !== 0 ? "pt-4 border-t border-gray-200" : ""}>
|
41 |
+
<div className="flex justify-between flex-wrap">
|
42 |
+
<h3 className="font-bold text-lg">{edu.degree}</h3>
|
43 |
+
<span className="text-gray-600">{edu.period}</span>
|
44 |
+
</div>
|
45 |
+
<p className="text-primary">{edu.institution}</p>
|
46 |
+
{edu.gpa && <p className="text-gray-600">GPA: {edu.gpa}</p>}
|
47 |
+
{edu.description.length > 0 && (
|
48 |
+
<ul className="mt-2 list-disc list-inside text-gray-700">
|
49 |
+
{edu.description.map((item, idx) => (
|
50 |
+
<li key={idx}>{item}</li>
|
51 |
+
))}
|
52 |
+
</ul>
|
53 |
+
)}
|
54 |
+
</div>
|
55 |
+
))}
|
56 |
+
</div>
|
57 |
+
</div>
|
58 |
+
|
59 |
+
{/* Experience */}
|
60 |
+
<div className="bg-white rounded-lg shadow p-6">
|
61 |
+
<h2 className="text-2xl font-bold mb-4 flex items-center">
|
62 |
+
<FaBriefcase className="mr-2 text-primary" />
|
63 |
+
Professional Experience
|
64 |
+
</h2>
|
65 |
+
<div className="space-y-6">
|
66 |
+
{experience.map((exp, index) => (
|
67 |
+
<div key={exp.id} className={index !== 0 ? "pt-4 border-t border-gray-200" : ""}>
|
68 |
+
<div className="flex justify-between flex-wrap">
|
69 |
+
<h3 className="font-bold text-lg">{exp.position}</h3>
|
70 |
+
<span className="text-gray-600">{exp.period}</span>
|
71 |
+
</div>
|
72 |
+
<p className="text-primary">{exp.company}</p>
|
73 |
+
<ul className="mt-2 list-disc list-inside text-gray-700">
|
74 |
+
{exp.description.map((item, idx) => (
|
75 |
+
<li key={idx}>{item}</li>
|
76 |
+
))}
|
77 |
+
</ul>
|
78 |
+
</div>
|
79 |
+
))}
|
80 |
+
</div>
|
81 |
+
</div>
|
82 |
+
|
83 |
+
{/* Research Projects */}
|
84 |
+
<div className="bg-white rounded-lg shadow p-6">
|
85 |
+
<h2 className="text-2xl font-bold mb-4 flex items-center">
|
86 |
+
<FaFlask className="mr-2 text-primary" />
|
87 |
+
Research Projects
|
88 |
+
</h2>
|
89 |
+
<div className="space-y-6">
|
90 |
+
{projects.map((project, index) => (
|
91 |
+
<div key={project.id} className={index !== 0 ? "pt-4 border-t border-gray-200" : ""}>
|
92 |
+
<div className="flex justify-between flex-wrap">
|
93 |
+
<h3 className="font-bold text-lg">{project.title}</h3>
|
94 |
+
<span className="text-gray-600">{project.period}</span>
|
95 |
+
</div>
|
96 |
+
<p className="text-primary">{project.organization}</p>
|
97 |
+
<ul className="mt-2 list-disc list-inside text-gray-700">
|
98 |
+
{project.description.map((item, idx) => (
|
99 |
+
<li key={idx}>{item}</li>
|
100 |
+
))}
|
101 |
+
</ul>
|
102 |
+
</div>
|
103 |
+
))}
|
104 |
+
</div>
|
105 |
+
</div>
|
106 |
+
|
107 |
+
{/* Publications */}
|
108 |
+
<div className="bg-white rounded-lg shadow p-6">
|
109 |
+
<h2 className="text-2xl font-bold mb-4 flex items-center">
|
110 |
+
<FaAward className="mr-2 text-primary" />
|
111 |
+
Selected Publications
|
112 |
+
</h2>
|
113 |
+
<div className="space-y-4">
|
114 |
+
{publications.slice(0, 3).map((pub, index) => (
|
115 |
+
<div key={pub.id} className={index !== 0 ? "pt-4 border-t border-gray-200" : ""}>
|
116 |
+
<h3 className="font-bold text-lg">{pub.title}</h3>
|
117 |
+
<p className="text-gray-700 italic">{pub.authors}</p>
|
118 |
+
<div className="flex justify-between items-center mt-1">
|
119 |
+
<p className="text-primary">{pub.venue}</p>
|
120 |
+
<span className="text-gray-600">{pub.year}</span>
|
121 |
+
</div>
|
122 |
+
</div>
|
123 |
+
))}
|
124 |
+
</div>
|
125 |
+
</div>
|
126 |
+
|
127 |
+
{/* Skills */}
|
128 |
+
<div className="bg-white rounded-lg shadow p-6">
|
129 |
+
<h2 className="text-2xl font-bold mb-4 flex items-center">
|
130 |
+
<FaCode className="mr-2 text-primary" />
|
131 |
+
Technical Skills
|
132 |
+
</h2>
|
133 |
+
<div className="space-y-4">
|
134 |
+
{Object.entries(skills).map(([category, skillList]) => (
|
135 |
+
<div key={category}>
|
136 |
+
<h3 className="font-bold text-lg mb-2">{category}</h3>
|
137 |
+
<div className="flex flex-wrap gap-2 mb-4">
|
138 |
+
{skillList.map((skill, idx) => (
|
139 |
+
<span
|
140 |
+
key={idx}
|
141 |
+
className="px-3 py-1 bg-light text-primary rounded-full text-sm"
|
142 |
+
>
|
143 |
+
{skill}
|
144 |
+
</span>
|
145 |
+
))}
|
146 |
+
</div>
|
147 |
+
</div>
|
148 |
+
))}
|
149 |
+
</div>
|
150 |
+
</div>
|
151 |
+
</div>
|
152 |
+
);
|
153 |
+
};
|
154 |
+
|
155 |
+
export default Resume;
|
tailwind.config.js
ADDED
@@ -0,0 +1,55 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/** @type {import('tailwindcss').Config} */
|
2 |
+
module.exports = {
|
3 |
+
content: [
|
4 |
+
"./src/**/*.{js,jsx,ts,tsx}",
|
5 |
+
"./public/index.html",
|
6 |
+
],
|
7 |
+
theme: {
|
8 |
+
extend: {
|
9 |
+
colors: {
|
10 |
+
primary: 'var(--primary)',
|
11 |
+
secondary: 'var(--secondary)',
|
12 |
+
accent: 'var(--accent)',
|
13 |
+
light: 'var(--light)',
|
14 |
+
dark: 'var(--dark)',
|
15 |
+
},
|
16 |
+
fontFamily: {
|
17 |
+
sans: ['Inter', 'sans-serif'],
|
18 |
+
},
|
19 |
+
typography: {
|
20 |
+
DEFAULT: {
|
21 |
+
css: {
|
22 |
+
color: 'var(--text)',
|
23 |
+
a: {
|
24 |
+
color: 'var(--primary)',
|
25 |
+
'&:hover': {
|
26 |
+
color: 'var(--secondary)',
|
27 |
+
},
|
28 |
+
},
|
29 |
+
h1: {
|
30 |
+
color: 'var(--text)',
|
31 |
+
},
|
32 |
+
h2: {
|
33 |
+
color: 'var(--text)',
|
34 |
+
},
|
35 |
+
h3: {
|
36 |
+
color: 'var(--text)',
|
37 |
+
},
|
38 |
+
h4: {
|
39 |
+
color: 'var(--text)',
|
40 |
+
},
|
41 |
+
code: {
|
42 |
+
color: 'var(--primary)',
|
43 |
+
backgroundColor: 'var(--light)',
|
44 |
+
padding: '0.25rem 0.5rem',
|
45 |
+
borderRadius: '0.25rem',
|
46 |
+
},
|
47 |
+
},
|
48 |
+
},
|
49 |
+
},
|
50 |
+
},
|
51 |
+
},
|
52 |
+
plugins: [
|
53 |
+
require('@tailwindcss/typography'),
|
54 |
+
],
|
55 |
+
};
|