This repository powers my personal website, but it is also intentionally built as a reusable, open-source portfolio template.
It’s content-driven: most updates can be done by editing JSON + Markdown files (projects, blogs, FAQs, services, sitemap, documents), without changing core UI logic.
- Frontend: Vite + React + React Router + Tailwind CSS
- Backend: Express + Nodemailer (contact form API)
- Content: JSON + Markdown
- Deploy: GitHub Pages (frontend) + Vercel (backend)
- Content-driven portfolio (edit JSON/Markdown to update the site)
- Projects, blogs, courses, FAQs, services pages
- Built-in search + structured views
- SEO utilities (sitemap + metadata modules)
- Contact form backed by Express API (Nodemailer)
- Designed for easy customization and maintenance
Template users (important): this repo includes a Google Search Console verification file in the root:
google90204ddbeb9f3cf5.html
If you deploy your own copy, remove it or replace it with your own verification file, otherwise it will verify the site for the original owner instead of you.
- Click Use this template (recommended), or fork the repo.
- Rename it to:
<your-username>.github.io(for GitHub Pages user site)
Start here:
frontend/public/data/json/(projects, blogs, courses, FAQs, services, sitemap, etc.)frontend/public/data/blogs/(Markdown blog posts)frontend/public/data/docs/(Markdown legal/docs)frontend/src/assets/common/author.js(your profile)frontend/src/assets/common/skills.js(skills list)frontend/src/assets/common/footer.js(footer/social links)
Follow the Quick Start section below to run frontend + backend locally.
- Frontend → GitHub Pages
- Backend → Vercel Then set environment variables exactly as documented below.
git clone https://github.com/saqibbedar/saqibbedar.github.io.git
cd saqibbedar.github.iocd frontend
npm installcd ../backend
npm installnpm run devThe backend runs on http://localhost:8000 by default.
Open a second terminal:
cd frontend
npm run devThe frontend runs on Vite’s default local port, usually http://localhost:5173.
Both apps use .env files.
Place this in frontend/.env:
VITE_BACKEND_CONTACT_API=http://localhost:8000/api/contactIf your backend is deployed on Vercel, replace it with your deployed API URL.
Place this in backend/.env:
EMAIL_USER=yourgmail@gmail.com
EMAIL_PASS=your_gmail_app_password
EMAIL_TO=yourgmail@gmail.com
FRONTEND_URL=https://saqibbedar.github.ioNotes:
EMAIL_USERis the Gmail address used to send mail.EMAIL_PASSshould be a Gmail App Password, not your normal login password.EMAIL_TOis optional if you want a separate inbox to receive contact mail.FRONTEND_URLis used by CORS on the backend.
The contact form sends JSON to the backend endpoint.
- Frontend request path:
VITE_BACKEND_CONTACT_API - Backend route:
/api/contact - Mail transport: Gmail through Nodemailer
The frontend validates the form before sending. The backend then receives the payload and sends the email to your inbox.
The frontend contains the full portfolio UI and content system.
Key folders:
frontend/public/data/json/- main content data for projects, blogs, courses, FAQs, services, sitemap, certificates, testimonials, education, and bootcampsfrontend/public/data/data-structures/- datatype references and example records for the JSON filesfrontend/public/data/blogs/- markdown-based blog postsfrontend/public/data/docs/- markdown docs for policy and termsfrontend/src/assets/- static asset data, author info, footer links, skills, and metadata mapsfrontend/src/components/common/- shared navbar and footerfrontend/src/components/sections/- page sections used to build each pagefrontend/src/components/features/- reusable feature-level logic and search helpersfrontend/src/components/views/- dynamic view components for blog, course, and project detail pagesfrontend/src/pages/- page entry pointsfrontend/src/routes/- application routesfrontend/src/services/- fetch, cache, and search logic used by the whole appfrontend/src/context/- global content and search state
The backend is intentionally small.
It includes:
backend/index.js- Express server and Gmail mail senderbackend/.env- runtime environment valuesbackend/package.json- server scripts and dependencies
If you want to personalize the site, these are the fastest places to start.
Most site content is in:
frontend/public/data/json/
This is where you will find:
projects.jsonblogs.jsoncourses.jsonfaqs.jsonservices.jsonsitemap.jsontestimonials.jsoneducation.jsoncertificates.jsonbootcamps-events.json
If you change data shapes here, update the matching fetch and search services too.
Look at:
frontend/src/assets/common/author.jsfrontend/src/assets/common/footer.jsfrontend/src/assets/common/skills.jsfrontend/src/assets/metadata/pages.jsfrontend/src/assets/metadata/views.js
These files control the profile text, social links, and metadata used across the site.
The main shell lives here:
frontend/src/components/common/Navbar/frontend/src/components/common/Footer/
If you want to change menu items, footer links, or social profile shortcuts, start there.
Each page is built from reusable section components in:
frontend/src/components/sections/
If you want to reverse engineer how a page is built, this is the first folder to inspect.
For content that changes by item:
frontend/src/components/views/Project/frontend/src/components/views/Blog/frontend/src/components/views/Course/
These handle dynamic pages and detail layouts.
The whole application logic is concentrated in:
frontend/src/services/
This is where fetching, caching, indexing, and search behavior live.
If you change the data structure, update the corresponding service too. The search index also needs to be updated whenever searchable fields change.
Check frontend/src/routes/AppRoutes.jsx for the full route map.
Important routes include:
/- Home/about- About/contact- Contact/projects- Projects/blogs- Blogs/courses- Courses/services- Services/faqs- FAQs/sitemap- Sitemap/search- Search/privacy-policy- Privacy Policy/terms-conditions- Terms and Conditions
Dynamic detail routes:
/projects/:id/blogs/:slug/courses/:id
This project is intentionally data-driven.
That means:
- update JSON data in
frontend/public/data/json/ - update schema references in
frontend/public/data/data-structures/ - update fetch services in
frontend/src/services/fetch/ - update search services in
frontend/src/services/search/
If you change a data field in a JSON file, check the related fetcher and indexing logic. That is the part most likely to break if the structure is changed without follow-up edits.
The backend only exists to send contact emails.
Current behavior:
- receives contact payload from the frontend
- validates email and message
- sends mail using Gmail and Nodemailer
- allows the deployed frontend via CORS
If you use Gmail:
- generate an App Password from your Google account
- do not use your normal Gmail password for SMTP
If you prefer another provider:
- change the Nodemailer transport settings in
backend/index.js - keep the frontend contact endpoint unchanged unless your API route changes
This is a Vite project, so the usual flow is:
- build the app
- publish the generated output
- connect GitHub Pages to the publish branch or deployment pipeline
If you deploy the frontend on GitHub Pages, make sure the backend API URL is updated in frontend/.env before building.
The backend is small and deploys well on Vercel.
Remember to set these environment variables on Vercel:
EMAIL_USEREMAIL_PASSEMAIL_TOif neededFRONTEND_URL
Contributions are welcome.
Before contributing:
- read
CONTRIBUTING.md - follow the existing code style
- update service logic if you change any data schema
- keep content-driven updates aligned with the data files
Please read CODE_OF_CONDUCT.md before contributing or opening issues.
The goal is simple: keep the project respectful, useful, and easy to maintain.
This project is released under the MIT License.
See LICENSE for the full text.
If you only remember three things, remember these:
- most content lives in
frontend/public/data/json/ - most behavior lives in
frontend/src/services/ - contact mail is handled by
backend/index.js
That is the core of the project.