# 🌐 Muaz Bhutta β€” Portfolio **A blazing-fast, zero-dependency static portfolio with automated CI/CD deployment** [![Live Site](https://img.shields.io/badge/Live-muazbhutta.online-2ea44f?style=for-the-badge&logo=googlechrome&logoColor=white)](https://muazbhutta.online) [![Deploy Status](https://img.shields.io/badge/Deploy-GitHub%20Actions-2088FF?style=for-the-badge&logo=githubactions&logoColor=white)](#-cicd--auto-deploy-on-every-push) [![License](https://img.shields.io/badge/License-MIT-yellow?style=for-the-badge)](LICENSE) ![HTML5](https://img.shields.io/badge/HTML5-E34F26?style=flat-square&logo=html5&logoColor=white) ![CSS3](https://img.shields.io/badge/CSS3-1572B6?style=flat-square&logo=css3&logoColor=white) ![JavaScript](https://img.shields.io/badge/JavaScript-F7DF1E?style=flat-square&logo=javascript&logoColor=black) ![Caddy](https://img.shields.io/badge/Caddy-1F88C0?style=flat-square&logo=caddy&logoColor=white) ![GitHub Actions](https://img.shields.io/badge/GitHub_Actions-2088FF?style=flat-square&logo=githubactions&logoColor=white) ![rsync](https://img.shields.io/badge/rsync-CC0000?style=flat-square&logo=gnubash&logoColor=white) *No build step. No framework. No node_modules black hole. Just clean HTML/CSS/JS β€” deployed automatically to a self-hosted VPS on every push.* [Live Demo](https://muazbhutta.online) Β· [Report Bug](../../issues) Β· [Request Feature](../../issues)
--- ## πŸ“‹ Table of Contents - [✨ Features](#-features) - [πŸ—οΈ Architecture](#️-architecture) - [πŸ“ File Structure](#-file-structure) - [✏️ Updating Content](#️-updating-content-the-important-part) - [πŸš€ Getting Started](#-getting-started) - [Run Locally](#step-1--run-it-locally) - [Push to GitHub](#step-2--push-to-github) - [Manual Deploy](#step-3--manual-deploy-to-the-vps) - [CI/CD Setup](#step-4--cicd--auto-deploy-on-every-push) - [πŸ” Deployment Flow](#-deployment-flow) - [πŸ› οΈ Tech Stack](#️-tech-stack) - [πŸ“„ License](#-license) - [πŸ“¬ Contact](#-contact) --- ## ✨ Features | Feature | Description | |---|---| | ⚑ **Fully Static** | Zero dependencies beyond Google Fonts β€” loads instantly | | πŸŒ— **Light / Dark / Auto Theme** | Auto mode follows the visitor's system setting and updates **live** if it changes | | πŸ“œ **Scroll-Reveal Timeline** | Animated career timeline, fully responsive down to mobile | | πŸ—‚οΈ **Single-File Content** | All content lives in `data.js` β€” edit one file, never touch markup | | πŸ€– **Auto-Deploy CI/CD** | Every push to `main` deploys to the VPS via GitHub Actions + rsync | | πŸ”’ **Self-Hosted** | Served by Caddy with automatic HTTPS on a personal VPS | --- ## πŸ—οΈ Architecture ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” git push β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Developer β”‚ ────────────────▢ β”‚ GitHub (main) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ triggers β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ GitHub Actions β”‚ β”‚ (deploy.yml) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ rsync over SSH β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” HTTPS (443) β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Visitor β”‚ ◀──────────────── β”‚ VPS + Caddy β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ auto-SSL πŸ”’ β”‚ /var/www/portfolioβ”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` --- ## πŸ“ File Structure ``` portfolio/ β”œβ”€β”€ index.html β†’ page structure β”œβ”€β”€ style.css β†’ design & theme tokens β”œβ”€β”€ script.js β†’ renders data.js into the page (no need to edit) β”œβ”€β”€ data.js β†’ ⭐ EDIT THIS FILE to add content β”œβ”€β”€ .gitignore β†’ keeps secrets & system files out of git └── .github/ └── workflows/ └── deploy.yml β†’ auto-deploy pipeline ``` --- ## ✏️ Updating Content (the important part) To add a new project, open **`data.js`** and add an object to the `PROJECTS` array: ```js { id: "unique-id", title: "Project Name", summary: "1–2 line description.", stack: ["Tech1", "Tech2"], link: "https://...", // or "#" if there's no link status: "production", // "production" or "lab" }, ``` > πŸ’‘ **Skills, credentials, About paragraphs, and the career timeline all work the same way** β€” add or edit an object in the matching array. Nothing in `index.html`, `style.css`, or `script.js` ever needs to change. --- ## πŸš€ Getting Started ### Step 1 β€” Run it locally These are static files, so "running" it just means opening it in a browser: **Option A (simplest):** ``` double-click index.html ``` **Option B (recommended β€” mirrors production behavior):** ```bash python3 -m http.server 8000 ``` Then open **http://localhost:8000**. This matches how Caddy serves the files on the VPS, so local behavior = production behavior. --- ### Step 2 β€” Push to GitHub ```bash cd portfolio git init git add . git commit -m "Initial portfolio" git branch -M main git remote add origin https://github.com//portfolio.git git push -u origin main ``` Why this matters: 1. πŸ“Œ Your code becomes **version-controlled** β€” every change is tracked 2. πŸ€– It becomes the **trigger source** for the CI/CD pipeline β€” every push to `main` auto-deploys --- ### Step 3 β€” Manual Deploy to the VPS *(first time, or without CI/CD)* The VPS already runs Caddy serving `muazbhutta.online` β€” just copy files into the directory Caddy points at: ```bash # from your local machine rsync -avz --delete ./portfolio/ user@your-server-ip:/var/www/portfolio/ ``` Confirm the Caddyfile block: ```caddy muazbhutta.online { root * /var/www/portfolio file_server } ``` Then reload: ```bash sudo systemctl reload caddy ``` βœ… **`https://muazbhutta.online` is now live** β€” Caddy handles SSL automatically. > πŸ”€ **Want a subdomain instead?** (e.g. `portfolio.muazbhutta.online`) β€” add a new Caddyfile block with the same directives, using the subdomain as the site address. --- ### Step 4 β€” CI/CD: Auto-Deploy on Every Push `.github/workflows/deploy.yml` uses **GitHub Actions** to rsync files to the VPS over SSH on every push to `main`. #### πŸ”‘ Required Repository Secrets Go to: **Repo β†’ Settings β†’ Secrets and variables β†’ Actions β†’ New repository secret** | Secret | Value | |---|---| | `DEPLOY_HOST` | Your VPS IP address | | `DEPLOY_USER` | SSH username on the VPS | | `DEPLOY_PORT` | `22` (or your custom SSH port) | | `DEPLOY_PATH` | `/var/www/portfolio/` | | `DEPLOY_SSH_KEY` | Private SSH deploy key *(see below)* | #### πŸ—οΈ Generating a Dedicated Deploy Key *(best practice)* ```bash # on your local machine ssh-keygen -t ed25519 -C "github-deploy" -f ./deploy_key -N "" ``` This creates `deploy_key` (private) + `deploy_key.pub` (public). Authorize the **public** key on the VPS: ```bash ssh-copy-id -i deploy_key.pub user@your-server-ip ``` *(or manually append `deploy_key.pub` contents to `~/.ssh/authorized_keys` on the VPS)* Then paste the **full contents of `deploy_key`** (the private key) into the `DEPLOY_SSH_KEY` secret on GitHub. > ⚠️ **Never commit the private key to the repo.** It lives only in GitHub Secrets. The included `.gitignore` blocks `*.key` and `.ssh/` as a safety net. #### πŸ§ͺ Testing the Pipeline ```bash # make a small change, e.g. add a project in data.js git add . git commit -m "Add new project" git push ``` Watch the **Actions** tab β†’ pipeline runs β†’ within **30–60 seconds** the change is live. No manual rsync. No SSH. ✨ --- ## πŸ” Deployment Flow ``` Edit data.js (add a project / skill / timeline entry) β”‚ β–Ό git add . && git commit -m "update" && git push β”‚ β–Ό GitHub Actions triggers automatically β”‚ β–Ό rsync copies files to VPS over SSH β”‚ β–Ό Caddy is already serving β†’ change is LIVE πŸŽ‰ ``` **From now on: edit `data.js`, push, done.** Everything else is automatic. --- ## πŸ› οΈ Tech Stack | Layer | Technology | Why | |---|---|---| | **Frontend** | Vanilla HTML5 / CSS3 / JS | Zero build step, instant loads, easy maintenance | | **Theming** | CSS custom properties + `prefers-color-scheme` | Native Light/Dark/Auto with live OS sync | | **Web Server** | [Caddy](https://caddyserver.com/) | Automatic HTTPS, dead-simple config | | **CI/CD** | GitHub Actions | Free, integrated, zero-maintenance pipeline | | **Transport** | rsync over SSH | Fast delta transfers β€” only changed files move | | **Hosting** | Self-hosted VPS | Full control, part of a larger self-hosted infra lab | --- ## πŸ“„ License Distributed under the **MIT License**. See `LICENSE` for more information. --- ## πŸ“¬ Contact **Muaz Bhutta** β€” Junior Network / Cloud & DevOps Engineer [![Website](https://img.shields.io/badge/Website-muazbhutta.online-2ea44f?style=flat-square&logo=googlechrome&logoColor=white)](https://muazbhutta.online) [![GitHub](https://img.shields.io/badge/GitHub-Follow-181717?style=flat-square&logo=github)](https://github.com/your-username) [![LinkedIn](https://img.shields.io/badge/LinkedIn-Connect-0A66C2?style=flat-square&logo=linkedin&logoColor=white)](https://linkedin.com/in/your-profile)
⭐ **If this repo helped you build your own portfolio pipeline, consider giving it a star!** ⭐ *Built with ❀️ and zero frameworks*