Skip to content

Commit c35aee7

Browse files
committed
Add comprehensive SEO, Open Graph, and favicon metadata to all pages and implement responsive contact card, project, tech-stack, and blog page layout.
1 parent b678042 commit c35aee7

8 files changed

Lines changed: 644 additions & 78 deletions

blog.html

Lines changed: 243 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -89,14 +89,104 @@ <h1>Mit Patel's Blog</h1>
8989
<div class="container">
9090
<main>
9191
<section>
92-
<h2 class="section-heading">
93-
<span style="display: inline-flex; align-items: baseline; gap: 0.5rem;">
94-
Recent Posts
95-
<span
96-
style="font-size: 0.65em; font-weight: 500; opacity: 0.6; text-transform: uppercase; font-style: italic; letter-spacing: 0.5px;">Total
97-
Posts: 12</span>
98-
</span>
99-
</h2>
92+
<div class="blog-heading-row">
93+
<h2 class="section-heading">
94+
<span style="display: inline-flex; align-items: baseline; gap: 0.5rem;">
95+
Recent Posts
96+
<span
97+
style="font-size: 0.65em; font-weight: 500; opacity: 0.6; text-transform: uppercase; font-style: italic; letter-spacing: 0.5px;">Total
98+
Posts: 12</span>
99+
</span>
100+
</h2>
101+
<!-- Mobile filter toggle button (hidden on desktop) -->
102+
<button id="mobile-filter-toggle" class="mobile-filter-toggle"
103+
aria-label="Filter by technology">
104+
<i class="fas fa-filter"></i>
105+
<span class="mobile-filter-label">Filter</span>
106+
</button>
107+
</div>
108+
109+
<!-- Mobile filter dropdown (hidden by default, shown on toggle) -->
110+
<div id="mobile-filter-panel" class="mobile-filter-panel">
111+
<div id="mobile-tag-filter-container" class="mobile-tag-container">
112+
<button class="tag filter-tag active" data-tag="all">Show All</button>
113+
114+
<button class="tag filter-tag" data-tag="aws">AWS</button>
115+
116+
<button class="tag filter-tag" data-tag="aws ec2">AWS EC2</button>
117+
118+
<button class="tag filter-tag" data-tag="aws ecr">AWS ECR</button>
119+
120+
<button class="tag filter-tag" data-tag="aws elastic beanstalk">AWS Elastic Beanstalk</button>
121+
122+
<button class="tag filter-tag" data-tag="aws s3">AWS S3</button>
123+
124+
<button class="tag filter-tag" data-tag="aws sagemaker">AWS SageMaker</button>
125+
126+
<button class="tag filter-tag" data-tag="agentic ai">Agentic AI</button>
127+
128+
<button class="tag filter-tag" data-tag="agno">Agno</button>
129+
130+
<button class="tag filter-tag" data-tag="cloudwatch">CloudWatch</button>
131+
132+
<button class="tag filter-tag" data-tag="dagshub">Dagshub</button>
133+
134+
<button class="tag filter-tag" data-tag="docker">Docker</button>
135+
136+
<button class="tag filter-tag" data-tag="duckduckgo api">DuckDuckGo API</button>
137+
138+
<button class="tag filter-tag" data-tag="duckduckgotools">DuckDuckGoTools</button>
139+
140+
<button class="tag filter-tag" data-tag="fastapi">FastAPI</button>
141+
142+
<button class="tag filter-tag" data-tag="flask">Flask</button>
143+
144+
<button class="tag filter-tag" data-tag="github actions">GitHub Actions</button>
145+
146+
<button class="tag filter-tag" data-tag="google api">Google API</button>
147+
148+
<button class="tag filter-tag" data-tag="google gemini">Google Gemini</button>
149+
150+
<button class="tag filter-tag" data-tag="groq">Groq</button>
151+
152+
<button class="tag filter-tag" data-tag="huggingface transformers">HuggingFace Transformers</button>
153+
154+
<button class="tag filter-tag" data-tag="mlops">MLOps</button>
155+
156+
<button class="tag filter-tag" data-tag="mlflow">MLflow</button>
157+
158+
<button class="tag filter-tag" data-tag="mongodb">MongoDB</button>
159+
160+
<button class="tag filter-tag" data-tag="multi-agent systems">Multi-Agent Systems</button>
161+
162+
<button class="tag filter-tag" data-tag="nlp">NLP</button>
163+
164+
<button class="tag filter-tag" data-tag="numpy">NumPy</button>
165+
166+
<button class="tag filter-tag" data-tag="pandas">Pandas</button>
167+
168+
<button class="tag filter-tag" data-tag="pytorch">PyTorch</button>
169+
170+
<button class="tag filter-tag" data-tag="python">Python</button>
171+
172+
<button class="tag filter-tag" data-tag="scikit-learn">Scikit-learn</button>
173+
174+
<button class="tag filter-tag" data-tag="streamlit">Streamlit</button>
175+
176+
<button class="tag filter-tag" data-tag="tensorboard">TensorBoard</button>
177+
178+
<button class="tag filter-tag" data-tag="weights &amp; biases">Weights &amp; Biases</button>
179+
180+
<button class="tag filter-tag" data-tag="yfinancetools">YFinanceTools</button>
181+
182+
<button class="tag filter-tag" data-tag="google-generativeai">google-generativeai</button>
183+
184+
<button class="tag filter-tag" data-tag="python-dotenv">python-dotenv</button>
185+
186+
<button class="tag filter-tag" data-tag="torchvision">torchvision</button>
187+
188+
</div>
189+
</div>
100190

