9.9 KiB
🌐 Muaz Bhutta — Portfolio
A blazing-fast, zero-dependency static portfolio with automated CI/CD deployment
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.
📋 Table of Contents
- ✨ Features
- 🏗️ Architecture
- 📁 File Structure
- ✏️ Updating Content
- 🚀 Getting Started
- 🔁 Deployment Flow
- 🛠️ Tech Stack
- 📄 License
- 📬 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:
{
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, orscript.jsever 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):
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
cd portfolio
git init
git add .
git commit -m "Initial portfolio"
git branch -M main
git remote add origin https://github.com/<your-username>/portfolio.git
git push -u origin main
Why this matters:
- 📌 Your code becomes version-controlled — every change is tracked
- 🤖 It becomes the trigger source for the CI/CD pipeline — every push to
mainauto-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:
# from your local machine
rsync -avz --delete ./portfolio/ user@your-server-ip:/var/www/portfolio/
Confirm the Caddyfile block:
muazbhutta.online {
root * /var/www/portfolio
file_server
}
Then reload:
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)
# 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:
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
.gitignoreblocks*.keyand.ssh/as a safety net.
🧪 Testing the Pipeline
# 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 | 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
⭐ If this repo helped you build your own portfolio pipeline, consider giving it a star! ⭐
Built with ❤️ and zero frameworks