Tools: How I Built My DevOps Portfolio Website from Scratch

Tools: How I Built My DevOps Portfolio Website from Scratch

How I Built My DevOps Portfolio Website from Scratch

Here's exactly how I did it and how you can too.

That difference is everything.

Live site: https://gaurav2349.github.io/portfolio-/

Deployed via gh-pages

https://yourusername.github.io/reponame

It updates automatically every day. Zero maintenance.

Site updates in 2 minutes. 🚀

update needed. As a fresher DevOps Engineer from CDAC Pune, one of the

first things I realized was that having a live portfoliowebsite is more powerful than any certificate or resume PDF.So I built one. From scratch. And deployed it live on theinternet the same day. Why I Built a PortfolioI was applying for DevOps roles in Pune and kept gettingignored. The problem wasn't my skills it was that nobodycould SEE my skills.A resume says "I know Docker and Kubernetes."A portfolio SHOWS it. What I BuiltA fully responsive dark-themed portfolio with:Animated typewriter showing my DevOps rolesLive GitHub contribution graph (updates automatically)Skills section with animated progress barsProjects section with GitHub linksAuto-fetching blog posts from Dev.toDownload resume buttonTerminal widget showing my skillsContact section with all my links Tech StackVersion 1 — Plain HTML/CSS/JSNo framework neededSingle file deploymentHosted free on GitHub PagesVersion 2 — ReactComponent-based architectureGitHub API integrationDev.to API for blog posts Step 1 — Setting Up GitHub PagesGitHub Pages is completely free and perfect forportfolio hosting.Here's what I did: Then in GitHub:Settings → Pages → Source → main branch → SaveYour site is live at: Step 2 — The Terminal WidgetThe terminal widget was my favourite part to build.It gives the portfolio that DevOps engineer aesthetic. Step 3 — Typewriter AnimationThis was pure JavaScript — no library needed. Step 4 — GitHub Contribution GraphI used ghchart.rshah.org — a free service thatgenerates your GitHub contribution graph as an image. Replace Gaurav2349 with your GitHub username.The color 00d4ff is the cyan accent color. Step 5 — Deploying the React VersionFor the React portfolio I used gh-pages package. Every time I make a change: Step 6 — Auto-fetching Dev.to PostsThis was the coolest dynamic feature. My portfolioautomatically shows my latest Dev.to posts usingtheir free API. Every time I publish a new post on Dev.to, it

automatically appears on my portfolio. No manual Templates let you quickly answer FAQs or store snippets for re-use. Hide child comments as well For further actions, you may consider blocking this person and/or reporting abuse

Command

Copy