101191
<!-- blogs -->
102192
<div id="blog-posts-container">
@@ -397,8 +487,11 @@ <h2 class="section-heading">Filter by Technology</h2>
397487
<script>
398488
document.addEventListener('DOMContentLoaded', function () {
399489
const tagContainer = document.getElementById('tag-filter-container');
490+
const mobileTagContainer = document.getElementById('mobile-tag-filter-container');
400491
const blogPosts = Array.from(document.querySelectorAll('.blog-post'));
401492
const loadMoreBtn = document.getElementById('load-more-btn');
493+
const mobileFilterToggle = document.getElementById('mobile-filter-toggle');
494+
const mobileFilterPanel = document.getElementById('mobile-filter-panel');
402495

403496
let currentMax = 5;
404497
const POSTS_PER_PAGE = 5;
@@ -432,20 +525,51 @@ <h2 class="section-heading">Filter by Technology</h2>
432525
}
433526
}
434527

528+
// Sync active state across both filter containers
529+
function syncFilterState(clickedTag, sourceContainer) {
530+
const allContainers = [tagContainer, mobileTagContainer].filter(Boolean);
531+
const selectedTag = clickedTag.getAttribute('data-tag').toLowerCase();
532+
533+
allContainers.forEach(container => {
534+
container.querySelectorAll('.filter-tag').forEach(btn => {
535+
btn.classList.remove('active');
536+
if (btn.getAttribute('data-tag').toLowerCase() === selectedTag) {
537+
btn.classList.add('active');
538+
}
539+
});
540+
});
541+
542+
currentFilter = selectedTag;
543+
currentMax = POSTS_PER_PAGE;
544+
updatePostsDisplay();
545+
}
546+
547+
// Desktop sidebar filter
435548
if (tagContainer) {
436549
tagContainer.addEventListener('click', function (e) {
437550
if (e.target.matches('.filter-tag')) {
438-
// Update the active button style
439-
tagContainer.querySelectorAll('.filter-tag').forEach(btn => btn.classList.remove('active'));
440-
e.target.classList.add('active');
551+
syncFilterState(e.target, tagContainer);
552+
}
553+
});
554+
}
441555

442-
currentFilter = e.target.getAttribute('data-tag').toLowerCase();
443-
currentMax = POSTS_PER_PAGE; // Reset max matches when filter changes
444-
updatePostsDisplay();
556+
// Mobile filter dropdown
557+
if (mobileTagContainer) {
558+
mobileTagContainer.addEventListener('click', function (e) {
559+
if (e.target.matches('.filter-tag')) {
560+
syncFilterState(e.target, mobileTagContainer);
445561
}
446562
});
447563
}
448564

