Skip to content

Commit ee4356c

Browse files
committed
improve project-blog association logic and optimize metadata display across templates and posts.
1 parent fb750f7 commit ee4356c

13 files changed

Lines changed: 100 additions & 254 deletions

blog.html

Lines changed: 8 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -87,28 +87,20 @@ <h2 class="section-heading">
8787
<button class="tag filter-tag active" data-tag="all">Show All</button>
8888
<button class="tag filter-tag" data-tag="aws">AWS</button>
8989
<button class="tag filter-tag" data-tag="aws ec2">AWS EC2</button>
90-
<button class="tag filter-tag" data-tag="aws ecr">AWS ECR</button>
9190
<button class="tag filter-tag" data-tag="aws elastic beanstalk">AWS Elastic Beanstalk</button>
9291
<button class="tag filter-tag" data-tag="aws s3">AWS S3</button>
9392
<button class="tag filter-tag" data-tag="aws sagemaker">AWS SageMaker</button>
94-
<button class="tag filter-tag" data-tag="agentic ai">Agentic AI</button>
9593
<button class="tag filter-tag" data-tag="agno">Agno</button>
9694
<button class="tag filter-tag" data-tag="cloudwatch">CloudWatch</button>
97-
<button class="tag filter-tag" data-tag="dagshub">Dagshub</button>
9895
<button class="tag filter-tag" data-tag="docker">Docker</button>
99-
<button class="tag filter-tag" data-tag="duckduckgo api">DuckDuckGo API</button>
100-
<button class="tag filter-tag" data-tag="duckduckgotools">DuckDuckGoTools</button>
10196
<button class="tag filter-tag" data-tag="fastapi">FastAPI</button>
10297
<button class="tag filter-tag" data-tag="flask">Flask</button>
10398
<button class="tag filter-tag" data-tag="github actions">GitHub Actions</button>
104-
<button class="tag filter-tag" data-tag="google api">Google API</button>
10599
<button class="tag filter-tag" data-tag="google gemini">Google Gemini</button>
106100
<button class="tag filter-tag" data-tag="groq">Groq</button>
107101
<button class="tag filter-tag" data-tag="huggingface transformers">HuggingFace Transformers</button>
108102
<button class="tag filter-tag" data-tag="mlops">MLOps</button>
109103
<button class="tag filter-tag" data-tag="mlflow">MLflow</button>
110-
<button class="tag filter-tag" data-tag="mongodb">MongoDB</button>
111-
<button class="tag filter-tag" data-tag="multi-agent systems">Multi-Agent Systems</button>
112104
<button class="tag filter-tag" data-tag="nlp">NLP</button>
113105
<button class="tag filter-tag" data-tag="numpy">NumPy</button>
114106
<button class="tag filter-tag" data-tag="pandas">Pandas</button>
@@ -118,16 +110,14 @@ <h2 class="section-heading">
118110
<button class="tag filter-tag" data-tag="streamlit">Streamlit</button>
119111
<button class="tag filter-tag" data-tag="tensorboard">TensorBoard</button>
120112
<button class="tag filter-tag" data-tag="weights &amp; biases">Weights &amp; Biases</button>
121-
<button class="tag filter-tag" data-tag="yfinancetools">YFinanceTools</button>
122-
<button class="tag filter-tag" data-tag="google-generativeai">google-generativeai</button>
123-
<button class="tag filter-tag" data-tag="python-dotenv">python-dotenv</button>
113+
<button class="tag filter-tag" data-tag="yfinance">YFinance</button>
124114
<button class="tag filter-tag" data-tag="torchvision">torchvision</button>
125115
</div>
126116
</div>
127117

