Skip to content

Commit 9c52e8c

Browse files
committed
add video link support to projects and automate conversion of image assets to WebP format
1 parent ee4356c commit 9c52e8c

10 files changed

+88
-16
lines changed

css/main.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ section {
171171
.page-header,
172172
.page-footer {
173173
background-color: var(--header-footer-bg-color);
174+
174175
color: var(--text-color);
175176
/* This ensures text in header/footer also changes color */
176177
border-color: var(--border-color);

css/post-layout.css

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,23 +268,45 @@ html[data-theme='dark'] .post-sidebar-right::-webkit-scrollbar-thumb {
268268

269269
/* ===== Mobile breakpoint ===== */
270270
@media (max-width: 48rem) {
271+
.page-content {
272+
overflow-x: hidden;
273+
}
274+
271275
.post-layout {
272276
max-width: 100% !important;
277+
width: 100% !important;
273278
padding: 0 1rem !important;
279+
min-width: 0;
280+
box-sizing: border-box;
281+
overflow-x: hidden;
274282
}
275283

276284
.post-center-column {
277285
max-width: 100%;
286+
min-width: 0;
278287
overflow-x: hidden;
279288
}
280289

281290
.post-content-main {
282291
padding: 1rem 0 0 0 !important;
292+
max-width: 100%;
293+
min-width: 0;
294+
overflow-x: hidden;
295+
word-wrap: break-word;
296+
overflow-wrap: break-word;
283297
}
284298

285-
.post-content-main pre {
299+
.post-content-main pre,
300+
.code-block-wrapper {
286301
max-width: 100%;
287302
overflow-x: auto;
303+
box-sizing: border-box;
304+
}
305+
306+
.post-content-main p > code,
307+
.post-content-main li > code {
308+
word-break: break-word;
309+
white-space: pre-wrap;
288310
}
289311

290312
.post-content-main img {

css/projects.css

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,3 +134,20 @@ body.dark .tech-icons img {
134134
.project-button.blog-link:hover {
135135
filter: brightness(1.1);
136136
}
137+
138+
.project-button.video-link {
139+
width: 42px;
140+
height: 42px;
141+
border-radius: 50%;
142+
padding: 0;
143+
display: flex;
144+
align-items: center;
145+
justify-content: center;
146+
border: 2px solid var(--link-color);
147+
font-size: 1.2rem;
148+
flex-shrink: 0;
149+
}
150+
151+
.project-button.video-link i {
152+
margin-left: 3px;
153+
}

generate_portfolio_modified.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,9 @@ def strip_html_tags(text):
7676
"summary": project.get("summary", {}).get("project_card", ""),
7777
"technologies": project.get("core_technologies", []),
7878
"github_url": project.get("github_url", ""),
79-
"live_demo_url": None,
79+
"live_demo_url": project.get("live_demo_url", None),
80+
"video_url": project.get("video_url", ""),
81+
"video_exists": project.get("video_exists", False),
8082
})
8183
data["featured_projects"] = featured_projects
8284

@@ -174,6 +176,9 @@ def strip_html_tags(text):
174176
if md_filepath.exists():
175177
with md_filepath.open("r", encoding="utf-8") as f:
176178
markdown_content = f.read()
179+
180+
markdown_content = re.sub(r'\.(png|jpe?g)(?=[)""\'\s>])', '.webp', markdown_content, flags=re.IGNORECASE)
181+
177182
post["detailed_content"] = markdown2.markdown(
178183
markdown_content, extras=["fenced-code-blocks", "code-friendly"]
179184
)

portfolio.json

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,8 @@
355355
"image": "project_images/network_security_architecture_thumbnail.jpg",
356356
"featured": true,
357357
"show_in_resume": true,
358+
"video_exists": false,
359+
"video_url": "",
358360
"core_technologies": [
359361
"Python",
360362
"AWS",
@@ -416,7 +418,8 @@
416418
],
417419
"previous_part_slug": "from-messy-data-to-production-mlops-my-network-security-journey-part-1"
418420
}
419-
] },
421+
]
422+
},
420423
"end-to-end-foodvision-mlops-pipeline": {
421424
"title": "End-to-End FoodVision MLOps Pipeline",
422425
"github_url": "https://github.com/GoJo-Rika/PyTorch-FoodVision-Mini",
@@ -427,6 +430,8 @@
427430
"image": "project_images/effnet-feature-extraction-diagram.png",
428431
"featured": true,
429432
"show_in_resume": true,
433+
"video_exists": false,
434+
"video_url": "",
430435
"core_technologies": [
431436
"PyTorch",
432437
"FastAPI",
@@ -492,6 +497,8 @@
492497
"image": "tech_icons/aws-sagemaker.svg",
493498
"featured": true,
494499
"show_in_resume": true,
500+
"video_exists": false,
501+
"video_url": "",
495502
"core_technologies": [
496503
"AWS SageMaker",
497504
"Scikit-learn",
@@ -562,6 +569,8 @@
562569
"image": "tech_icons/hugging-face.svg",
563570
"featured": true,
564571
"show_in_resume": true,
572+
"video_exists": false,
573+
"video_url": "",
565574
"core_technologies": [
566575
"HuggingFace Transformers",
567576
"PyTorch",
@@ -663,6 +672,8 @@
663672
"image": "posts_assets/pipeline_workflow_diagram.png",
664673
"featured": true,
665674
"show_in_resume": true,
675+
"video_exists": false,
676+
"video_url": "",
666677
"core_technologies": [
667678
"AWS",
668679
"Python",
@@ -723,6 +734,8 @@
723734
"image": "project_images/financial-ai.jpg",
724735
"featured": true,
725736
"show_in_resume": true,
737+
"video_exists": false,
738+
"video_url": "",
726739
"core_technologies": [
727740
"Python",
728741
"Agno",
@@ -767,6 +780,8 @@
767780
"image": "project_images/video-summarizer-thumbnail.png",
768781
"featured": true,
769782
"show_in_resume": true,
783+
"video_exists": false,
784+
"video_url": "",
770785
"core_technologies": [
771786
"Python",
772787
"Streamlit",
@@ -836,6 +851,8 @@
836851
"image": "",
837852
"featured": false,
838853
"show_in_resume": true,
854+
"video_exists": false,
855+
"video_url": "",
839856
"core_technologies": [
840857
"AWS Bedrock",
841858
"AWS Lambda",
@@ -868,6 +885,8 @@
868885
"image": "",
869886
"featured": false,
870887
"show_in_resume": true,
888+
"video_exists": false,
889+
"video_url": "",
871890
"core_technologies": [
872891
"Python",
873892
"Agno",
@@ -895,6 +914,8 @@
895914
"image": "",
896915
"featured": false,
897916
"show_in_resume": true,
917+
"video_exists": false,
918+
"video_url": "",
898919
"core_technologies": [
899920
"Python",
900921
"LangChain",
@@ -912,7 +933,8 @@
912933
"Document Processing",
913934
"Semantic Search"
914935
],
915-
"blogs": [] }
936+
"blogs": []
937+
}
916938
},
917939
"volunteer_experience": [],
918940
"references": [],

posts/from-messy-data-to-production-mlops-my-network-security-journey-part-1.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ <h1>Building a Bulletproof ML Pipeline: The Unseen Engineering (Part 1)</h1>
8989

9090
<p>This is the story of building a production-ready machine learning system that detects phishing URLs. In this first part, we'll focus on laying a robust foundation: designing a modular architecture, implementing crucial safeguards like custom logging and data validation, and establishing a reproducible experiment-driven workflow.</p>
9191

92-
<p><img src="posts_assets/pipeline_workflow_diagram.png" alt="A diagram showing the MLOps pipeline flow from Data Ingestion to Model Pusher." /></p>
92+
<p><img src="posts_assets/pipeline_workflow_diagram.webp" alt="A diagram showing the MLOps pipeline flow from Data Ingestion to Model Pusher." /></p>
9393

9494
<h2>The Vision: More Than Just Another ML Project</h2>
9595

posts/from-messy-data-to-production-mlops-my-network-security-journey-part-2.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ <h1>The Deployment Gauntlet: From <code>localhost</code> to Live on AWS (Part 2)
8989

9090
<p>This is where theory meets the harsh, humbling reality of production infrastructure. This is the story of the deployment gauntlet.</p>
9191

92-
<p><img src="posts_assets/network-architecture-diagram.jpg" alt="A diagram showing the overall project architecture including AWS services, MLflow, and the FastAPI application." /></p>
92+
<p><img src="posts_assets/network-architecture-diagram.webp" alt="A diagram showing the overall project architecture including AWS services, MLflow, and the FastAPI application." /></p>
9393

9494
<h2>The AWS Deployment Nightmare: When the Cloud Humbles You</h2>
9595

posts/from-notebook-to-ui-the-local-development-journey-part-1.html

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ <h3>The First Big Question: Is My Model Actually Any Good?</h3>
9696
<p><strong>Problem #1: My experiments were chaotic and biased.</strong>
9797
My first attempt at a solution was to bring order to the chaos. I wrote a nested loop to systematically iterate through every combination of model (<code>EfficientNetB0</code>, <code>B2</code>, <code>B4</code>), dataset size, and training duration.</p>
9898

99-
<p><img src="posts_assets/experiments-table.png" alt="A table showing the structured plan for all 8 experiments, varying model type, data size, and epochs." />
99+
<p><img src="posts_assets/experiments-table.webp" alt="A table showing the structured plan for all 8 experiments, varying model type, data size, and epochs." />
100100
<em>Moving from random tweaks to a structured experiment plan like this was the first step toward building a reliable model.</em></p>
101101

102102
<p>This was a huge step forward! But it created a new problem: I was drowning in a sea of <code>print()</code> statements. Comparing the results of run #3 with run #17 was a nightmare of scrolling and squinting.</p>
@@ -111,7 +111,7 @@ <h3>The First Big Question: Is My Model Actually Any Good?</h3>
111111
<p><strong>Problem #2: I couldn't visualize the story of my training.</strong>
112112
I realized I didn't just need results; I needed a narrative. I needed to see the learning curves to understand <em>how</em> each model was behaving. This is where TensorBoard came in. But my first attempt was, again, a mess. All my logs were jumbled into one confusing timeline.</p>
113113

114-
<p><img src="posts_assets/tensorboard-accuracy-chart.png" alt="A screenshot of the TensorBoard dashboard showing accuracy curves for multiple experiments." />
114+
<p><img src="posts_assets/tensorboard-accuracy-chart.webp" alt="A screenshot of the TensorBoard dashboard showing accuracy curves for multiple experiments." />
115115
<em>TensorBoard made it easy to visually compare all eight experiments. The superiority of the <code>EffNetB2</code> model trained on 20% of the data (the top-performing line) became immediately obvious.</em></p>
116116

117117
<p>The insight wasn't just to <em>use</em> TensorBoard, but to be deliberate about <em>how</em> I organized my logs. I wrote a small utility function to create a clean, timestamped directory structure for every single run, which made the above visualization possible.</p>
@@ -129,15 +129,15 @@ <h3>The Second Big Question: How Do I Squeeze Out More Performance?</h3>
129129

130130
<p>My experiments were now reliable, but the best model's accuracy was still just "okay." I knew the answer was <strong>Transfer Learning</strong>, but I soon learned that knowing the name of a technique is very different from implementing it correctly.</p>
131131

132-
<p><img src="posts_assets/feature-extraction-diagram.png" alt="A diagram showing a large pre-trained model being adapted for a new, smaller task." />
132+
<p><img src="posts_assets/feature-extraction-diagram.webp" alt="A diagram showing a large pre-trained model being adapted for a new, smaller task." />
133133
<em>The core concept of feature extraction: keep the pre-trained 'backbone' (the feature learner) and only train a new, small 'head' (the classifier) on our specific data.</em></p>
134134

135135
<p><strong>Problem #3: My GPU was crying and my training was slow.</strong>
136136
My first attempt was naive. I loaded a pre-trained <code>EfficientNet</code>, swapped the final layer for my 3-class classifier, and hit "train." My GPU fan spun up like a jet engine, and the estimated training time was in hours, not minutes.</p>
137137

138138
<p>The "aha!" moment came after digging into how transfer learning truly works. I was trying to retrain the entire network. The solution was to <strong>freeze the backbone</strong>.</p>
139139

140-
<p><img src="posts_assets/torchinfo-frozen-layers.png" alt="A screenshot of the torchinfo summary showing a massive reduction in trainable parameters." />
140+
<p><img src="posts_assets/torchinfo-frozen-layers.webp" alt="A screenshot of the torchinfo summary showing a massive reduction in trainable parameters." />
141141
<em>The proof is in the numbers. After freezing the backbone, the number of trainable parameters dropped from over 4 million to just 3,843, dramatically speeding up training.</em></p>
142142

143143
<pre><code># The crucial insight: only train the tiny new part of the model

projects_template.html

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,11 @@ <h3 class="project-title">{{ project.title }}</h3>
9494
<a href="{{ project.github_url }}" class="project-button" target="_blank"
9595
rel="noopener noreferrer">View on GitHub</a>
9696
{% endif %}
97+
{% if project.video_exists and project.video_url %}
98+
<a href="{{ project.video_url }}" class="project-button video-link" target="_blank" rel="noopener noreferrer" title="Watch Video">
99+
<i class="fa-solid fa-play"></i>
100+
</a>
101+
{% endif %}
97102
{% if project.blog_slug %}
98103
<a href="posts/{{ project.blog_slug }}.html" class="project-button blog-link">Read
99104
the Story</a>

sitemap.xml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,37 +2,37 @@
22
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
33
<url>
44
<loc>https://gojo-rika.github.io/</loc>
5-
<lastmod>2026-04-04</lastmod>
5+
<lastmod>2026-04-11</lastmod>
66
<changefreq>monthly</changefreq>
77
<priority>1.0</priority>
88
</url>
99
<url>
1010
<loc>https://gojo-rika.github.io/resume.html</loc>
11-
<lastmod>2026-04-04</lastmod>
11+
<lastmod>2026-04-11</lastmod>
1212
<changefreq>monthly</changefreq>
1313
<priority>0.8</priority>
1414
</url>
1515
<url>
1616
<loc>https://gojo-rika.github.io/projects.html</loc>
17-
<lastmod>2026-04-04</lastmod>
17+
<lastmod>2026-04-11</lastmod>
1818
<changefreq>monthly</changefreq>
1919
<priority>0.8</priority>
2020
</url>
2121
<url>
2222
<loc>https://gojo-rika.github.io/blog.html</loc>
23-
<lastmod>2026-04-04</lastmod>
23+
<lastmod>2026-04-11</lastmod>
2424
<changefreq>weekly</changefreq>
2525
<priority>0.9</priority>
2626
</url>
2727
<url>
2828
<loc>https://gojo-rika.github.io/contact.html</loc>
29-
<lastmod>2026-04-04</lastmod>
29+
<lastmod>2026-04-11</lastmod>
3030
<changefreq>yearly</changefreq>
3131
<priority>0.6</priority>
3232
</url>
3333
<url>
3434
<loc>https://gojo-rika.github.io/tech-stack.html</loc>
35-
<lastmod>2026-04-04</lastmod>
35+
<lastmod>2026-04-11</lastmod>
3636
<changefreq>monthly</changefreq>
3737
<priority>0.7</priority>
3838
</url>

0 commit comments

Comments
 (0)