# Create a new repo on GitHub # Clone it locally -weight: 500;">git clone https://github.com/Gaurav2349/portfolio-.-weight: 500;">git cd portfolio- # Add your index.html file -weight: 500;">git add index.html -weight: 500;">git commit -m "Add portfolio website" -weight: 500;">git push origin main # Create a new repo on GitHub # Clone it locally -weight: 500;">git clone https://github.com/Gaurav2349/portfolio-.-weight: 500;">git cd portfolio- # Add your index.html file -weight: 500;">git add index.html -weight: 500;">git commit -m "Add portfolio website" -weight: 500;">git push origin main # Create a new repo on GitHub # Clone it locally -weight: 500;">git clone https://github.com/Gaurav2349/portfolio-.-weight: 500;">git cd portfolio- # Add your index.html file -weight: 500;">git add index.html -weight: 500;">git commit -m "Add portfolio website" -weight: 500;">git push origin main <div class="terminal"> <div class="terminal-bar"> <span class="dot red"></span> <span class="dot yellow"></span> <span class="dot green"></span> </div> <div class="terminal-body"> <div>$ whoami</div> <div class="output">→ DevOps Engineer</div> <div>$ -weight: 500;">kubectl get skills</div> <div class="output">Docker Running ✓</div> <div class="output">Kubernetes Running ✓</div> </div> </div> <div class="terminal"> <div class="terminal-bar"> <span class="dot red"></span> <span class="dot yellow"></span> <span class="dot green"></span> </div> <div class="terminal-body"> <div>$ whoami</div> <div class="output">→ DevOps Engineer</div> <div>$ -weight: 500;">kubectl get skills</div> <div class="output">Docker Running ✓</div> <div class="output">Kubernetes Running ✓</div> </div> </div> <div class="terminal"> <div class="terminal-bar"> <span class="dot red"></span> <span class="dot yellow"></span> <span class="dot green"></span> </div> <div class="terminal-body"> <div>$ whoami</div> <div class="output">→ DevOps Engineer</div> <div>$ -weight: 500;">kubectl get skills</div> <div class="output">Docker Running ✓</div> <div class="output">Kubernetes Running ✓</div> </div> </div> const roles = [ 'DevOps Engineer', 'Linux Power User', 'CI/CD Pipeline Builder', 'Cloud Administrator' ]; let roleIndex = 0; let charIndex = 0; let deleting = false; function type() { const word = roles[roleIndex]; if (!deleting) { // typing forward element.textContent = word.slice(0, charIndex++); if (charIndex > word.length) { deleting = true; setTimeout(type, 1800); return; } } else { // deleting backward element.textContent = word.slice(0, charIndex--); if (charIndex < 0) { deleting = false; roleIndex = (roleIndex + 1) % roles.length; charIndex = 0; } } setTimeout(type, deleting ? 45 : 85); } const roles = [ 'DevOps Engineer', 'Linux Power User', 'CI/CD Pipeline Builder', 'Cloud Administrator' ]; let roleIndex = 0; let charIndex = 0; let deleting = false; function type() { const word = roles[roleIndex]; if (!deleting) { // typing forward element.textContent = word.slice(0, charIndex++); if (charIndex > word.length) { deleting = true; setTimeout(type, 1800); return; } } else { // deleting backward element.textContent = word.slice(0, charIndex--); if (charIndex < 0) { deleting = false; roleIndex = (roleIndex + 1) % roles.length; charIndex = 0; } } setTimeout(type, deleting ? 45 : 85); } const roles = [ 'DevOps Engineer', 'Linux Power User', 'CI/CD Pipeline Builder', 'Cloud Administrator' ]; let roleIndex = 0; let charIndex = 0; let deleting = false; function type() { const word = roles[roleIndex]; if (!deleting) { // typing forward element.textContent = word.slice(0, charIndex++); if (charIndex > word.length) { deleting = true; setTimeout(type, 1800); return; } } else { // deleting backward element.textContent = word.slice(0, charIndex--); if (charIndex < 0) { deleting = false; roleIndex = (roleIndex + 1) % roles.length; charIndex = 0; } } setTimeout(type, deleting ? 45 : 85); } <img src="https://ghchart.rshah.org/00d4ff/Gaurav2349" alt="GitHub contributions" /> <img src="https://ghchart.rshah.org/00d4ff/Gaurav2349" alt="GitHub contributions" /> <img src="https://ghchart.rshah.org/00d4ff/Gaurav2349" alt="GitHub contributions" /> # Install gh-pages -weight: 500;">npm -weight: 500;">install gh-pages --save-dev # Add to package.json "homepage": "https://gaurav2349.github.io/portfolio-", "scripts": { "predeploy": "-weight: 500;">npm run build", "deploy": "gh-pages -d build" } # Deploy with one command -weight: 500;">npm run deploy # Install gh-pages -weight: 500;">npm -weight: 500;">install gh-pages --save-dev # Add to package.json "homepage": "https://gaurav2349.github.io/portfolio-", "scripts": { "predeploy": "-weight: 500;">npm run build", "deploy": "gh-pages -d build" } # Deploy with one command -weight: 500;">npm run deploy # Install gh-pages -weight: 500;">npm -weight: 500;">install gh-pages --save-dev # Add to package.json "homepage": "https://gaurav2349.github.io/portfolio-", "scripts": { "predeploy": "-weight: 500;">npm run build", "deploy": "gh-pages -d build" } # Deploy with one command -weight: 500;">npm run deploy -weight: 500;">npm run deploy -weight: 500;">npm run deploy -weight: 500;">npm run deploy useEffect(() => { fetch('https://dev.to/api/articles?username=gauravnayak&per_page=3') .then(r => r.json()) .then(data => setPosts(data)); }, []); useEffect(() => { fetch('https://dev.to/api/articles?username=gauravnayak&per_page=3') .then(r => r.json()) .then(data => setPosts(data)); }, []); useEffect(() => { fetch('https://dev.to/api/articles?username=gauravnayak&per_page=3') .then(r => r.json()) .then(data => setPosts(data)); }, []); - HTML/CSS/JS is enough to build something impressive You don't need React for everything. My first version was a single HTML file and it looked amazing. - GitHub Pages is genuinely free and powerful No server costs, no hosting fees, no configuration. Perfect for portfolios. - A live URL beats a PDF resume every time I started including my portfolio link in every application. Response rate improved noticeably. - Build in public Pushing code regularly, making open source contributions, writing blogs — all of this builds your online presence over time. --- Results Portfolio live at: https://gaurav2349.github.io/portfolio-/ GitHub: https://github.com/Gaurav2349 First open source PR merged on an 18k star repo Reliance job application submitted --- Your Turn If you're a fresher DevOps engineer reading this build your portfolio today. Not tomorrow. Today. It takes one afternoon and the results speak for themselves. All you need: A GitHub account (free) Basic HTML/CSS knowledge Your resume content If I could do it you can too. --- I'm Gaurav Nayak, a fresher DevOps Engineer from CDAC Pune actively looking for DevOps/Cloud/Linux Admin roles. Let's connect on LinkedIn or check out my GitHub.