128118
<!-- Blog post cards -->
129119
<div id="blog-posts-container">
130-
<article class="blog-post" data-tags="python,streamlit,agno,google gemini,duckduckgo api,google-generativeai,python-dotenv">
120+
<article class="blog-post" data-tags="python,streamlit,google gemini,agno">
131121
<h3 class="post-meta">
132122
<a href="posts/building-an-intelligent-video-analyst-crafting-the-agents-brain-part-2.html">Building an Intelligent Video Analyst: Crafting the Agent&#39;s Brain (Part 2)</a>
133123
</h3>
@@ -136,7 +126,7 @@ <h3 class="post-meta">
136126
<div class="tech-stack">
137127
</div>
138128
</article>
139-
<article class="blog-post" data-tags="python,streamlit,agno,google gemini,duckduckgo api,google-generativeai,python-dotenv">
129+
<article class="blog-post" data-tags="python,streamlit,google gemini,agno">
140130
<h3 class="post-meta">
141131
<a href="posts/building-an-intelligent-video-analyst-the-foundational-pipeline-part-1.html">Building an Intelligent Video Analyst: The Foundational Pipeline (Part 1)</a>
142132
</h3>
@@ -145,7 +135,7 @@ <h3 class="post-meta">
145135
<div class="tech-stack">
146136
</div>
147137
</article>
148-
<article class="blog-post" data-tags="python,agno,groq,agentic ai,multi-agent systems,fastapi,duckduckgotools,yfinancetools,google api">
138+
<article class="blog-post" data-tags="python,agno,groq,fastapi,yfinance">
149139
<h3 class="post-meta">
150140
<a href="posts/multi-agent-chaos-when-ai-agents-wouldnt-cooperate.html">Multi-Agent Chaos: When AI Agents Wouldn&#39;t Cooperate</a>
151141
</h3>
@@ -190,7 +180,7 @@ <h3 class="post-meta">
190180
<div class="tech-stack">
191181
</div>
192182
</article>
193-
<article class="blog-post" data-tags="aws,aws sagemaker,scikit-learn,aws s3,python,mlops,cloudwatch">
183+
<article class="blog-post" data-tags="aws sagemaker,scikit-learn,aws s3,python,mlops,cloudwatch,aws">
194184
<h3 class="post-meta">
195185
<a href="posts/when-sagemaker-humbled-me-a-cloud-native-ml-reality-check.html">When SageMaker Humbled Me: A Cloud-Native ML Reality Check</a>
196186
</h3>
@@ -217,7 +207,7 @@ <h3 class="post-meta">
217207
<div class="tech-stack">
218208
</div>
219209
</article>
220-
<article class="blog-post" data-tags="python,mlflow,dagshub,aws ec2,aws ecr,aws s3,scikit-learn,mongodb,fastapi,docker,github actions">
210+
<article class="blog-post" data-tags="python,aws,docker,fastapi,scikit-learn,mlflow,github actions">
221211
<h3 class="post-meta">
222212
<a href="posts/from-messy-data-to-production-mlops-my-network-security-journey-part-2.html">From Messy Data to Production MLOps: My Network Security Journey (Part 2)</a>
223213
</h3>
@@ -226,7 +216,7 @@ <h3 class="post-meta">
226216
<div class="tech-stack">
227217
</div>
228218
</article>
229-
<article class="blog-post" data-tags="python,mlflow,dagshub,aws ec2,aws ecr,aws s3,scikit-learn,mongodb,fastapi,docker,github actions">
219+
<article class="blog-post" data-tags="python,aws,docker,fastapi,scikit-learn,mlflow,github actions">
230220
<h3 class="post-meta">
231221
<a href="posts/from-messy-data-to-production-mlops-my-network-security-journey-part-1.html">From Messy Data to Production MLOps: My Network Security Journey (Part 1)</a>
232222
</h3>
@@ -251,28 +241,20 @@ <h2 class="section-heading">Filter by Technology</h2>
251241
<button class="tag filter-tag active" data-tag="all">Show All</button>
252242
<button class="tag filter-tag" data-tag="aws">AWS</button>
253243
<button class="tag filter-tag" data-tag="aws ec2">AWS EC2</button>
254-
<button class="tag filter-tag" data-tag="aws ecr">AWS ECR</button>
255244
<button class="tag filter-tag" data-tag="aws elastic beanstalk">AWS Elastic Beanstalk</button>
256245
<button class="tag filter-tag" data-tag="aws s3">AWS S3</button>
257246
<button class="tag filter-tag" data-tag="aws sagemaker">AWS SageMaker</button>
258-
<button class="tag filter-tag" data-tag="agentic ai">Agentic AI</button>
259247
<button class="tag filter-tag" data-tag="agno">Agno</button>
260248
<button class="tag filter-tag" data-tag="cloudwatch">CloudWatch</button>
261-
<button class="tag filter-tag" data-tag="dagshub">Dagshub</button>
262249
<button class="tag filter-tag" data-tag="docker">Docker</button>
263-
<button class="tag filter-tag" data-tag="duckduckgo api">DuckDuckGo API</button>
264-
<button class="tag filter-tag" data-tag="duckduckgotools">DuckDuckGoTools</button>
265250
<button class="tag filter-tag" data-tag="fastapi">FastAPI</button>
266251
<button class="tag filter-tag" data-tag="flask">Flask</button>
267252
<button class="tag filter-tag" data-tag="github actions">GitHub Actions</button>
268-
<button class="tag filter-tag" data-tag="google api">Google API</button>
269253
<button class="tag filter-tag" data-tag="google gemini">Google Gemini</button>
270254
<button class="tag filter-tag" data-tag="groq">Groq</button>
271255
<button class="tag filter-tag" data-tag="huggingface transformers">HuggingFace Transformers</button>
272256
<button class="tag filter-tag" data-tag="mlops">MLOps</button>
273257
<button class="tag filter-tag" data-tag="mlflow">MLflow</button>
274-
<button class="tag filter-tag" data-tag="mongodb">MongoDB</button>
275-
<button class="tag filter-tag" data-tag="multi-agent systems">Multi-Agent Systems</button>
276258
<button class="tag filter-tag" data-tag="nlp">NLP</button>
277259
<button class="tag filter-tag" data-tag="numpy">NumPy</button>
278260
<button class="tag filter-tag" data-tag="pandas">Pandas</button>
@@ -282,9 +264,7 @@ <h2 class="section-heading">Filter by Technology</h2>
282264
<button class="tag filter-tag" data-tag="streamlit">Streamlit</button>
283265
<button class="tag filter-tag" data-tag="tensorboard">TensorBoard</button>
284266
<button class="tag filter-tag" data-tag="weights &amp; biases">Weights &amp; Biases</button>
285-
<button class="tag filter-tag" data-tag="yfinancetools">YFinanceTools</button>
286-
<button class="tag filter-tag" data-tag="google-generativeai">google-generativeai</button>
287-
<button class="tag filter-tag" data-tag="python-dotenv">python-dotenv</button>
267+
<button class="tag filter-tag" data-tag="yfinance">YFinance</button>
288268
<button class="tag filter-tag" data-tag="torchvision">torchvision</button>
289269
</div>
290270
</section>