565+
// Mobile filter toggle button
566+
if (mobileFilterToggle && mobileFilterPanel) {
567+
mobileFilterToggle.addEventListener('click', function () {
568+
const isOpen = mobileFilterPanel.classList.toggle('open');
569+
mobileFilterToggle.classList.toggle('active', isOpen);
570+
});
571+
}
572+
449573
if (loadMoreBtn) {
450574
loadMoreBtn.addEventListener('click', function () {
451575
currentMax += POSTS_PER_PAGE;
@@ -458,7 +582,7 @@ <h2 class="section-heading">Filter by Technology</h2>
458582
});
459583
</script>
460584
<style>
461-
/* Add some basic styling for the active button */
585+
/* ===== Filter Tag Base Styles ===== */
462586
.filter-tag {
463587
cursor: pointer;
464588
border: 1px solid transparent;
@@ -467,27 +591,20 @@ <h2 class="section-heading">Filter by Technology</h2>
467591
.filter-tag.active {
468592
border-color: var(--link-color, #0077cc);
469593
background-color: #cceeff;
470-
/* A light blue to indicate selection */
471594
color: #000;
472595
}
473596

474-
/* Add these new rules to the <style> block at the bottom */
475-
476-
/* Target the container to stack the buttons vertically */
597+
/* Desktop sidebar filter layout */
477598
#tag-filter-container {
478599
display: flex;
479600
flex-direction: column;
480-
/* This is the key change */
481601
gap: 0.5rem;
482-
/* Adds space between the stacked buttons */
483602
}
484603

485-
/* Make the buttons full-width and aligned left */
486604
#tag-filter-container .filter-tag {
487605
width: 100%;
488606
text-align: left;
489607
margin-right: 0;
490-
/* Remove the old horizontal margin */
491608
}
492609

493610
/* Load more button styles */
@@ -507,6 +624,109 @@ <h2 class="section-heading">Filter by Technology</h2>
507624
background-color: var(--link-color, #0077cc);
508625
color: #fff;
509626
}
627+
628+
/* ===== Blog Heading Row ===== */
629+
.blog-heading-row {
630+
display: flex;
631+
align-items: center;
632+
justify-content: space-between;
633+
gap: 1rem;
634+
}
635+
636+
.blog-heading-row .section-heading {
637+
flex: 1;
638+
margin-bottom: 0;
639+
}
640+
641+
/* ===== Mobile Filter Toggle Button ===== */
642+
.mobile-filter-toggle {
643+
display: none;
644+
/* Hidden by default on desktop */
645+
}
646+
647+
/* ===== Mobile Filter Panel ===== */
648+
.mobile-filter-panel {
649+
display: none;
650+
/* Hidden by default */
651+
}
652+
653+
/* ===== Mobile / Tablet: show filter button, hide sidebar ===== */
654+
@media (max-width: 48rem) {
655+
656+
/* Hide the desktop sidebar completely on mobile */
657+
aside {
658+
display: none !important;
659+
}
660+
661+
/* Show the mobile filter toggle button */
662+
.mobile-filter-toggle {
663+
display: inline-flex;
664+
align-items: center;
665+
gap: 0.4rem;
666+
padding: 8px 14px;
667+
border: 1px solid var(--border-color);
668+
border-radius: 6px;
669+
background-color: var(--card-bg-color);
670+
color: var(--text-color);
671+
font-size: 0.9rem;
672+
font-weight: 600;
673+
cursor: pointer;
674+
transition: all 0.2s ease;
675+
flex-shrink: 0;
676+
font-family: inherit;
677+
}
678+
679+
.mobile-filter-toggle i {
680+
font-size: 0.85rem;
681+
color: var(--link-color);
682+
}
683+
684+
.mobile-filter-toggle:hover,
685+
.mobile-filter-toggle.active {
686+
border-color: var(--link-color);
687+
color: var(--link-color);
688+
}
689+
690+
/* Mobile filter panel (dropdown) */
691+
.mobile-filter-panel {
692+
display: none;
693+
/* Still hidden until .open is added */
694+
}
695+
696+
.mobile-filter-panel.open {
697+
display: block;
698+
margin-bottom: 1.5rem;
699+
padding: 1rem;
700+
background-color: var(--card-bg-color);
701+
border: 1px solid var(--border-color);
702+
border-radius: 8px;
703+
animation: filterSlideDown 0.25s ease-out;
704+
}
705+
706+
@keyframes filterSlideDown {
707+
from {
708+
opacity: 0;
709+
transform: translateY(-8px);
710+
}
711+
712+
to {
713+
opacity: 1;
714+
transform: translateY(0);
715+
}
716+
}
717+
718+
/* Mobile tag container: horizontal wrap layout */
719+
.mobile-tag-container {
720+
display: flex;
721+
flex-wrap: wrap;
722+
gap: 0.5rem;
723+
}
724+
725+
.mobile-tag-container .filter-tag {
726+
font-size: 0.85rem;
727+
padding: 4px 10px;
728+
}
729+
}
510730
</style>
511731

512732
</footer>

0 commit comments

Comments
 (0)