Missing Features
Missing Features
Deep analysis and implementation guide for adding valuable features not yet present on the site.
Table of Contents
- Client-Side Search
- RSS Feed Subscribe UI
- Reading Time Estimates
- Social Sharing Buttons
- Back-to-Top Enhancements
- Related Content Suggestions
- Project Filtering & Sorting
- Contact Form
- Sitemap Page
1. Client-Side Search
Why
The site has 8 portfolio items, 3 publications, 5 talks, and 7 blog posts. As content grows, visitors need a way to find specific topics. The _config.yml already has search: true but no implementation exists.
Implementation
See 04-content-ux.md Section 6 for the full Lunr.js implementation with:
- Search data JSON generation from all collections
- Fuzzy search with Lunr.js
- Lazy-loaded search index (only fetched on focus)
- Debounced input handling
- Results with collection type badges
Alternative: Simple filter search
If Lunr.js feels heavy, implement a simpler filter-based search:
// Lightweight search without Lunr.js dependency
// Filter visible items on archive pages
function initFilterSearch() {
const searchInput = document.getElementById('filter-input');
if (!searchInput) return;
const items = document.querySelectorAll('.archive__item');
searchInput.addEventListener('input', function() {
const query = this.value.toLowerCase().trim();
items.forEach(function(item) {
const title = item.querySelector('.archive__item-title');
const excerpt = item.querySelector('.archive__item-excerpt');
const tags = item.querySelectorAll('.archive__item-tag');
const text = [
title ? title.textContent : '',
excerpt ? excerpt.textContent : '',
Array.from(tags).map(t => t.textContent).join(' ')
].join(' ').toLowerCase();
item.style.display = text.includes(query) ? '' : 'none';
});
});
}
Add a filter input to archive pages:
<input type="search" id="filter-input"
placeholder="Filter projects..."
aria-label="Filter items"
autocomplete="off">
Trade-offs:
- Lunr.js: Full-text search, fuzzy matching, ranking, but adds ~8KB dependency
- Filter search: Zero dependencies, instant, but only matches visible text
2. RSS Feed Subscribe UI
Why
jekyll-feed generates /feed.xml but there’s no visible way for visitors to discover or subscribe to it. RSS is valuable for academic audiences who use feed readers.
Implementation
See 04-content-ux.md Section 5 for:
- Footer RSS icon
- Blog archive subscribe CTA
Additional: Add to masthead
For maximum visibility, add an RSS icon to the masthead utility buttons:
<!-- _includes/masthead.html - add alongside theme/lang toggles -->
<a href="/feed.xml" class="rss-link" aria-label="RSS Feed" title="RSS Feed">
<i class="fas fa-rss" aria-hidden="true"></i>
</a>
// _sass/_masthead.scss
.rss-link {
color: var(--color-text-light);
font-size: 0.9em;
padding: 0.35rem;
&:hover {
color: #f26522; // RSS orange
}
}
3. Reading Time Estimates
Current State
The _includes/read-time.html include exists and is used in blog post listings. However, it may not be visible on all content types.
Implementation
Ensure reading time is shown on:
- Blog post listings (archive pages)
- Individual blog post pages
- Publication pages (for the abstract/description)
<!-- _includes/read-time.html - verify this exists and is correct -->
Enable in _config.yml defaults if not already:
defaults:
- scope:
path: ""
type: posts
values:
read_time: true
4. Social Sharing Buttons
Current State
_includes/social-share.html exists in the includes directory. Check if it’s included in post layouts.
Implementation
Ensure social sharing is enabled on blog posts and publications:
# _config.yml - in defaults
defaults:
- scope:
path: ""
type: posts
values:
share: true
- scope:
path: ""
type: publications
values:
share: true
If the existing social-share.html is outdated, create a modern version:
<!-- _includes/social-share.html -->
// _sass/_page.scss or _utilities.scss
.page__share {
margin-top: 2rem;
padding-top: 1.5rem;
border-top: 1px solid var(--color-border);
}
.share-links {
display: flex;
gap: 0.75rem;
flex-wrap: wrap;
}
.share-link {
display: inline-flex;
align-items: center;
gap: 0.35rem;
padding: 0.4em 0.8em;
font-size: 0.85em;
border-radius: 0.35em;
text-decoration: none;
color: #fff;
transition: opacity 0.2s ease;
&:hover { opacity: 0.85; }
&--linkedin { background: #0077b5; }
&--twitter { background: #1da1f2; }
&--email { background: var(--color-text-light, #64748b); }
}
5. Back-to-Top Enhancements
Current State
A scroll-to-top button exists in _includes/footer.html with logic in _main.js. It appears after 300px of scrolling.
Enhancement
Add smooth scroll behavior and improve the button’s position/animation:
// _sass/_utilities.scss - enhance existing styles
.scroll-to-top {
position: fixed;
bottom: 1.5rem;
right: 1.5rem;
z-index: 50;
width: 2.5rem;
height: 2.5rem;
display: flex;
align-items: center;
justify-content: center;
background: var(--color-primary);
color: #fff;
border: none;
border-radius: 50%;
cursor: pointer;
opacity: 0;
visibility: hidden;
transform: translateY(1rem);
transition: opacity 0.3s ease, visibility 0.3s ease, transform 0.3s ease;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
&.is-visible {
opacity: 1;
visibility: visible;
transform: translateY(0);
}
&:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
}
&:active {
transform: translateY(0);
}
}
6. Related Content Suggestions
Why
When visitors finish reading a blog post or viewing a project, they have no guidance on what to explore next. Related content increases time on site and engagement.
Implementation
See 04-content-ux.md Section 7 for the full tag-based related posts implementation.
Cross-collection suggestions
For a more interesting approach, suggest content across collections:
<!-- _includes/explore-more.html -->
<div class="explore-more">
<h3>
<span class="lang-en">Explore More</span>
<span class="lang-es">Explorar Mas</span>
</h3>
<div class="explore-more__grid">
<!-- Show mix of recent content -->
<div class="grid__item">
<article class="archive__item" itemscope itemtype="http://schema.org/CreativeWork">
<div class="archive__item-body">
<h2 class="archive__item-title" itemprop="headline">
<a href="https://efrenrodriguezrodriguez.com" rel="permalink"></a>
</h2>
</div>
</article>
</div>
<div class="grid__item">
<article class="archive__item" itemscope itemtype="http://schema.org/CreativeWork">
<div class="archive__item-body">
<h2 class="archive__item-title" itemprop="headline">
<a href="https://efrenrodriguezrodriguez.com" rel="permalink"></a>
</h2>
</div>
</article>
</div>
</div>
</div>
7. Project Filtering & Sorting
Why
The portfolio page has 8 projects split between research and personal categories. As projects grow, filtering by category or technology becomes valuable.
Implementation
Category filter tabs
<!-- _pages/portfolio.html - add filter controls -->
<div class="portfolio-filters" role="tablist" aria-label="Filter projects">
<button class="filter-btn active" role="tab" aria-selected="true" data-filter="all">
<span class="lang-en">All</span>
<span class="lang-es">Todos</span>
</button>
<button class="filter-btn" role="tab" aria-selected="false" data-filter="research">
<span class="lang-en">Research</span>
<span class="lang-es">Investigacion</span>
</button>
<button class="filter-btn" role="tab" aria-selected="false" data-filter="personal">
<span class="lang-en">Personal</span>
<span class="lang-es">Personal</span>
</button>
</div>
Filter JavaScript
// Add to _main.js
function initPortfolioFilters() {
const buttons = document.querySelectorAll('.filter-btn');
const items = document.querySelectorAll('.archive__item');
if (!buttons.length || !items.length) return;
buttons.forEach(function(btn) {
btn.addEventListener('click', function() {
var filter = this.getAttribute('data-filter');
// Update active state
buttons.forEach(function(b) {
b.classList.remove('active');
b.setAttribute('aria-selected', 'false');
});
this.classList.add('active');
this.setAttribute('aria-selected', 'true');
// Filter items
items.forEach(function(item) {
if (filter === 'all') {
item.style.display = '';
return;
}
var category = item.getAttribute('data-category');
item.style.display = (category === filter) ? '' : 'none';
});
});
});
}
Add data attributes to portfolio items
In _includes/archive-single.html, add the category as a data attribute:
<article class="archive__item" data-category="other">
CSS for filter buttons
// _sass/_archive.scss
.portfolio-filters {
display: flex;
gap: 0.5rem;
margin-bottom: 2rem;
flex-wrap: wrap;
}
.filter-btn {
padding: 0.4em 1em;
border: 1px solid var(--color-border);
border-radius: 2em;
background: transparent;
color: var(--color-text-light);
cursor: pointer;
font-size: 0.85em;
font-weight: 500;
transition: all 0.2s ease;
&:hover {
border-color: var(--color-primary);
color: var(--color-primary);
}
&.active {
background: var(--color-primary);
border-color: var(--color-primary);
color: #fff;
}
}
8. Contact Form
Current State
File: _pages/contact.md
Check the current contact page structure. If it only lists email/social links, consider adding a contact form.
Implementation with Formspree (free tier)
<!-- _pages/contact.md - add contact form -->
<form action="https://formspree.io/f/YOUR_FORM_ID" method="POST" class="contact-form">
<div class="form-group">
<label for="name">
<span class="lang-en">Name</span>
<span class="lang-es">Nombre</span>
</label>
<input type="text" id="name" name="name" required
autocomplete="name">
</div>
<div class="form-group">
<label for="email">
<span class="lang-en">Email</span>
<span class="lang-es">Correo electronico</span>
</label>
<input type="email" id="email" name="_replyto" required
autocomplete="email">
</div>
<div class="form-group">
<label for="subject">
<span class="lang-en">Subject</span>
<span class="lang-es">Asunto</span>
</label>
<select id="subject" name="subject">
<option value="collaboration">Research Collaboration</option>
<option value="speaking">Speaking / Talks</option>
<option value="opportunity">Job Opportunity</option>
<option value="other">Other</option>
</select>
</div>
<div class="form-group">
<label for="message">
<span class="lang-en">Message</span>
<span class="lang-es">Mensaje</span>
</label>
<textarea id="message" name="message" rows="5" required></textarea>
</div>
<!-- Honeypot for spam prevention -->
<input type="text" name="_gotcha" style="display:none">
<button type="submit" class="btn btn--primary">
<span class="lang-en">Send Message</span>
<span class="lang-es">Enviar Mensaje</span>
</button>
</form>
Setup:
- Create a free account at formspree.io
- Create a new form
- Replace
YOUR_FORM_IDwith your form ID - Submissions are forwarded to your email
Alternative services:
- Netlify Forms (if migrating to Netlify)
- Basin (free tier)
- Web3Forms (no signup required)
9. Sitemap Page
Why
While jekyll-sitemap generates an XML sitemap for search engines, a human-readable sitemap page helps visitors navigate all content at a glance.
Implementation
Create _pages/sitemap-page.md:
---
layout: archive
title: "Sitemap"
title_en: "Sitemap"
title_es: "Mapa del Sitio"
permalink: /sitemap-page/
---
<div class="sitemap-human">
<h2><span class="lang-en">Main Pages</span><span class="lang-es">Paginas Principales</span></h2>
<ul>
<li><a href="/">Home</a></li>
<li><a href="/cv/">CV</a></li>
<li><a href="/contact/">Contact</a></li>
</ul>
<h2><span class="lang-en">Research</span><span class="lang-es">Investigacion</span></h2>
<ul>
<li><a href="/publication/silicon-vertex-detector-timing-upgrade-II-lhcb">Silicon vertex detector with timing for the Upgrade II of LHCb</a> (2023)</li>
<li><a href="/publication/tracking-time-measurements-3D-pixel-time-resolution">Tracking the Time: Measurements towards the characterization of a 3D pixel in terms of time resolution and Landau contribution evaluation</a> (2023)</li>
<li><a href="/publication/the-lhcb-upgrade-i">The LHCb upgrade I</a> (2023)</li>
</ul>
<h2><span class="lang-en">Projects</span><span class="lang-es">Proyectos</span></h2>
<ul>
<li><a href="/portfolio/3d-sensor-simulation/">3D Silicon Sensor Simulation</a></li>
<li><a href="/portfolio/data-analysis-pipeline/">Test Beam Data Pipeline</a></li>
<li><a href="/portfolio/julabo-control/">JulaboFL1703-control</a></li>
<li><a href="/portfolio/lhcb-velo-upgrade/">LHCb VELO Detector Upgrade</a></li>
<li><a href="/portfolio/maptoposter/">MapToPoster</a></li>
<li><a href="/portfolio/starter-pack/">CERN Starter Pack</a></li>
<li><a href="/portfolio/timepix4-telescope/">Timepix4 Beam Telescope</a></li>
<li><a href="/portfolio/vecindad-ames/">Vecindad Ames</a></li>
</ul>
<h2><span class="lang-en">Talks</span><span class="lang-es">Charlas</span></h2>
<ul>
<li><a href="/workshops/generative-ais-for-dummies">Generative AIs for Dummies Workshop</a> (2023)</li>
<li><a href="/talks/lhcb-velo-detector-design-operation-results">The LHCb VELO detector: design operation and first results</a> (2023)</li>
<li><a href="/talks/timepix4-sps-results">New Results from Timepix4 at the SPS</a> (2023)</li>
<li><a href="/talks/tracking-time-3d-pixel-resolution">Tracking the Time: Single cell 3D pixel time resolution and Landau contribution evaluation via test-beam and laboratory measurements</a> (2022)</li>
<li><a href="/talks/silicon-vertex-detector-timing-lhcb-upgrade">A Silicon Vertex Detector with Timing for the Upgrade II of LHCb</a> (2022)</li>
</ul>
<h2>Blog</h2>
<ul>
<li><a href="/posts/2024/10/new-horizons-at-cern/">New Horizons in Particle Physics: My Role at CERN with the VELO Group</a> (October 2024)</li>
<li><a href="/posts/2024/05/grid-ussage-nikhef/">I Think I Broke the Grid: 3rd Place in Grid Usage at Nikhef!</a> (May 2024)</li>
<li><a href="/posts/2023/12/generative-ai-for-dummies/">Generative AI for Dummies</a> (December 2023)</li>
<li><a href="/posts/2023/12/hiroshima-symposium-particle-physics/">Exploring the Frontiers of Particle Physics at the Hiroshima Symposium</a> (December 2023)</li>
<li><a href="/posts/2023/11/python-it-specialist-certification/">Achievement Unlocked: INF-303 Python IT Specialist Certification</a> (November 2023)</li>
<li><a href="/posts/2023/06/lhcb-velo-detector-launch/">Journey to Unraveling the Universe's Mysteries: The LHCb VELO Detector Launch</a> (June 2023)</li>
<li><a href="/posts/2022/06/advanced-detector-technologies-conference/">Shaping the Future of Particle Physics: Insights from the Advanced Detector Technologies Conference</a> (June 2022)</li>
</ul>
</div>
Add to footer:
<!-- _includes/footer.html -->
<a href="/sitemap-page/">Sitemap</a>
Priority Matrix
| Feature | Impact | Effort | Priority |
|---|---|---|---|
| Client-side search | High | Medium | P1 |
| Project filtering | Medium | Low | P1 |
| Social sharing buttons | Medium | Low | P1 |
| RSS feed subscribe UI | Low | Low | P1 |
| Contact form | Medium | Low | P2 |
| Related content | Medium | Medium | P2 |
| Reading time | Low | Low | P2 |
| Human sitemap | Low | Low | P3 |
| Back-to-top enhancement | Low | Low | P3 |
Implementation Order
Recommended order for maximum impact with minimum effort:
- Project filtering tabs - Quick win, improves portfolio navigation
- Social sharing buttons - Easy, increases content reach
- RSS feed visibility - Trivial, helps returning visitors
- Client-side search - Medium effort, high value as content grows
- Contact form - Quick setup with Formspree
- Related content - Increases engagement and page views
- Human sitemap - Quick, helps navigation