Features
Dev Showcase is packed with modern features designed to create an impressive and professional portfolio experience. This guide covers all major features and their implementation details.
Core Features Overview
Multilingual Support Dynamic ES/EN translation system with automatic language detection
Interactive Charts Chart.js-powered visualizations for skills and vocational data
Dynamic Profiles Switch between Data Science, Web Dev, and Data Analyst views
Glassmorphism Design Modern UI with translucent panels and backdrop blur effects
Multilingual Support (ES/EN)
The portfolio provides seamless language switching between English and Spanish with persistent user preferences.
Features
Automatic Language Detection : Detects user’s browser language on first visit
URL-based Language : Language preference reflected in URL (/en/dataScience or /es/dataScience)
LocalStorage Persistence : Remembers user’s language choice across sessions
Cookie Synchronization : Server-side cookie for consistent experience
Instant Updates : All text updates without page reload
Fallback Chain : Browser language → stored preference → Spanish (default)
Implementation
// translation.js - Language change handler
const changeLanguage = async ( language ) => {
if ( ! SUPPORTED_LANGUAGES . includes ( language )) language = DEFAULT_LANGUAGE ;
const translations = await loadTranslations ( language );
if ( ! translations ) {
showLanguageError ( language );
return ;
}
window . currentTranslations = translations ;
document . documentElement . lang = language ;
updateContent ( translations );
updateActiveButton ( language );
updateURL ( language );
localStorage . setItem ( 'preferredLanguage' , language );
};
Translation File Structure
All text content is stored in JSON files at wwwroot/languages/:
// en.json excerpt
{
"typewriter" : {
"prefix" : "I'm " ,
"phrases" : [
"Ricardo Alejandro Pérez Santillán" ,
"a Data enthusiast" ,
"an automation addict"
]
},
"navigation" : {
"introduction" : "Introduction" ,
"skills" : "Skills" ,
"projects" : "Projects & Experience" ,
"education" : "Education" ,
"downloadCV" : "Download CV"
}
}
Easy Customization : Update your content by editing en.json and es.json. No code changes needed!
Dynamic Profile Views
Switch between different professional profiles, each with tailored content that highlights relevant skills and experience.
Available Profiles
Data Science Focus on ML, Python, pandas, and data modeling
Web Development Highlight ASP.NET Core, JavaScript, and full-stack projects
Data Analyst Emphasize BI tools, SQL, and dashboard creation
Backend Implementation
// HomeController.cs - Profile routing
public class HomeController : Controller
{
private static readonly HashSet < string > ValidProfiles = new ( StringComparer . OrdinalIgnoreCase )
{
"dataScience" ,
"webDev" ,
"dataAnalyst" ,
"DataAnalysis"
};
public IActionResult Profile ( string profile )
{
if ( ! ValidProfiles . Contains ( profile ))
return NotFound ();
ViewData [ "Profile" ] = profile ;
return View ( "HomePage" );
}
}
Route Configuration
// Program.cs - Profile routes with language support
app . MapControllerRoute (
name : "profilesWithLang" ,
pattern : "{lang}/{profile}" ,
defaults : new { controller = "Home" , action = "Profile" },
constraints : new
{
lang = "^(es|en)$" ,
profile = @"^(dataScience|webDev|dataAnalyst|DataAnalysis)$"
});
Profile-specific content is managed through the JSON translation files using dynamic keys like aboutContent_dataScience, aboutContent_webDev, etc.
Interactive Charts with Chart.js
Powerful data visualizations showcase skills, competencies, and vocational profiles using Chart.js 4.4.0.
Chart Types
1. Radar Charts (RIASEC Vocational Profile)
Displays vocational interests across 18 dimensions using the RIASEC model:
// charts-manager.js - Radar chart configuration
const radarOptions = {
responsive: true ,
maintainAspectRatio: false ,
plugins: {
legend: { display: false },
tooltip: {
backgroundColor: 'rgba(10,3,47,0.92)' ,
callbacks: {
label : ctx => ` ${ ctx . dataset . label } : ${ ctx . parsed . r } %`
}
}
},
scales: {
r: {
beginAtZero: true ,
max: 100 ,
grid: { color: 'rgba(255,255,255,0.15)' , circular: true },
pointLabels: {
color: 'rgb(160,161,163)' ,
font: { size: 12 , weight: '600' }
}
}
}
};
2. Horizontal Bar Charts (Skills Proficiency)
Animated progress bars showing proficiency levels:
// charts-manager.js - Bar chart for skills
const barOptions = {
indexAxis: 'y' ,
responsive: true ,
maintainAspectRatio: false ,
scales: {
x: {
beginAtZero: true ,
max: 100 ,
ticks: {
callback : v => v + '%'
}
}
}
};
3. Cognitive Aptitude Charts
Compares personal scores against general averages:
const buildCognitiveData = () => {
const voc = getVoc ();
const nums = getChartData ()?. cognitive ?? {};
return {
labels: voc . cognitiveLabels ?? [], // ['Verbal', 'Numerical', 'Logical']
datasets: [
makeDs ( 'mine' , voc . cognitiveMe ?? 'My Score' , COGNITIVE_COLORS . mine ),
makeDs ( 'avg' , voc . cognitiveAvg ?? 'General Average' , COGNITIVE_COLORS . avg , {
borderDash: [ 6 , 3 ]
})
]
};
};
Chart Data Management
// en.json - Chart data structure
"chartsData" : {
"riasec" : {
"realistic" : [ 50 , 44 , 14 , 0 , 0 , 0 , ... ],
"investigative" : [ 0 , 0 , 0 , 56 , 91 , 37 , ... ],
"artistic" : [ 0 , 0 , 0 , 0 , 0 , 0 , 33 , ... ]
},
"cognitive" : {
"mine" : [ 47 , 40 , 47 ],
"avg" : [ 44 , 34 , 51 ]
}
}
Charts are dynamically created/destroyed based on the active section to optimize performance.
Infinite Carousel System
Smooth, touch-enabled carousel for browsing projects with seamless infinite scrolling.
Features
Infinite Scrolling : Clones cards at both ends for seamless looping
Touch/Mouse Support : Drag to navigate on any device
Responsive : Adapts to viewport size (shows 2.1 cards on desktop, 1.1 on mobile)
Smooth Animations : CSS transitions with cubic-bezier easing
Click Protection : Prevents card clicks during drag operations
Pagination : Shows current position (e.g., “3 / 5”)
Implementation
// carousel.js - Core carousel class
class InfiniteCarousel {
constructor ({ trackSelector , cardSelector , prevBtnSelector , nextBtnSelector }) {
this . track = document . querySelector ( trackSelector );
this . originalCards = document . querySelectorAll ( cardSelector );
this . totalOriginal = this . originalCards . length ;
this . currentIndex = this . clonesCount ;
this . init ();
}
move ( direction ) {
if ( this . isTransitioning ) return ;
this . isTransitioning = true ;
this . track . style . transition = 'transform 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94)' ;
if ( direction === 'next' ) this . currentIndex ++ ;
else this . currentIndex -- ;
this . updatePosition ( true );
this . updatePagination ();
}
}
Touch Events
// carousel.js - Touch/drag support
touchMove ( event ) {
if ( ! this . isDragging ) return ;
const currentPosition = this . getPositionX ( event );
const diff = currentPosition - this . startPos ;
if ( Math . abs ( diff ) > 5 ) {
this . hasMoved = true ;
if ( event . cancelable && event . type === 'touchmove' ) event . preventDefault ();
}
this . currentTranslate = this . prevTranslate + diff ;
this . animationID = requestAnimationFrame (() => {
this . track . style . transition = 'none' ;
this . track . style . transform = `translate3d( ${ this . currentTranslate } px, 0, 0)` ;
});
}
The carousel uses translate3d for hardware-accelerated smooth animations and requestAnimationFrame for optimal performance.
Particle Animation System
Dynamic particle animations in the header create depth and visual interest.
Features
20 Animated Particles : Each with unique trajectory and timing
CSS-based Animation : No JavaScript overhead, pure CSS performance
Randomized Movement : Each particle has custom translation vectors
Opacity Transitions : Fade in/out for smooth appearance
Rotation Effects : Particles rotate as they float
Implementation
<!-- _Layout.cshtml - Particle generation -->
< header class = "header-particles" >
< div class = "particles-container" >
@for (int i = 0; i < 20; i++)
{
< div class = "particle" ></ div >
}
</ div >
< div class = "header-content" >
< h2 data-translate = "header.hello" > #HELLO WORLD </ h2 >
< h1 > I'm Ricardo Alejandro Pérez Santillán </ h1 >
</ div >
</ header >
/* header-particles.css - Animation keyframes */
@keyframes float {
0% {
transform : translate ( 0 , 0 ) rotate ( 0 deg );
opacity : 0 ;
}
8% {
opacity : 0.5 ;
transform : translate ( calc ( var ( --tx ) * 0.15 ), calc ( var ( --ty ) * 0.1 )) rotate ( 45 deg );
}
/* ... intermediate keyframes ... */
100% {
transform : translate ( var ( --tx ), var ( --ty )) rotate ( 360 deg );
opacity : 0 ;
}
}
.particle {
position : absolute ;
background-color : #c0c0c0 ;
border-radius : 50 % ;
opacity : 0.3 ;
animation : float linear infinite ;
}
.particle:nth-child ( 1 ) {
width : 3 px ;
height : 3 px ;
left : 10 % ;
top : 20 % ;
--tx : 80 px ;
--ty : -250 px ;
animation-duration : 8 s ;
animation-delay : 0 s ;
}
Glassmorphism Design
Modern frosted-glass effect for UI panels with backdrop blur and translucency.
Visual Features
Translucent Backgrounds : Semi-transparent panels with blur effect
Border Highlights : Subtle borders with gradient colors
Shadow Depth : Multiple shadow layers for dimension
Hover Effects : Interactive glow on mouse hover
/* panels-glow.css - Glassmorphism effect */
.panel-glow {
background : rgba ( 255 , 255 , 255 , 0.05 );
backdrop-filter : blur ( 10 px );
border : 1 px solid rgba ( 255 , 255 , 255 , 0.1 );
border-radius : 16 px ;
box-shadow :
0 8 px 32 px rgba ( 0 , 0 , 0 , 0.3 ),
inset 0 1 px 0 rgba ( 255 , 255 , 255 , 0.1 );
transition : all 0.3 s ease ;
}
.panel-glow:hover {
background : rgba ( 255 , 255 , 255 , 0.08 );
border-color : rgba ( 255 , 255 , 255 , 0.2 );
box-shadow :
0 12 px 48 px rgba ( 0 , 0 , 0 , 0.4 ),
0 0 20 px rgba ( 255 , 255 , 255 , 0.1 ),
inset 0 1 px 0 rgba ( 255 , 255 , 255 , 0.15 );
}
Responsive Design
Fully responsive layout optimized for all device sizes.
Breakpoints
Desktop : 1200px and above (full sidebar, multi-column layouts)
Tablet : 768px - 1199px (collapsible sidebar, adjusted spacing)
Mobile : Below 768px (hamburger menu, single column)
/* responsive.css - Mobile optimization */
@media ( max-width : 768 px ) {
.sidebar {
position : fixed ;
left : -100 % ;
transition : left 0.3 s ease ;
z-index : 1000 ;
}
.sidebar.active {
left : 0 ;
}
.header-content h1 {
font-size : 1.8 rem ;
}
.carousel-card {
width : 90 vw ;
}
}
Downloadable CV
Profile-specific CV download with automatic language detection.
Features
Language-Aware : Serves English or Spanish CV based on current language
Profile-Specific : Different CVs for Data Analyst vs other profiles
Direct Download : Browser-native download, no server processing
// translation.js - CV link updater
window . updateCVLink = () => {
const btn = document . getElementById ( 'cvDownloadBtn' );
if ( ! btn ) return ;
const lang = document . documentElement . lang || DEFAULT_LANGUAGE ;
const path = window . location . pathname . toLowerCase ();
if ( path . includes ( '/dataanalyst' ) || path . includes ( '/dataanalysis' )) {
btn . href = lang === 'en'
? '/files/RicardoAlejandroPerezSantillan_DataAnalyst.pdf'
: '/files/RicardoAlejandroPerezSantillan_AnalistaDeDatos.pdf' ;
} else {
btn . href = lang === 'en' ? '/documents/cv_en.pdf' : '/documents/cv.pdf' ;
}
};
Additional Features
Typewriter Effect Animated text in header cycles through phrases with typing animation
Smooth Scrolling Section navigation with smooth scroll animations
Modal System Project detail modals with image galleries
Stat Animations Progress bars animate on scroll into view
Want to see these features in action? Follow the Quick Start guide to run the portfolio locally and explore all features interactively.