css/post.css

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,11 @@
5252
font-family: 'Courier New', Courier, monospace;
5353
font-size: 0.9em;
5454
line-height: 1.5;
55+
margin: 0;
56+
}
57+
58+
.code-block-wrapper {
5559
margin: 1.5em 0;
56-
position: relative !important;
57-
/* Must stay relative for the copy button to anchor */
5860
}
5961

6062
.post-content-main pre code {
@@ -142,7 +144,7 @@ aside .tech-stack {
142144
}
143145

144146
/* ===== CUSTOM COPY-TO-CLIPBOARD BUTTON STYLING ===== */
145-
.post-content-main pre>.copy-code-btn {
147+
.code-block-wrapper>.copy-code-btn {
146148
position: absolute !important;
147149
top: 0.5rem !important;
148150
right: 0.5rem !important;
@@ -162,15 +164,15 @@ aside .tech-stack {
162164
z-index: 10;
163165
}
164166

165-
.post-content-main pre:hover>.copy-code-btn {
167+
.code-block-wrapper:hover>.copy-code-btn {
166168
opacity: 1;
167169
}
168170

169-
.post-content-main pre>.copy-code-btn:hover {
171+
.code-block-wrapper>.copy-code-btn:hover {
170172
background-color: rgba(128, 128, 128, 0.3);
171173
}
172174

173-
.post-content-main pre>.copy-code-btn.copied {
175+
.code-block-wrapper>.copy-code-btn.copied {
174176
color: var(--link-color);
175177
opacity: 1;
176178
}

generate_portfolio_modified.py

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,11 @@ def strip_html_tags(text):
6060
all_blogs = []
6161
for project in projects_blog_db.values():
6262
github_url = project.get("github_url", "")
63+
parent_techs = project.get("core_technologies", [])
6364
for blog in project.get("blogs", []):
6465
blog["github_url"] = github_url
66+
blog["project_title"] = project["title"]
67+
blog["core_technologies"] = parent_techs
6568
all_blogs.append(blog)
6669

6770
featured_projects = []
@@ -79,15 +82,16 @@ def strip_html_tags(text):
7982

8083
projects_for_resume = []
8184
for project in projects_blog_db.values():
82-
projects_for_resume.append({
83-
"title": project["title"],
84-
"url": project.get("github_url", ""),
85-
"summary": project.get("summary", {}).get("resume_page", ""),
86-
"core_technologies": project.get("core_technologies", []),
87-
"keywords": project.get("keywords", []),
88-
"highlights": [],
89-
"images": [],
90-
})
85+
if project.get("show_in_resume", True):
86+
projects_for_resume.append({
87+
"title": project["title"],
88+
"url": project.get("github_url", ""),
89+
"summary": project.get("summary", {}).get("resume_page", ""),
90+
"core_technologies": project.get("core_technologies", []),
91+
"keywords": project.get("keywords", []),
92+
"highlights": [],
93+
"images": [],
94+
})
9195
data["projects"] = projects_for_resume
9296

9397
# ---------------------------------------------------------------------------
@@ -196,12 +200,10 @@ def strip_html_tags(text):
196200
# 8. Match featured projects to their starting blog post (Part 1)
197201
# ---------------------------------------------------------------------------
198202
for project in data.get("featured_projects", []):
199-
github_url = project.get("github_url")
200-
if github_url:
201-
for post in reversed(blog_posts):
202-
if post.get("github_url") == github_url and not post.get("previous_part_slug"):
203-
project["blog_slug"] = post["slug"]
204-
break
203+
for post in reversed(blog_posts):
204+
if post.get("project_title") == project["title"] and not post.get("previous_part_slug"):
205+
project["blog_slug"] = post["slug"]
206+
break
205207

206208
# ---------------------------------------------------------------------------
207209
# 9. Render all page templates

js/app.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,14 +58,23 @@ document.addEventListener('DOMContentLoaded', function () {
5858
document.body.appendChild(toast);
5959

6060
codeBlocks.forEach(block => {
61+
// Create a wrapper for the code block
62+
const wrapper = document.createElement('div');
63+
wrapper.className = 'code-block-wrapper';
64+
wrapper.style.position = 'relative';
65+
66+
// Insert wrapper before block, then move block inside wrapper
67+
block.parentNode.insertBefore(wrapper, block);
68+
wrapper.appendChild(block);
69+
6170
// Create the copy button using an icon
6271
const copyButton = document.createElement('button');
6372
copyButton.className = 'copy-code-btn';
6473
copyButton.innerHTML = '<i class="far fa-copy"></i>';
6574
copyButton.setAttribute('aria-label', 'Copy code to clipboard');
6675

67-
// Add the button to the pre block
68-
block.appendChild(copyButton);
76+
// Add the button to the wrapper instead of the pre block
77+
wrapper.appendChild(copyButton);
6978

7079
// Add the click event listener
7180
copyButton.addEventListener('click', () => {

js/search-index.js

Lines changed: 12 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,8 @@ const SEARCH_INDEX = [
77
"tags": [
88
"Python",
99
"Streamlit",
10-
"Agno",
1110
"Google Gemini",
12-
"DuckDuckGo API",
13-
"google-generativeai",
14-
"python-dotenv",
11+
"Agno",
1512
"Agentic AI",
1613
"Multimodal AI",
1714
"Generative AI",
@@ -32,11 +29,8 @@ const SEARCH_INDEX = [
3229
"tags": [
3330
"Python",
3431
"Streamlit",
35-
"Agno",
3632
"Google Gemini",
37-
"DuckDuckGo API",
38-
"google-generativeai",
39-
"python-dotenv",
33+
"Agno",
4034
"Agentic AI",
4135
"Multimodal AI",
4236
"Generative AI",
@@ -58,12 +52,8 @@ const SEARCH_INDEX = [
5852
"Python",
5953
"Agno",
6054
"Groq",
61-
"Agentic AI",
62-
"Multi-Agent Systems",
6355
"FastAPI",
64-
"DuckDuckGoTools",
65-
"YFinanceTools",
66-
"Google API",
56+
"YFinance",
6757
"Multi-Agent AI System",
6858
"Financial Analysis",
6959
"Stock Market",
@@ -187,14 +177,14 @@ const SEARCH_INDEX = [
187177
"date": "2025-09-15",
188178
"summary": "I thought taking a scikit-learn model to the cloud would be simple, but AWS SageMaker taught me more about cloud architecture and DevOps than I ever expected. This post details my entire journey, from battling IAM roles and structuring S3 buckets to mastering the SageMaker training patterns that finally bridged the gap between my local machine and a production-ready endpoint. It's a story of the struggles, the breakthroughs, and the hard-won lessons learned while building a real-world ML pipeline.",
189179
"tags": [
190-
"AWS",
191180
"AWS SageMaker",
192181
"Scikit-learn",
193182
"AWS S3",
194183
"Python",
195184
"MLOps",
196185
"CloudWatch",
197186
"AWS",
187+
"AWS",
198188
"Amazon SageMaker",
199189
"AWS S3",
200190
"IAM",
@@ -266,15 +256,11 @@ const SEARCH_INDEX = [
266256
"summary": "With a working local pipeline, the \"easy\" part was next: deployment. This turned into a multi-day AWS nightmare. After successfully automating the CI/CD pipeline with GitHub Actions, the app was live but unreachable. The culprit? A single, critical line of code related to container networking. This post dives into the humbling, real-world challenges of cloud infrastructure, debugging EC2 security groups, and the final \"aha!\" moment that brought the entire system online.",
267257
"tags": [
268258
"Python",
269-
"MLflow",
270-
"Dagshub",
271-
"AWS EC2",
272-
"AWS ECR",
273-
"AWS S3",
274-
"Scikit-learn",
275-
"MongoDB",
276-
"FastAPI",
259+
"AWS",
277260
"Docker",
261+
"FastAPI",
262+
"Scikit-learn",
263+
"MLflow",
278264
"GitHub Actions",
279265
"CI/CD automation",
280266
"Schema Validation",
@@ -295,15 +281,11 @@ const SEARCH_INDEX = [
295281
"summary": "My journey began with a classic MLOps mistake: underestimating messy data. My model worked locally, but I spent weeks debugging failures until a breakthrough came from implementing rigorous **data validation schemas** and **drift detection**. This post covers the foundational engineering\u2014modular architecture, custom logging, and experiment tracking\u2014that's essential *before* you even think about the cloud. It\u2019s the story of building a resilient pipeline from the ground up.",
296282
"tags": [
297283
"Python",
298-
"MLflow",
299-
"Dagshub",
300-
"AWS EC2",
301-
"AWS ECR",
302-
"AWS S3",
303-
"Scikit-learn",
304-
"MongoDB",
305-
"FastAPI",
284+
"AWS",
306285
"Docker",
286+
"FastAPI",
287+
"Scikit-learn",
288+
"MLflow",
307289
"GitHub Actions",
308290
"MLOps",
309291
"End-to-End ML Pipeline",

0 commit comments

Comments
 (0)