Skip to main content

Technical Implementation Review

Score: 8.5/10 Potential: 9/10 Gap: 0.5 points

Executive Summary

Your technical implementation is significantly above average for a portfolio site. Clean code organization, proper semantic HTML, good accessibility practices, and thoughtful architecture. However, there are maintainability issues that will create problems as the site scales: inline JavaScript, duplicated navigation logic, and imperative DOM manipulation.

Bottom line: You write good code. Now write maintainable code.

What You’re Doing Right

1. Code Organization (9/10)

Directory structure is clean and follows Jekyll conventions:

_sass/
├── _variables.scss     (83 lines)  - Design tokens
├── _base.scss         (84 lines)  - Resets and base styles
├── _typography.scss   (143 lines) - Font styles
├── _layout.scss       (605 lines) - Page layouts
├── _components.scss   (489 lines) - Reusable components
├── _utilities.scss    (123 lines) - Helper classes
├── _responsive.scss   (363 lines) - Media queries
├── _gallery.scss      (585 lines) - Gallery components
├── main.scss          (11 lines)  - Imports all above
└── design-system-pro.scss (726 lines) - Alternative system

Total: 3,211 lines across 10 files

Good decisions:

  • ✅ No monolithic files (largest is 726 lines)
  • ✅ Clear separation of concerns
  • ✅ Consistent naming conventions
  • ✅ Proper SCSS nesting and variables

Note: You have two design systems (main.scss imports vs design-system-pro.scss). This is technical debt—decide on one.

2. Semantic HTML (9/10)

From _layouts/default.html:

<!-- Line 33: Accessibility -->
<a href="#main" class="sr-only">Skip to main content</a>

<!-- Lines 36-93: Semantic structure -->
<header class="site-header" id="site-header">
  <nav class="site-nav" aria-label="Primary navigation">
    <!-- Navigation -->
  </nav>
</header>

<main id="main">
  <article class="page">
  <div class="container container-narrow">
    <header class="page-header">
      <h1 class="page-title">Design &amp; UX Review</h1>
      
    </header>
    
    <div class="page-content">
      <h1 id="design--ux-review">Design &amp; UX Review</h1>

<p><strong>Score</strong>: 7/10
<strong>Potential</strong>: 8/10
<strong>Gap</strong>: 1 point</p>

<h2 id="executive-summary">Executive Summary</h2>

<p>Your design system is technically competent with good fundamentals (typography scale, consistent spacing, semantic colors). However, the aesthetic choices are <strong>safe to the point of invisibility</strong>. The site follows generic portfolio patterns without visual personality or memorable moments. Technical execution is solid; creative expression is missing.</p>

<h2 id="the-core-problem-template-thinking">The Core Problem: Template Thinking</h2>

<h3 id="what-makes-design-generic">What Makes Design “Generic”</h3>

<p><strong>Not about quality</strong> - Your code is clean, your spacing is consistent, your colors are accessible.</p>

<p><strong>It’s about differentiation</strong> - When I see your site, I could swap the content with 50 other portfolios and the design would still work. That’s the problem.</p>

<h3 id="evidence-of-template-patterns">Evidence of Template Patterns</h3>

<h4 id="pattern-1-the-standard-hero">Pattern 1: The Standard Hero</h4>

<p><strong>From <code class="language-plaintext highlighter-rouge">index.html</code> (lines 7-34):</strong></p>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;section</span> <span class="na">class=</span><span class="s">"hero"</span><span class="nt">&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"container container-narrow"</span><span class="nt">&gt;</span>
    <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"hero-content"</span><span class="nt">&gt;</span>
      <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"hero-avatar"</span><span class="nt">&gt;</span>
        <span class="nt">&lt;img</span> <span class="na">src=</span><span class="s">"/assets/images/headshot.jpg"</span> <span class="na">alt=</span><span class="s">"..."</span><span class="nt">&gt;</span>
      <span class="nt">&lt;/div&gt;</span>
      <span class="nt">&lt;h1</span> <span class="na">class=</span><span class="s">"hero-title"</span><span class="nt">&gt;</span>Brandon JP Lambert<span class="nt">&lt;/h1&gt;</span>
      <span class="nt">&lt;p</span> <span class="na">class=</span><span class="s">"hero-tagline"</span><span class="nt">&gt;</span>Language Learning <span class="err">&amp;</span> Teaching<span class="nt">&lt;/p&gt;</span>
      <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"hero-actions"</span><span class="nt">&gt;</span>
        <span class="nt">&lt;a</span> <span class="na">href=</span><span class="s">"/work/"</span> <span class="na">class=</span><span class="s">"btn btn-primary"</span><span class="nt">&gt;</span>Learn More<span class="nt">&lt;/a&gt;</span>
        <span class="nt">&lt;a</span> <span class="na">href=</span><span class="s">"/contact/"</span> <span class="na">class=</span><span class="s">"btn btn-secondary"</span><span class="nt">&gt;</span>Contact Me<span class="nt">&lt;/a&gt;</span>
      <span class="nt">&lt;/div&gt;</span>
    <span class="nt">&lt;/div&gt;</span>
  <span class="nt">&lt;/div&gt;</span>
<span class="nt">&lt;/section&gt;</span>
</code></pre></div></div>

<p><strong>This is Every Portfolio Ever:</strong></p>
<ol>
  <li>Centered avatar</li>
  <li>Name</li>
  <li>Tagline</li>
  <li>Two buttons</li>
</ol>

<p><strong>No judgment</strong> - it works. But it’s <strong>unmemorable</strong>.</p>

<p><strong>Zero portfolios examined:</strong> Can you name a single portfolio that has this layout and stuck with you?</p>

<h4 id="pattern-2-the-translateย-2px-card-hover">Pattern 2: The Translateย(-2px) Card Hover</h4>

<p><strong>From <code class="language-plaintext highlighter-rouge">_sass/_components.scss</code> (lines 11-14):</strong></p>

<div class="language-scss highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">&amp;</span><span class="nd">:hover</span> <span class="p">{</span>
  <span class="nl">transform</span><span class="p">:</span> <span class="nf">translateY</span><span class="p">(</span><span class="m">-2px</span><span class="p">);</span>
  <span class="nl">border-color</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">color-accent</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>Usage count in the industry:</strong> ~10 million websites</p>

<p><strong>Why it’s overused:</strong> It’s the default Tailwind/Bootstrap hover effect. It works, but signals “I used the standard pattern.”</p>

<p><strong>Not bad</strong> - just <strong>unoriginal</strong>.</p>

<h4 id="pattern-3-the-academic-blue">Pattern 3: The Academic Blue</h4>

<p><strong>From <code class="language-plaintext highlighter-rouge">_sass/_variables.scss</code> (lines 8):</strong></p>

<div class="language-scss highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">--color-accent</span><span class="p">:</span> <span class="mh">#2c5282</span><span class="p">;</span>  <span class="c1">// Deep academic blue</span>
</code></pre></div></div>

<p><strong>This color appears on:</strong></p>
<ul>
  <li>University websites</li>
  <li>LinkedIn</li>
  <li>Conservative financial sites</li>
  <li>Government portals</li>
  <li>Your portfolio</li>
</ul>

<p><strong>It’s safe, professional, and forgettable.</strong></p>

<h3 id="why-safe-is-dangerous">Why “Safe” is Dangerous</h3>

<p><strong>Safe design means:</strong></p>
<ul>
  <li>✅ You won’t offend anyone</li>
  <li>✅ It’s accessible and professional</li>
  <li>❌ No one remembers it</li>
  <li>❌ Doesn’t reflect personality</li>
  <li>❌ Doesn’t differentiate you</li>
</ul>

<p><strong>In a competitive market, memorable &gt; safe.</strong></p>

<h2 id="design-system-analysis">Design System Analysis</h2>

<h3 id="-whats-working-well">✅ What’s Working Well</h3>

<h4 id="1-typography-scale-_variablesscss-lines-22-30">1. <strong>Typography Scale</strong> (_variables.scss, lines 22-30)</h4>

<div class="language-scss highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">--font-size-xs</span><span class="p">:</span> <span class="m">0</span><span class="mi">.64rem</span><span class="p">;</span>
<span class="na">--font-size-sm</span><span class="p">:</span> <span class="m">0</span><span class="mi">.8rem</span><span class="p">;</span>
<span class="na">--font-size-base</span><span class="p">:</span> <span class="m">1rem</span><span class="p">;</span>
<span class="na">--font-size-md</span><span class="p">:</span> <span class="m">1</span><span class="mi">.25rem</span><span class="p">;</span>
<span class="na">--font-size-lg</span><span class="p">:</span> <span class="m">1</span><span class="mi">.563rem</span><span class="p">;</span>
<span class="na">--font-size-xl</span><span class="p">:</span> <span class="m">1</span><span class="mi">.953rem</span><span class="p">;</span>
<span class="na">--font-size-2xl</span><span class="p">:</span> <span class="m">2</span><span class="mi">.441rem</span><span class="p">;</span>
<span class="na">--font-size-3xl</span><span class="p">:</span> <span class="m">3</span><span class="mi">.052rem</span><span class="p">;</span>
</code></pre></div></div>

<p><strong>Good:</strong></p>
<ul>
  <li>Proper modular scale (1.25 ratio)</li>
  <li>Sufficient range for hierarchy</li>
  <li>Semantic naming</li>
</ul>

<p><strong>Observation:</strong> You have 8 sizes but probably only use 4-5 regularly.</p>

<h4 id="2-spacing-system-_variablesscss-lines-43-53">2. <strong>Spacing System</strong> (_variables.scss, lines 43-53)</h4>

<div class="language-scss highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">--space-2</span><span class="p">:</span> <span class="m">0</span><span class="mi">.5rem</span><span class="p">;</span>   <span class="c1">// 8px</span>
<span class="na">--space-3</span><span class="p">:</span> <span class="m">1rem</span><span class="p">;</span>     <span class="c1">// 16px</span>
<span class="na">--space-4</span><span class="p">:</span> <span class="m">1</span><span class="mi">.5rem</span><span class="p">;</span>   <span class="c1">// 24px</span>
<span class="na">--space-5</span><span class="p">:</span> <span class="m">2rem</span><span class="p">;</span>     <span class="c1">// 32px</span>
</code></pre></div></div>

<p><strong>Good:</strong></p>
<ul>
  <li>Based on 8px grid (industry standard)</li>
  <li>Consistent mathematical relationship</li>
  <li>Prevents arbitrary spacing values</li>
</ul>

<p><strong>Observation:</strong> This alone puts you ahead of many portfolios.</p>

<h4 id="3-color-naming-_variablesscss-lines-4-12">3. <strong>Color Naming</strong> (_variables.scss, lines 4-12)</h4>

<div class="language-scss highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">--color-ink</span><span class="p">:</span> <span class="mh">#1a1a1a</span><span class="p">;</span>           <span class="c1">// Primary text</span>
<span class="na">--color-paper</span><span class="p">:</span> <span class="mh">#fafaf9</span><span class="p">;</span>          <span class="c1">// Background</span>
<span class="na">--color-accent</span><span class="p">:</span> <span class="mh">#2c5282</span><span class="p">;</span>         <span class="c1">// Deep academic blue</span>
<span class="na">--color-secondary</span><span class="p">:</span> <span class="mh">#718096</span><span class="p">;</span>      <span class="c1">// Muted gray</span>
</code></pre></div></div>

<p><strong>Good:</strong></p>
<ul>
  <li>Semantic, not descriptive (ink/paper vs dark-gray/light-gray)</li>
  <li>Clear purpose for each color</li>
  <li>Accessible contrast ratios</li>
</ul>

<p><strong>Observation:</strong> Your naming is better than your color choices.</p>

<h4 id="4-font-pairing-_variablesscss-lines-32-35">4. <strong>Font Pairing</strong> (_variables.scss, lines 32-35)</h4>

<div class="language-scss highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">--font-body</span><span class="p">:</span> <span class="s1">'Inter'</span><span class="o">,</span> <span class="o">-</span><span class="n">apple-system</span><span class="o">,</span> <span class="n">BlinkMacSystemFont</span><span class="o">,</span> <span class="s1">'Segoe UI'</span><span class="o">...</span>
<span class="o">--</span><span class="n">font-heading</span><span class="o">:</span> <span class="s1">'Crimson Text'</span><span class="o">,</span> <span class="s1">'EB Garamond'</span><span class="o">,</span> <span class="n">Georgia</span><span class="o">,</span> <span class="nb">serif</span><span class="p">;</span>
<span class="na">--font-mono</span><span class="p">:</span> <span class="s1">'JetBrains Mono'</span><span class="o">,</span> <span class="s1">'Fira Code'</span><span class="o">,</span> <span class="nb">monospace</span><span class="p">;</span>
</code></pre></div></div>

<p><strong>Good:</strong></p>
<ul>
  <li>Classic pairing: serif headings + sans body</li>
  <li>Appropriate fallbacks</li>
  <li>Monospace for code (relevant for dev portfolio)</li>
</ul>

<p><strong>Observation:</strong> This pairing appears on 1000+ dev portfolios. It’s the “Helvetica/Georgia” of 2025.</p>

<h3 id="️-what-needs-improvement">⚠️ What Needs Improvement</h3>

<h4 id="1-color-palette-is-too-conservative">1. <strong>Color Palette is Too Conservative</strong></h4>

<p><strong>Current palette:</strong></p>
<ul>
  <li>Deep blue (#2c5282)</li>
  <li>Muted gray (#718096)</li>
  <li>Near-black (#1a1a1a)</li>
  <li>Off-white (#fafaf9)</li>
</ul>

<p><strong>This palette says:</strong> “Corporate, safe, don’t take risks”</p>

<p><strong>What it should say:</strong> “Educator who experiments, creates, and thinks differently”</p>

<p><strong>Problems:</strong></p>
<ol>
  <li><strong>No warmth</strong> - All cool colors, nothing inviting</li>
  <li><strong>No energy</strong> - No vibrant accent for important actions</li>
  <li><strong>No personality</strong> - Could be anyone’s site</li>
</ol>

<p><strong>Where are your photography colors?</strong> You mention Letratos as a photography project. Why isn’t your visual palette informed by your photography?</p>

<h4 id="2-layout-is-too-uniform">2. <strong>Layout is Too Uniform</strong></h4>

<p><strong>Evidence:</strong> All project cards are identical (ai-projects.html, lines 34-123)</p>

<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
<span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"card project-card"</span> <span class="na">data-category=</span><span class="s">"Educational"</span><span class="nt">&gt;</span>
  <span class="c">&lt;!-- Same structure for every project --&gt;</span>
<span class="nt">&lt;/div&gt;</span>

<span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"card project-card"</span> <span class="na">data-category=</span><span class="s">"Educational"</span><span class="nt">&gt;</span>
  <span class="c">&lt;!-- Same structure for every project --&gt;</span>
<span class="nt">&lt;/div&gt;</span>

<span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"card project-card"</span> <span class="na">data-category=</span><span class="s">"Portfolio"</span><span class="nt">&gt;</span>
  <span class="c">&lt;!-- Same structure for every project --&gt;</span>
<span class="nt">&lt;/div&gt;</span>

<span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"card project-card"</span> <span class="na">data-category=</span><span class="s">"Educational Games"</span><span class="nt">&gt;</span>
  <span class="c">&lt;!-- Same structure for every project --&gt;</span>
<span class="nt">&lt;/div&gt;</span>

<span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"card project-card"</span> <span class="na">data-category=</span><span class="s">"Educational Games"</span><span class="nt">&gt;</span>
  <span class="c">&lt;!-- Same structure for every project --&gt;</span>
<span class="nt">&lt;/div&gt;</span>

<span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"card project-card"</span> <span class="na">data-category=</span><span class="s">"Educational"</span><span class="nt">&gt;</span>
  <span class="c">&lt;!-- Same structure for every project --&gt;</span>
<span class="nt">&lt;/div&gt;</span>

<span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"card project-card"</span> <span class="na">data-category=</span><span class="s">"Data Visualization"</span><span class="nt">&gt;</span>
  <span class="c">&lt;!-- Same structure for every project --&gt;</span>
<span class="nt">&lt;/div&gt;</span>

<span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"card project-card"</span> <span class="na">data-category=</span><span class="s">"Educational"</span><span class="nt">&gt;</span>
  <span class="c">&lt;!-- Same structure for every project --&gt;</span>
<span class="nt">&lt;/div&gt;</span>

<span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"card project-card"</span> <span class="na">data-category=</span><span class="s">"E-commerce"</span><span class="nt">&gt;</span>
  <span class="c">&lt;!-- Same structure for every project --&gt;</span>
<span class="nt">&lt;/div&gt;</span>

<span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"card project-card"</span> <span class="na">data-category=</span><span class="s">"Data Visualization"</span><span class="nt">&gt;</span>
  <span class="c">&lt;!-- Same structure for every project --&gt;</span>
<span class="nt">&lt;/div&gt;</span>

<span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"card project-card"</span> <span class="na">data-category=</span><span class="s">"Creative Platform"</span><span class="nt">&gt;</span>
  <span class="c">&lt;!-- Same structure for every project --&gt;</span>
<span class="nt">&lt;/div&gt;</span>

<span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"card project-card"</span> <span class="na">data-category=</span><span class="s">"Educational"</span><span class="nt">&gt;</span>
  <span class="c">&lt;!-- Same structure for every project --&gt;</span>
<span class="nt">&lt;/div&gt;</span>

<span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"card project-card"</span> <span class="na">data-category=</span><span class="s">"Creative Tools"</span><span class="nt">&gt;</span>
  <span class="c">&lt;!-- Same structure for every project --&gt;</span>
<span class="nt">&lt;/div&gt;</span>

<span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"card project-card"</span> <span class="na">data-category=</span><span class="s">"Productivity Tools"</span><span class="nt">&gt;</span>
  <span class="c">&lt;!-- Same structure for every project --&gt;</span>
<span class="nt">&lt;/div&gt;</span>

<span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"card project-card"</span> <span class="na">data-category=</span><span class="s">"Educational"</span><span class="nt">&gt;</span>
  <span class="c">&lt;!-- Same structure for every project --&gt;</span>
<span class="nt">&lt;/div&gt;</span>

<span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"card project-card"</span> <span class="na">data-category=</span><span class="s">"Educational"</span><span class="nt">&gt;</span>
  <span class="c">&lt;!-- Same structure for every project --&gt;</span>
<span class="nt">&lt;/div&gt;</span>

<span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"card project-card"</span> <span class="na">data-category=</span><span class="s">"Educational"</span><span class="nt">&gt;</span>
  <span class="c">&lt;!-- Same structure for every project --&gt;</span>
<span class="nt">&lt;/div&gt;</span>

<span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"card project-card"</span> <span class="na">data-category=</span><span class="s">"Educational"</span><span class="nt">&gt;</span>
  <span class="c">&lt;!-- Same structure for every project --&gt;</span>
<span class="nt">&lt;/div&gt;</span>

</code></pre></div></div>

<p><strong>Every project gets:</strong></p>
<ul>
  <li>Same width card</li>
  <li>Same height image</li>
  <li>Same text layout</li>
  <li>Same button arrangement</li>
</ul>

<p><strong>Result:</strong> Visual monotony. Nothing stands out as “most important.”</p>

<p><strong>Better approach:</strong> Differentiate by project status/importance:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[Featured Project - Full Width]
+------------------------------------------+
|  Large Image          |  Description     |
|  Gallery             |  Key Metrics     |
|                      |  [Demo] [Code]   |
+------------------------------------------+

[Active Projects - 2 Column]
+--------------------+  +--------------------+
| Image              |  | Image              |
| Title              |  | Title              |
| Brief Desc         |  | Brief Desc         |
+--------------------+  +--------------------+

[Prototypes - 3 Column]
+------+  +------+  +------+
| Icon |  | Icon |  | Icon |
| Name |  | Name |  | Name |
+------+  +------+  +------+
</code></pre></div></div>

<p>This creates <strong>visual hierarchy</strong> and <strong>guides attention</strong>.</p>

<h4 id="3-no-personality-moments">3. <strong>No Personality Moments</strong></h4>

<p><strong>Personality</strong> = unexpected delighters that make people smile or pause</p>

<p><strong>Current count:</strong> 0</p>

<p><strong>Examples from other portfolios:</strong></p>
<ul>
  <li>Custom 404 page with humor</li>
  <li>Animated illustrations that react to scroll</li>
  <li>Easter eggs (Konami code, hidden messages)</li>
  <li>Personal photos/behind-the-scenes</li>
  <li>Hand-drawn elements</li>
  <li>Playful micro-interactions</li>
  <li>Dark mode with personality (not just inverted colors)</li>
</ul>

<p><strong>Your opportunity:</strong> You’re a <strong>photographer</strong> and <strong>language learner</strong>. Where are:</p>
<ul>
  <li>Bilingual easter eggs?</li>
  <li>Your photos used as backgrounds?</li>
  <li>Spanish idioms as section headers?</li>
  <li>Teaching artifacts (old lesson plans, student feedback)?</li>
</ul>

<h4 id="4-button-design-is-generic">4. <strong>Button Design is Generic</strong></h4>

<p><strong>From <code class="language-plaintext highlighter-rouge">_sass/_components.scss</code> (lines 33-88):</strong></p>

<div class="language-scss highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.btn</span> <span class="p">{</span>
  <span class="nl">display</span><span class="p">:</span> <span class="n">inline-block</span><span class="p">;</span>
  <span class="nl">padding</span><span class="p">:</span> <span class="m">0</span><span class="mi">.5rem</span> <span class="m">1</span><span class="mi">.25rem</span><span class="p">;</span>
  <span class="nl">border-radius</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">border-radius-sm</span><span class="p">);</span>  <span class="c1">// 2px</span>
  <span class="nl">font-size</span><span class="p">:</span> <span class="m">0</span><span class="mi">.875rem</span><span class="p">;</span>
  <span class="nl">font-weight</span><span class="p">:</span> <span class="m">500</span><span class="p">;</span>
  <span class="c1">// ...</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>This button could be on:</strong> Amazon, Shopify, WordPress, Medium, your site</p>

<p><strong>What makes a memorable button?</strong></p>
<ul>
  <li>Unique shape/radius</li>
  <li>Motion on hover (not just color change)</li>
  <li>Sound feedback (subtle)</li>
  <li>Contextual variations</li>
</ul>

<p><strong>Example of personality:</strong></p>
<div class="language-scss highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.btn-primary</span> <span class="p">{</span>
  <span class="c1">// Current: flat blue rectangle</span>

  <span class="c1">// Alternative 1: Subtle skew</span>
  <span class="nl">transform</span><span class="p">:</span> <span class="nf">skewX</span><span class="p">(</span><span class="m">-2deg</span><span class="p">);</span>

  <span class="c1">// Alternative 2: Bottom border indicator</span>
  <span class="nl">border-bottom</span><span class="p">:</span> <span class="m">3px</span> <span class="nb">solid</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">color-accent-dark</span><span class="p">);</span>

  <span class="c1">// Alternative 3: Arrow that slides in</span>
  <span class="k">&amp;</span><span class="nd">::after</span> <span class="p">{</span>
    <span class="nl">content</span><span class="p">:</span> <span class="s2">"→"</span><span class="p">;</span>
    <span class="nl">opacity</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
    <span class="nl">transform</span><span class="p">:</span> <span class="nf">translateX</span><span class="p">(</span><span class="m">-10px</span><span class="p">);</span>
    <span class="nl">transition</span><span class="p">:</span> <span class="n">all</span> <span class="m">0</span><span class="mi">.2s</span><span class="p">;</span>
  <span class="p">}</span>
  <span class="k">&amp;</span><span class="nd">:hover::after</span> <span class="p">{</span>
    <span class="nl">opacity</span><span class="p">:</span> <span class="m">1</span><span class="p">;</span>
    <span class="nl">transform</span><span class="p">:</span> <span class="nf">translateX</span><span class="p">(</span><span class="m">5px</span><span class="p">);</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>Not saying use these</strong> - but your buttons have <strong>zero personality</strong>.</p>

<h2 id="missing-visual-elements">Missing Visual Elements</h2>

<h3 id="1-photography-integration">1. <strong>Photography Integration</strong></h3>

<p><strong>You’re a photographer</strong>, yet:</p>
<ul>
  <li>No photo gallery on homepage</li>
  <li>Letratos project buried in project list</li>
  <li>Photography not part of visual identity</li>
  <li>No photos used as section backgrounds/headers</li>
</ul>

<p><strong>Opportunity:</strong></p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">&lt;!-- Hero Section with your photo --&gt;</span>
<span class="nt">&lt;section</span> <span class="na">class=</span><span class="s">"hero"</span> <span class="na">style=</span><span class="s">"background-image: url('your-photo.jpg');"</span><span class="nt">&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"hero-overlay"</span><span class="nt">&gt;</span>
    <span class="c">&lt;!-- Content with readable contrast --&gt;</span>
  <span class="nt">&lt;/div&gt;</span>
<span class="nt">&lt;/section&gt;</span>

<span class="c">&lt;!-- About section with personal photo --&gt;</span>
<span class="nt">&lt;section</span> <span class="na">class=</span><span class="s">"about"</span><span class="nt">&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"about-content"</span><span class="nt">&gt;</span>
    <span class="nt">&lt;img</span> <span class="na">src=</span><span class="s">"you-teaching.jpg"</span> <span class="na">alt=</span><span class="s">"Teaching in Medellín"</span><span class="nt">&gt;</span>
    <span class="nt">&lt;p&gt;</span>This is me in 2020, teaching English in Colombia...<span class="nt">&lt;/p&gt;</span>
  <span class="nt">&lt;/div&gt;</span>
<span class="nt">&lt;/section&gt;</span>
</code></pre></div></div>

<p><strong>Why this matters:</strong> It <strong>humanizes</strong> your portfolio and shows <strong>another dimension</strong> of who you are.</p>

<h3 id="2-bilingual-design-elements">2. <strong>Bilingual Design Elements</strong></h3>

<p><strong>You have full Spanish translation</strong>, but design doesn’t reflect bilingualism:</p>
<ul>
  <li>No visual language indicator beyond EN/ES buttons</li>
  <li>No Spanish typography considerations</li>
  <li>No cultural visual references</li>
</ul>

<p><strong>Ideas:</strong></p>
<ul>
  <li>Section headers in both languages stacked</li>
  <li>Spanish idiom illustrations</li>
  <li>Color palette inspired by Colombian culture</li>
  <li>Typography that honors Spanish diacritics</li>
</ul>

<h3 id="3-educational-artifacts">3. <strong>Educational Artifacts</strong></h3>

<p><strong>You’re a 4th-generation educator</strong>, yet:</p>
<ul>
  <li>No teaching photos</li>
  <li>No student work examples (with permission)</li>
  <li>No old lesson plans or handouts</li>
  <li>No visual timeline of teaching career</li>
</ul>

<p><strong>Opportunity:</strong> Create a “Teaching History” visual timeline:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Great-grandfather (1940s) → Grandfather (1970s) → Father (1990s) → You (2010s)
[Photo]                     [Photo]                [Photo]           [Photo]
Teaching: Math              Teaching: Science      Teaching: History Teaching: Languages
Medium: Chalkboard          Medium: Overhead       Medium: Computer  Medium: AI
</code></pre></div></div>

<p>This is <strong>unique, memorable, and meaningful</strong>.</p>

<h2 id="specific-design-improvements">Specific Design Improvements</h2>

<h3 id="1-homepage-hero---add-asymmetry">1. Homepage Hero - Add Asymmetry</h3>

<p><strong>Current layout (index.html, lines 8-32):</strong> Centered, symmetrical, predictable</p>

<p><strong>Improved layout:</strong></p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;section</span> <span class="na">class=</span><span class="s">"hero hero-asymmetric"</span><span class="nt">&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"hero-left"</span><span class="nt">&gt;</span>
    <span class="c">&lt;!-- Large personal photo from Colombia --&gt;</span>
    <span class="nt">&lt;img</span> <span class="na">src=</span><span class="s">"brandon-teaching.jpg"</span> <span class="na">alt=</span><span class="s">"Teaching"</span><span class="nt">&gt;</span>
  <span class="nt">&lt;/div&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"hero-right"</span><span class="nt">&gt;</span>
    <span class="nt">&lt;span</span> <span class="na">class=</span><span class="s">"hero-eyebrow"</span><span class="nt">&gt;</span>4th Generation Educator<span class="nt">&lt;/span&gt;</span>
    <span class="nt">&lt;h1&gt;</span>Brandon JP Lambert<span class="nt">&lt;/h1&gt;</span>
    <span class="nt">&lt;p</span> <span class="na">class=</span><span class="s">"hero-intro"</span><span class="nt">&gt;</span>
      I teach languages. I build tools. I use AI to make both better.
      <span class="nt">&lt;strong&gt;</span>10 years in classrooms → 15 projects → 1 portfolio<span class="nt">&lt;/strong&gt;</span>
    <span class="nt">&lt;/p&gt;</span>
    <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"hero-stats"</span><span class="nt">&gt;</span>
      <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"stat"</span><span class="nt">&gt;</span>
        <span class="nt">&lt;span</span> <span class="na">class=</span><span class="s">"stat-number"</span><span class="nt">&gt;</span>10<span class="nt">&lt;/span&gt;</span>
        <span class="nt">&lt;span</span> <span class="na">class=</span><span class="s">"stat-label"</span><span class="nt">&gt;</span>Years Teaching<span class="nt">&lt;/span&gt;</span>
      <span class="nt">&lt;/div&gt;</span>
      <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"stat"</span><span class="nt">&gt;</span>
        <span class="nt">&lt;span</span> <span class="na">class=</span><span class="s">"stat-number"</span><span class="nt">&gt;</span>15<span class="nt">&lt;/span&gt;</span>
        <span class="nt">&lt;span</span> <span class="na">class=</span><span class="s">"stat-label"</span><span class="nt">&gt;</span>AI Projects<span class="nt">&lt;/span&gt;</span>
      <span class="nt">&lt;/div&gt;</span>
      <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"stat"</span><span class="nt">&gt;</span>
        <span class="nt">&lt;span</span> <span class="na">class=</span><span class="s">"stat-number"</span><span class="nt">&gt;</span>B2<span class="nt">&lt;/span&gt;</span>
        <span class="nt">&lt;span</span> <span class="na">class=</span><span class="s">"stat-label"</span><span class="nt">&gt;</span>Spanish Level<span class="nt">&lt;/span&gt;</span>
      <span class="nt">&lt;/div&gt;</span>
    <span class="nt">&lt;/div&gt;</span>
    <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"hero-actions"</span><span class="nt">&gt;</span>
      <span class="nt">&lt;a</span> <span class="na">href=</span><span class="s">"/work/philosophy/"</span> <span class="na">class=</span><span class="s">"btn btn-primary"</span><span class="nt">&gt;</span>My Teaching Approach →<span class="nt">&lt;/a&gt;</span>
      <span class="nt">&lt;a</span> <span class="na">href=</span><span class="s">"/ai-projects/"</span> <span class="na">class=</span><span class="s">"btn btn-secondary"</span><span class="nt">&gt;</span>See the Tools<span class="nt">&lt;/a&gt;</span>
    <span class="nt">&lt;/div&gt;</span>
  <span class="nt">&lt;/div&gt;</span>
<span class="nt">&lt;/section&gt;</span>
</code></pre></div></div>

<p><strong>Why better:</strong></p>
<ul>
  <li>Asymmetric layout creates visual interest</li>
  <li>Stats give concrete proof</li>
  <li>Photo humanizes immediately</li>
  <li>Clear value proposition</li>
</ul>

<h3 id="2-project-cards---create-hierarchy">2. Project Cards - Create Hierarchy</h3>

<p><strong>Current:</strong> All projects have equal visual weight</p>

<p><strong>Improved:</strong> Three tiers</p>

<h4 id="tier-1-featured-project-full-width">Tier 1: Featured Project (Full Width)</h4>
<div class="language-scss highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.project-featured</span> <span class="p">{</span>
  <span class="nl">display</span><span class="p">:</span> <span class="n">grid</span><span class="p">;</span>
  <span class="na">grid-template-columns</span><span class="p">:</span> <span class="m">1</span><span class="mi">.5fr</span> <span class="m">1fr</span><span class="p">;</span>
  <span class="na">gap</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">space-6</span><span class="p">);</span>
  <span class="nl">margin-bottom</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">space-8</span><span class="p">);</span>
  <span class="nl">padding</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">space-6</span><span class="p">);</span>
  <span class="nl">background</span><span class="p">:</span> <span class="nf">linear-gradient</span><span class="p">(</span><span class="m">135deg</span><span class="o">,</span> <span class="mh">#f5f7fa</span> <span class="m">0%</span><span class="o">,</span> <span class="mh">#c3cfe2</span> <span class="m">100%</span><span class="p">);</span>
  <span class="nl">border-radius</span><span class="p">:</span> <span class="m">12px</span><span class="p">;</span>

  <span class="nc">.project-gallery</span> <span class="p">{</span>
    <span class="c1">// Large image carousel</span>
  <span class="p">}</span>

  <span class="nc">.project-details</span> <span class="p">{</span>
    <span class="c1">// Prominent description, metrics, CTAs</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<h4 id="tier-2-active-projects-2-column-grid">Tier 2: Active Projects (2 Column Grid)</h4>
<div class="language-scss highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.project-active</span> <span class="p">{</span>
  <span class="nl">display</span><span class="p">:</span> <span class="n">grid</span><span class="p">;</span>
  <span class="na">grid-template-columns</span><span class="p">:</span> <span class="nf">repeat</span><span class="p">(</span><span class="m">2</span><span class="o">,</span> <span class="m">1fr</span><span class="p">);</span>
  <span class="na">gap</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">space-5</span><span class="p">);</span>

  <span class="nc">.project-card</span> <span class="p">{</span>
    <span class="c1">// Medium-sized cards</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<h4 id="tier-3-prototypes-3-column-compact">Tier 3: Prototypes (3 Column, Compact)</h4>
<div class="language-scss highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.project-prototype</span> <span class="p">{</span>
  <span class="nl">display</span><span class="p">:</span> <span class="n">grid</span><span class="p">;</span>
  <span class="na">grid-template-columns</span><span class="p">:</span> <span class="nf">repeat</span><span class="p">(</span><span class="m">3</span><span class="o">,</span> <span class="m">1fr</span><span class="p">);</span>
  <span class="na">gap</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">space-3</span><span class="p">);</span>

  <span class="nc">.project-card</span> <span class="p">{</span>
    <span class="c1">// Compact cards, less detail</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>Impact:</strong> Visitors immediately see what’s most important.</p>

<h3 id="3-color-palette---add-warmth--energy">3. Color Palette - Add Warmth &amp; Energy</h3>

<p><strong>Current palette problems:</strong></p>
<ul>
  <li>Too corporate</li>
  <li>No warmth</li>
  <li>No energy</li>
</ul>

<p><strong>Proposed alternative (inspired by your Colombia photography):</strong></p>

<div class="language-scss highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">:root</span> <span class="p">{</span>
  <span class="c1">// Primary (keep some blue, warm it up)</span>
  <span class="na">--color-primary</span><span class="p">:</span> <span class="mh">#2B6CB0</span><span class="p">;</span>      <span class="c1">// Warmer blue</span>
  <span class="na">--color-primary-dark</span><span class="p">:</span> <span class="mh">#1A4971</span><span class="p">;</span>
  <span class="na">--color-primary-light</span><span class="p">:</span> <span class="mh">#4299E1</span><span class="p">;</span>

  <span class="c1">// Secondary (add warm accent)</span>
  <span class="na">--color-secondary</span><span class="p">:</span> <span class="mh">#DD6B20</span><span class="p">;</span>    <span class="c1">// Warm orange (Colombia sunset)</span>

  <span class="c1">// Tertiary (education green)</span>
  <span class="na">--color-tertiary</span><span class="p">:</span> <span class="mh">#38A169</span><span class="p">;</span>     <span class="c1">// Success/growth green</span>

  <span class="c1">// Neutrals (warmer)</span>
  <span class="na">--color-ink</span><span class="p">:</span> <span class="mh">#2D3748</span><span class="p">;</span>          <span class="c1">// Softer than pure black</span>
  <span class="na">--color-paper</span><span class="p">:</span> <span class="mh">#FFFAF0</span><span class="p">;</span>        <span class="c1">// Warmer white (slight cream)</span>

  <span class="c1">// Supporting</span>
  <span class="na">--color-accent</span><span class="p">:</span> <span class="mh">#9F7AEA</span><span class="p">;</span>       <span class="c1">// Purple for variety</span>
  <span class="na">--color-muted</span><span class="p">:</span> <span class="mh">#718096</span><span class="p">;</span>        <span class="c1">// Keep this</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>Color usage:</strong></p>
<ul>
  <li><strong>Primary blue</strong>: Main CTAs, links</li>
  <li><strong>Secondary orange</strong>: Important accents, featured elements</li>
  <li><strong>Tertiary green</strong>: Success states, completed projects</li>
  <li><strong>Purple</strong>: Hover states, subtle highlights</li>
</ul>

<p><strong>Why better:</strong></p>
<ul>
  <li>Warm colors are inviting</li>
  <li>Orange adds energy</li>
  <li>Green connects to education/growth theme</li>
  <li>Still professional, but memorable</li>
</ul>

<h3 id="4-typography---add-personality">4. Typography - Add Personality</h3>

<p><strong>Current fonts are fine</strong>, but could be more distinctive:</p>

<p><strong>Alternative 1: Embrace the Academic</strong></p>
<div class="language-scss highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">--font-heading</span><span class="p">:</span> <span class="s1">'Crimson Pro'</span><span class="o">,</span> <span class="s1">'Crimson Text'</span><span class="o">,</span> <span class="n">Georgia</span><span class="o">,</span> <span class="nb">serif</span><span class="p">;</span>
<span class="na">--font-body</span><span class="p">:</span> <span class="s1">'Inter'</span><span class="o">,</span> <span class="nb">sans-serif</span><span class="p">;</span>
<span class="na">--font-accent</span><span class="p">:</span> <span class="s1">'Playfair Display'</span><span class="o">,</span> <span class="nb">serif</span><span class="p">;</span>  <span class="c1">// For callouts</span>
</code></pre></div></div>
<p>Use Playfair Display for pull quotes, section headers</p>

<p><strong>Alternative 2: Modern Geometric</strong></p>
<div class="language-scss highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">--font-heading</span><span class="p">:</span> <span class="s1">'Poppins'</span><span class="o">,</span> <span class="nb">sans-serif</span><span class="p">;</span>  <span class="c1">// Geometric, friendly</span>
<span class="na">--font-body</span><span class="p">:</span> <span class="s1">'Inter'</span><span class="o">,</span> <span class="nb">sans-serif</span><span class="p">;</span>
<span class="na">--font-accent</span><span class="p">:</span> <span class="s1">'Space Mono'</span><span class="o">,</span> <span class="nb">monospace</span><span class="p">;</span>  <span class="c1">// For code/tech elements</span>
</code></pre></div></div>

<p><strong>Alternative 3: Humanist (warm, approachable)</strong></p>
<div class="language-scss highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">--font-heading</span><span class="p">:</span> <span class="s1">'Merriweather'</span><span class="o">,</span> <span class="nb">serif</span><span class="p">;</span>
<span class="na">--font-body</span><span class="p">:</span> <span class="s1">'Source Sans Pro'</span><span class="o">,</span> <span class="nb">sans-serif</span><span class="p">;</span>
<span class="na">--font-accent</span><span class="p">:</span> <span class="s1">'Bitter'</span><span class="o">,</span> <span class="nb">serif</span><span class="p">;</span>  <span class="c1">// For emphasis</span>
</code></pre></div></div>

<p><strong>Recommendation:</strong> Stick with current, but add <strong>typographic variety</strong>:</p>
<ul>
  <li>Use italic Crimson Text for pull quotes</li>
  <li>Add larger font sizes for important statements</li>
  <li>Increase line-height for readability (current: 1.6, try 1.8)</li>
</ul>

<h3 id="5-micro-interactions---add-delight">5. Micro-Interactions - Add Delight</h3>

<p><strong>Current interactions:</strong> Hover color changes, translateY(-2px)</p>

<p><strong>Opportunities:</strong></p>

<h4 id="navigation-hover">Navigation Hover</h4>
<div class="language-scss highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.site-nav</span> <span class="nt">a</span> <span class="p">{</span>
  <span class="nl">position</span><span class="p">:</span> <span class="nb">relative</span><span class="p">;</span>

  <span class="k">&amp;</span><span class="nd">::after</span> <span class="p">{</span>
    <span class="nl">content</span><span class="p">:</span> <span class="s1">''</span><span class="p">;</span>
    <span class="nl">position</span><span class="p">:</span> <span class="nb">absolute</span><span class="p">;</span>
    <span class="nl">bottom</span><span class="p">:</span> <span class="m">-2px</span><span class="p">;</span>
    <span class="nl">left</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
    <span class="nl">width</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
    <span class="nl">height</span><span class="p">:</span> <span class="m">2px</span><span class="p">;</span>
    <span class="nl">background</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">color-primary</span><span class="p">);</span>
    <span class="nl">transition</span><span class="p">:</span> <span class="n">width</span> <span class="m">0</span><span class="mi">.3s</span> <span class="n">ease</span><span class="p">;</span>
  <span class="p">}</span>

  <span class="k">&amp;</span><span class="nd">:hover::after</span> <span class="p">{</span>
    <span class="nl">width</span><span class="p">:</span> <span class="m">100%</span><span class="p">;</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<h4 id="project-card-hover">Project Card Hover</h4>
<div class="language-scss highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.project-card</span> <span class="p">{</span>
  <span class="nl">transition</span><span class="p">:</span> <span class="n">all</span> <span class="m">0</span><span class="mi">.3s</span> <span class="n">ease</span><span class="p">;</span>

  <span class="k">&amp;</span><span class="nd">:hover</span> <span class="p">{</span>
    <span class="nl">transform</span><span class="p">:</span> <span class="nf">translateY</span><span class="p">(</span><span class="m">-4px</span><span class="p">)</span> <span class="nf">scale</span><span class="p">(</span><span class="m">1</span><span class="mi">.02</span><span class="p">);</span>
    <span class="nl">box-shadow</span><span class="p">:</span> <span class="m">0</span> <span class="m">12px</span> <span class="m">24px</span> <span class="nf">rgba</span><span class="p">(</span><span class="m">0</span><span class="o">,</span><span class="m">0</span><span class="o">,</span><span class="m">0</span><span class="o">,</span><span class="m">0</span><span class="mi">.15</span><span class="p">);</span>

    <span class="nc">.project-image</span> <span class="nt">img</span> <span class="p">{</span>
      <span class="nl">transform</span><span class="p">:</span> <span class="nf">scale</span><span class="p">(</span><span class="m">1</span><span class="mi">.05</span><span class="p">);</span>
    <span class="p">}</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<h4 id="button-press">Button Press</h4>
<div class="language-scss highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.btn</span> <span class="p">{</span>
  <span class="k">&amp;</span><span class="nd">:active</span> <span class="p">{</span>
    <span class="nl">transform</span><span class="p">:</span> <span class="nf">translateY</span><span class="p">(</span><span class="m">1px</span><span class="p">);</span>
    <span class="nl">box-shadow</span><span class="p">:</span> <span class="nb">inset</span> <span class="m">0</span> <span class="m">2px</span> <span class="m">4px</span> <span class="nf">rgba</span><span class="p">(</span><span class="m">0</span><span class="o">,</span><span class="m">0</span><span class="o">,</span><span class="m">0</span><span class="o">,</span><span class="m">0</span><span class="mi">.1</span><span class="p">);</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>Small changes, big impact</strong> on perceived quality.</p>

<h2 id="ux-issues-to-fix">UX Issues to Fix</h2>

<h3 id="1-mobile-menu-implementation">1. <strong>Mobile Menu Implementation</strong></h3>

<p><strong>Current</strong> (_layouts/default.html, lines 85-89):</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;button</span> <span class="na">class=</span><span class="s">"mobile-menu-toggle"</span> <span class="na">onclick=</span><span class="s">"toggleMobileMenu()"</span><span class="nt">&gt;</span>
  <span class="nt">&lt;span&gt;&lt;/span&gt;</span>
  <span class="nt">&lt;span&gt;&lt;/span&gt;</span>
  <span class="nt">&lt;span&gt;&lt;/span&gt;</span>
<span class="nt">&lt;/button&gt;</span>
</code></pre></div></div>

<p><strong>Problems:</strong></p>
<ul>
  <li>Hamburger icon without label (accessibility issue)</li>
  <li>No visual feedback on menu state</li>
  <li>JavaScript inline in HTML</li>
</ul>

<p><strong>Better:</strong></p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;button</span> <span class="na">class=</span><span class="s">"mobile-menu-toggle"</span>
        <span class="na">aria-label=</span><span class="s">"Toggle menu"</span>
        <span class="na">aria-expanded=</span><span class="s">"false"</span>
        <span class="na">aria-controls=</span><span class="s">"mobile-menu"</span><span class="nt">&gt;</span>
  <span class="nt">&lt;span</span> <span class="na">class=</span><span class="s">"hamburger"</span><span class="nt">&gt;</span>
    <span class="nt">&lt;span</span> <span class="na">class=</span><span class="s">"hamburger-line"</span><span class="nt">&gt;&lt;/span&gt;</span>
    <span class="nt">&lt;span</span> <span class="na">class=</span><span class="s">"hamburger-line"</span><span class="nt">&gt;&lt;/span&gt;</span>
    <span class="nt">&lt;span</span> <span class="na">class=</span><span class="s">"hamburger-line"</span><span class="nt">&gt;&lt;/span&gt;</span>
  <span class="nt">&lt;/span&gt;</span>
  <span class="nt">&lt;span</span> <span class="na">class=</span><span class="s">"sr-only"</span><span class="nt">&gt;</span>Menu<span class="nt">&lt;/span&gt;</span>
<span class="nt">&lt;/button&gt;</span>
</code></pre></div></div>

<p><strong>With CSS animation:</strong></p>
<div class="language-scss highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.mobile-menu-toggle</span> <span class="p">{</span>
  <span class="k">&amp;</span><span class="o">[</span><span class="nt">aria-expanded</span><span class="o">=</span><span class="s2">"true"</span><span class="o">]</span> <span class="p">{</span>
    <span class="nc">.hamburger-line</span><span class="nd">:nth-child</span><span class="o">(</span><span class="nt">1</span><span class="o">)</span> <span class="p">{</span>
      <span class="nl">transform</span><span class="p">:</span> <span class="nf">rotate</span><span class="p">(</span><span class="m">45deg</span><span class="p">)</span> <span class="nf">translate</span><span class="p">(</span><span class="m">5px</span><span class="o">,</span> <span class="m">5px</span><span class="p">);</span>
    <span class="p">}</span>
    <span class="nc">.hamburger-line</span><span class="nd">:nth-child</span><span class="o">(</span><span class="nt">2</span><span class="o">)</span> <span class="p">{</span>
      <span class="nl">opacity</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
    <span class="p">}</span>
    <span class="nc">.hamburger-line</span><span class="nd">:nth-child</span><span class="o">(</span><span class="nt">3</span><span class="o">)</span> <span class="p">{</span>
      <span class="nl">transform</span><span class="p">:</span> <span class="nf">rotate</span><span class="p">(</span><span class="m">-45deg</span><span class="p">)</span> <span class="nf">translate</span><span class="p">(</span><span class="m">5px</span><span class="o">,</span> <span class="m">-5px</span><span class="p">);</span>
    <span class="p">}</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>Animated hamburger → X</strong> is expected UX.</p>

<h3 id="2-language-switcher-visibility">2. <strong>Language Switcher Visibility</strong></h3>

<p><strong>Current</strong> (_layouts/default.html, lines 75-82):</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"language-toggle"</span><span class="nt">&gt;</span>
  <span class="nt">&lt;button</span> <span class="na">class=</span><span class="s">"lang-btn"</span> <span class="na">data-lang=</span><span class="s">"en"</span><span class="nt">&gt;</span>EN<span class="nt">&lt;/button&gt;</span>
  <span class="nt">&lt;button</span> <span class="na">class=</span><span class="s">"lang-btn"</span> <span class="na">data-lang=</span><span class="s">"es"</span><span class="nt">&gt;</span>ES<span class="nt">&lt;/button&gt;</span>
<span class="nt">&lt;/div&gt;</span>
</code></pre></div></div>

<p><strong>Problems:</strong></p>
<ul>
  <li>Small buttons, easy to miss</li>
  <li>No indication which is active (requires JS)</li>
  <li>No flags or clear visual differentiation</li>
</ul>

<p><strong>Better:</strong></p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"language-toggle"</span> <span class="na">role=</span><span class="s">"group"</span> <span class="na">aria-label=</span><span class="s">"Language selection"</span><span class="nt">&gt;</span>
  <span class="nt">&lt;button</span> <span class="na">class=</span><span class="s">"lang-btn"</span> <span class="na">data-lang=</span><span class="s">"en"</span> <span class="na">aria-pressed=</span><span class="s">"true"</span><span class="nt">&gt;</span>
    <span class="nt">&lt;span</span> <span class="na">class=</span><span class="s">"flag"</span><span class="nt">&gt;</span>🇺🇸<span class="nt">&lt;/span&gt;</span>
    <span class="nt">&lt;span</span> <span class="na">class=</span><span class="s">"lang-label"</span><span class="nt">&gt;</span>English<span class="nt">&lt;/span&gt;</span>
  <span class="nt">&lt;/button&gt;</span>
  <span class="nt">&lt;button</span> <span class="na">class=</span><span class="s">"lang-btn"</span> <span class="na">data-lang=</span><span class="s">"es"</span> <span class="na">aria-pressed=</span><span class="s">"false"</span><span class="nt">&gt;</span>
    <span class="nt">&lt;span</span> <span class="na">class=</span><span class="s">"flag"</span><span class="nt">&gt;</span>🇪🇸<span class="nt">&lt;/span&gt;</span>
    <span class="nt">&lt;span</span> <span class="na">class=</span><span class="s">"lang-label"</span><span class="nt">&gt;</span>Español<span class="nt">&lt;/span&gt;</span>
  <span class="nt">&lt;/button&gt;</span>
<span class="nt">&lt;/div&gt;</span>
</code></pre></div></div>

<p><strong>With styles:</strong></p>
<div class="language-scss highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.lang-btn</span> <span class="p">{</span>
  <span class="k">&amp;</span><span class="o">[</span><span class="nt">aria-pressed</span><span class="o">=</span><span class="s2">"true"</span><span class="o">]</span> <span class="p">{</span>
    <span class="nl">background</span><span class="p">:</span> <span class="nf">var</span><span class="p">(</span><span class="o">--</span><span class="n">color-primary</span><span class="p">);</span>
    <span class="nl">color</span><span class="p">:</span> <span class="no">white</span><span class="p">;</span>
    <span class="nl">font-weight</span><span class="p">:</span> <span class="m">600</span><span class="p">;</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>Flags + labels + clear active state</strong> = better UX.</p>

<h3 id="3-project-filtering-feedback">3. <strong>Project Filtering Feedback</strong></h3>

<p><strong>Current</strong> (ai-projects.html, lines 11-19):</p>
<ul>
  <li>Buttons change color when active</li>
  <li>No count of filtered results</li>
  <li>No empty state message</li>
</ul>

<p><strong>Improved:</strong></p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"filter-controls"</span><span class="nt">&gt;</span>
  <span class="nt">&lt;button</span> <span class="na">class=</span><span class="s">"filter-btn active"</span> <span class="na">data-filter=</span><span class="s">"all"</span><span class="nt">&gt;</span>
    All Projects <span class="nt">&lt;span</span> <span class="na">class=</span><span class="s">"count"</span><span class="nt">&gt;</span>(15)<span class="nt">&lt;/span&gt;</span>
  <span class="nt">&lt;/button&gt;</span>
  <span class="nt">&lt;button</span> <span class="na">class=</span><span class="s">"filter-btn"</span> <span class="na">data-filter=</span><span class="s">"Educational"</span><span class="nt">&gt;</span>
    Educational <span class="nt">&lt;span</span> <span class="na">class=</span><span class="s">"count"</span><span class="nt">&gt;</span>(8)<span class="nt">&lt;/span&gt;</span>
  <span class="nt">&lt;/button&gt;</span>
  <span class="c">&lt;!-- etc --&gt;</span>
<span class="nt">&lt;/div&gt;</span>

<span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"filter-results"</span><span class="nt">&gt;</span>
  <span class="nt">&lt;p&gt;</span>Showing <span class="nt">&lt;strong</span> <span class="na">id=</span><span class="s">"results-count"</span><span class="nt">&gt;</span>15<span class="nt">&lt;/strong&gt;</span> projects<span class="nt">&lt;/p&gt;</span>
<span class="nt">&lt;/div&gt;</span>
</code></pre></div></div>

<p><strong>JavaScript updates count</strong> when filtering. Users get immediate feedback.</p>

<h3 id="4-missing-loading-states">4. <strong>Missing Loading States</strong></h3>

<p><strong>Current:</strong> No loading indicators for:</p>
<ul>
  <li>Image lazy loading</li>
  <li>Page transitions</li>
  <li>AJAX (if any)</li>
</ul>

<p><strong>Add:</strong></p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"project-image"</span><span class="nt">&gt;</span>
  <span class="nt">&lt;img</span> <span class="na">src=</span><span class="s">"project.jpg"</span>
       <span class="na">loading=</span><span class="s">"lazy"</span>
       <span class="na">alt=</span><span class="s">"..."</span>
       <span class="na">onload=</span><span class="s">"this.classList.add('loaded')"</span><span class="nt">&gt;</span>
  <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">"image-loader"</span><span class="nt">&gt;&lt;/div&gt;</span>
<span class="nt">&lt;/div&gt;</span>
</code></pre></div></div>

<div class="language-scss highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.project-image</span> <span class="p">{</span>
  <span class="nl">position</span><span class="p">:</span> <span class="nb">relative</span><span class="p">;</span>

  <span class="nt">img</span> <span class="p">{</span>
    <span class="nl">opacity</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
    <span class="nl">transition</span><span class="p">:</span> <span class="n">opacity</span> <span class="m">0</span><span class="mi">.3s</span><span class="p">;</span>

    <span class="k">&amp;</span><span class="nc">.loaded</span> <span class="p">{</span>
      <span class="nl">opacity</span><span class="p">:</span> <span class="m">1</span><span class="p">;</span>
    <span class="p">}</span>
  <span class="p">}</span>

  <span class="nc">.image-loader</span> <span class="p">{</span>
    <span class="nl">position</span><span class="p">:</span> <span class="nb">absolute</span><span class="p">;</span>
    <span class="na">inset</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
    <span class="nl">background</span><span class="p">:</span> <span class="nf">linear-gradient</span><span class="p">(</span><span class="m">90deg</span><span class="o">,</span> <span class="mh">#f0f0f0</span> <span class="m">25%</span><span class="o">,</span> <span class="mh">#e0e0e0</span> <span class="m">50%</span><span class="o">,</span> <span class="mh">#f0f0f0</span> <span class="m">75%</span><span class="p">);</span>
    <span class="nl">background-size</span><span class="p">:</span> <span class="m">200%</span> <span class="m">100%</span><span class="p">;</span>
    <span class="nl">animation</span><span class="p">:</span> <span class="n">loading</span> <span class="m">1</span><span class="mi">.5s</span> <span class="n">infinite</span><span class="p">;</span>
  <span class="p">}</span>

  <span class="nt">img</span><span class="nc">.loaded</span> <span class="o">~</span> <span class="nc">.image-loader</span> <span class="p">{</span>
    <span class="nl">display</span><span class="p">:</span> <span class="nb">none</span><span class="p">;</span>
  <span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>

<p><strong>Skeleton loaders</strong> improve perceived performance.</p>

<h2 id="design-inspiration-sources">Design Inspiration Sources</h2>

<h3 id="portfolios-with-personality">Portfolios with Personality</h3>
<ul>
  <li><strong>Cassie Evans</strong> (cassie.codes) - Playful animations, hand-drawn elements</li>
  <li><strong>Lynn Fisher</strong> (lynnandtonic.com) - Unique layout each year, creative constraints</li>
  <li><strong>Tatiana Mac</strong> (tatianamac.com) - Strong typography, clear voice</li>
  <li><strong>Dan Abramov</strong> (overreacted.io) - Content-first, personality in writing</li>
</ul>

<h3 id="key-takeaways-from-each">Key Takeaways from Each</h3>
<ul>
  <li><strong>Cassie</strong>: Animation can show personality without being distracting</li>
  <li><strong>Lynn</strong>: Constraints breed creativity (she redesigns yearly with a theme)</li>
  <li><strong>Tatiana</strong>: Strong opinions, strongly held (design reflects confidence)</li>
  <li><strong>Dan</strong>: Content quality matters more than flashy design</li>
</ul>

<p><strong>Your opportunity:</strong> Combine educator authenticity with creative visual expression.</p>

<h2 id="action-plan-design-improvements">Action Plan: Design Improvements</h2>

<h3 id="week-1-quick-visual-wins-6-8-hours">Week 1: Quick Visual Wins (6-8 hours)</h3>

<p><strong>Day 1: Color Palette Refresh</strong> (2 hours)</p>
<ul>
  <li>Update _variables.scss with warmer colors</li>
  <li>Test contrast ratios (WebAIM tool)</li>
  <li>Apply to buttons and accents</li>
</ul>

<p><strong>Day 2: Hero Section Redesign</strong> (3 hours)</p>
<ul>
  <li>Add personal photo</li>
  <li>Create asymmetric layout</li>
  <li>Add stats/metrics</li>
  <li>Rewrite CTA buttons</li>
</ul>

<p><strong>Day 3: Project Card Hierarchy</strong> (2 hours)</p>
<ul>
  <li>Pick 1 featured project (full width)</li>
  <li>Adjust grid for Active vs Prototype projects</li>
  <li>Add visual differentiation</li>
</ul>

<h3 id="week-2-personality--polish-8-10-hours">Week 2: Personality &amp; Polish (8-10 hours)</h3>

<p><strong>Day 4: Photography Integration</strong> (3 hours)</p>
<ul>
  <li>Select 5-10 best photos from Letratos</li>
  <li>Add as section backgrounds (with overlay)</li>
  <li>Create photo gallery on homepage</li>
  <li>Link to Letratos prominently</li>
</ul>

<p><strong>Day 5: Micro-Interactions</strong> (2 hours)</p>
<ul>
  <li>Improve button hover states</li>
  <li>Add nav underline animation</li>
  <li>Animate mobile menu icon</li>
  <li>Polish project card hovers</li>
</ul>

<p><strong>Day 6: Typography Refinement</strong> (2 hours)</p>
<ul>
  <li>Increase body line-height to 1.8</li>
  <li>Add pull quote styling (large, italic, Crimson)</li>
  <li>Create visual hierarchy in project descriptions</li>
  <li>Add section header treatments</li>
</ul>

<p><strong>Day 7: UX Fixes</strong> (2 hours)</p>
<ul>
  <li>Fix mobile menu accessibility</li>
  <li>Improve language switcher visibility</li>
  <li>Add loading states for images</li>
  <li>Add filter result counts</li>
</ul>

<h3 id="month-1-major-redesign-elements-16-20-hours">Month 1: Major Redesign Elements (16-20 hours)</h3>

<p><strong>Week 3: Teaching Timeline</strong> (6 hours)</p>
<ul>
  <li>Design visual timeline of 4 generations</li>
  <li>Source family photos (if available)</li>
  <li>Create illustrated version if no photos</li>
  <li>Add to “About” or “Work” page</li>
</ul>

<p><strong>Week 4: Bilingual Design Elements</strong> (6 hours)</p>
<ul>
  <li>Add Spanish idioms as section headers</li>
  <li>Create bilingual typography treatments</li>
  <li>Add cultural color references</li>
  <li>Design language-specific layouts</li>
</ul>

<p><strong>Week 5: Project Case Studies</strong> (8 hours)</p>
<ul>
  <li>Choose top 3 projects</li>
  <li>Create detailed visual case study layout</li>
  <li>Include process images, iterations, metrics</li>
  <li>Design unique layout for each</li>
</ul>

<h2 id="success-metrics-design">Success Metrics (Design)</h2>

<h3 id="beforeafter-comparison">Before/After Comparison</h3>

<p><strong>Test:</strong> Show 5 people your portfolio for 30 seconds. After, ask:</p>

<p><strong>Current responses (predicted):</strong></p>
<ul>
  <li>“It’s clean”</li>
  <li>“Professional”</li>
  <li>“Blue and white”</li>
  <li>“Developer portfolio”</li>
</ul>

<p><strong>Goal responses:</strong></p>
<ul>
  <li>“The teaching timeline is really cool”</li>
  <li>“I love the photo of you teaching”</li>
  <li>“The orange accent is warm”</li>
  <li>“An educator who codes—that’s unique”</li>
</ul>

<p><strong>If responses change</strong> → design is working.</p>

<h3 id="specific-metrics">Specific Metrics</h3>

<p><strong>Visual Variety</strong></p>
<ul>
  <li>Current: All project cards identical</li>
  <li>Goal: 3 distinct card layouts (featured, active, prototype)</li>
</ul>

<p><strong>Color Usage</strong></p>
<ul>
  <li>Current: 90% gray/blue, 10% accent</li>
  <li>Goal: 70% neutral, 20% primary, 10% warm accents</li>
</ul>

<p><strong>Personal Elements</strong></p>
<ul>
  <li>Current: 1 (avatar)</li>
  <li>Goal: 5+ (photos, teaching artifacts, family history)</li>
</ul>

<p><strong>Memorable Moments</strong></p>
<ul>
  <li>Current: 0</li>
  <li>Goal: 3-5 (timeline, photo gallery, unique layout, Easter egg)</li>
</ul>

<h2 id="final-thought-on-design">Final Thought on Design</h2>

<p><strong>Your design isn’t bad. It’s boring.</strong></p>

<p>And “boring” is worse than “bad” because:</p>
<ul>
  <li>Bad design gets remembered (even negatively)</li>
  <li>Boring design gets forgotten</li>
</ul>

<p>You have <strong>unique stories</strong> (4 generations of teaching, learning Spanish, Colombia experience, building 15 projects).</p>

<p>Your design should <strong>reflect those stories visually</strong>.</p>

<p><strong>Stop designing like you’re applying for a corporate job.</strong></p>

<p><strong>Start designing like you’re starting a conversation.</strong></p>

<p>The technical foundation is solid. Now add personality, warmth, and visual storytelling.</p>

<p>Start with the hero section redesign. You’ll feel the difference immediately.</p>

    </div>
  </div>
</article>
</main>

<footer class="site-footer">
  <!-- Footer content -->
</footer>

Good practices:

  • ✅ Proper <header>, <nav>, <main>, <footer> structure
  • ✅ Skip-to-content link for keyboard navigation
  • ✅ ARIA labels on interactive elements
  • ✅ Semantic heading hierarchy

One issue: Mobile menu has accessibility problems (covered later).

3. SEO & Meta Tags (8.5/10)

From _layouts/default.html (lines 8-29):

<!-- SEO Meta Tags -->
<!-- Begin Jekyll SEO tag v2.8.0 -->
<title>Technical Implementation Review | Brandon JP Lambert</title>
<meta name="generator" content="Jekyll v3.10.0" />
<meta property="og:title" content="Technical Implementation Review" />
<meta name="author" content="Brandon JP Lambert" />
<meta property="og:locale" content="en" />
<meta name="description" content="Academic portfolio and educational resource platform showcasing work in education, technology, and language learning. Bilingual English/Spanish site featuring AI projects, teaching philosophy, and Spanish learning resources." />
<meta property="og:description" content="Academic portfolio and educational resource platform showcasing work in education, technology, and language learning. Bilingual English/Spanish site featuring AI projects, teaching philosophy, and Spanish learning resources." />
<link rel="canonical" href="https://brandonjplambert.com/docs/portfolio-review/03-technical-implementation/" />
<meta property="og:url" content="https://brandonjplambert.com/docs/portfolio-review/03-technical-implementation/" />
<meta property="og:site_name" content="Brandon JP Lambert" />
<meta property="og:type" content="website" />
<meta name="twitter:card" content="summary" />
<meta property="twitter:title" content="Technical Implementation Review" />
<script type="application/ld+json">
{"@context":"https://schema.org","@type":"WebPage","author":{"@type":"Person","name":"Brandon JP Lambert"},"description":"Academic portfolio and educational resource platform showcasing work in education, technology, and language learning. Bilingual English/Spanish site featuring AI projects, teaching philosophy, and Spanish learning resources.","headline":"Technical Implementation Review","url":"https://brandonjplambert.com/docs/portfolio-review/03-technical-implementation/"}</script>
<!-- End Jekyll SEO tag -->


<!-- Alternate language versions -->
<link rel="alternate" hreflang="en" href="https://brandonjplambert.com/docs/portfolio-review/03-technical-implementation/">
<link rel="alternate" hreflang="es" href="https://brandonjplambert.com/es/docs/portfolio-review/03-technical-implementation/">
<link rel="alternate" hreflang="x-default" href="https://brandonjplambert.com/docs/portfolio-review/03-technical-implementation/">

<!-- Fonts with preconnect -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>

<!-- Favicon -->
<link rel="icon" type="image/png" sizes="32x32" href="...">

<!-- Feed -->
<link rel="alternate" type="application/rss+xml" title="Brandon JP Lambert" href="/feed.xml">

Good practices:

  • ✅ Using jekyll-seo-tag plugin
  • ✅ Proper hreflang tags for bilingual content
  • ✅ Font preconnect for performance
  • ✅ RSS feed available
  • ✅ Cache busting with timestamps (line 22)

One issue: Google Fonts are render-blocking. Consider self-hosting or font-display: swap.

4. Performance Considerations (8/10)

From _config.yml (lines 58-60):

sass:
  style: compressed
  sass_dir: _sass

From _layouts/default.html (line 22):

<link rel="stylesheet" href="/assets/css/main.css?v=1762906844">

From _pages/ai-projects.html (line 43):

<img src="" alt="..." loading="lazy">

Good practices:

  • ✅ Compressed SASS output
  • ✅ Cache busting on CSS
  • ✅ Lazy loading images
  • ✅ No unnecessary JavaScript libraries

Performance score prediction: Lighthouse 90-95

Improvements possible:

  • Critical CSS inlining
  • Image optimization (WebP with fallbacks)
  • Service worker for offline support
  • Font subsetting (only load characters you use)

5. Accessibility (8/10)

Good elements:

<!-- ARIA labels -->
<button aria-label="Toggle menu">...</button>
<button aria-label="Switch to English">...</button>

<!-- Skip link -->
<a href="#main" class="sr-only">Skip to main content</a>

<!-- Semantic structure -->
<nav aria-label="Primary navigation">...</nav>

From _sass/_variables.scss (lines 4-12):

// High contrast colors
--color-ink: #1a1a1a;     // Dark enough for WCAG AAA
--color-paper: #fafaf9;   // Light enough for contrast
--color-accent: #2c5282; // Passes WCAG AA on white

Accessibility strengths:

  • ✅ Good color contrast
  • ✅ Semantic HTML
  • ✅ Keyboard navigation support
  • ✅ Skip links
  • ✅ ARIA labels where needed

Issues:

  • ❌ Mobile menu missing aria-expanded state
  • ❌ No focus indicators visible (keyboard navigation unclear)
  • ❌ Some interactive elements use onclick instead of proper event listeners
  • ❌ No reduced-motion media query support

Technical Debt Identified

RESOLVED Oct 8, 2025 - Inline JavaScript in Templates

Problem 1: 346 Lines of JavaScript in HTMLFIXED

File: _pages/ai-projects.html (lines 152-498)Now 167 lines total

Resolution (Oct 8, 2025):

  • ✅ Extracted to 4 focused modules in /assets/js/
  • ✅ projects-filter.js (117 lines)
  • ✅ project-modal.js (113 lines)
  • ✅ tech-tooltips.js (115 lines)
  • ✅ site-navigation.js (171 lines)
  • ✅ Result: 994 → 167 lines (-83% reduction)
  • ✅ See: daily_reports/2025-10-08.md for full details

Original Problems (NOW FIXED):

  1. Untestable - Now modular and testable
  2. No minification - Can now minify separately
  3. No linting - Modules can be linted
  4. Hard to debug - Clear module boundaries
  5. Violates separation of concerns - Proper separation achieved

Current structure:

<script>
(function() {
  'use strict';
  // 346 lines of project filtering logic
  // 200+ lines of modal logic
  // 50+ lines of tooltip logic
})();
</script>

Should be:

/assets/js/
├── projects-filter.js    (filtering logic)
├── project-modal.js      (history modal)
├── tech-tooltips.js      (tooltip interactions)
└── main.js              (initialization)

Impact: Medium effort (4-6 hours), high value (maintainability)

RESOLVED Oct 8, 2025 - Navigation Duplication → FIXED

File: _layouts/default.html (lines 40-93 and 96-133)

Resolution (Oct 8, 2025):

  • ✅ Created _includes/nav-items.html (single source of truth)
  • ✅ Eliminated 56 lines of duplication
  • ✅ DRY principle applied (Don’t Repeat Yourself)
  • ✅ Navigation logic now reusable
  • ✅ default.html reduced from 332 → 130 lines (-61%)

You have two complete navigation structures:NOW: Single navigation include

Current Architecture:

<!-- Desktop nav (3 lines) -->





<li>
  <a href="/"
     
     >
    Home
  </a>
</li>



<li>
  <a href="/work/"
     
     >
    Work
  </a>
</li>



<li>
  <a href="/ai-projects/"
     
     >
    AI Projects
  </a>
</li>



<li>
  <a href="/resources/"
     
     >
    Resources
  </a>
</li>



<li>
  <a href="/contact/"
     
     >
    Contact
  </a>
</li>



<!-- Mobile nav (8 lines with parameter) -->





<li class="mobile-nav-item">
  <a href="/"
     
     onclick="closeMobileMenu()">
    Home
  </a>
</li>



<li class="mobile-nav-item">
  <a href="/work/"
     
     onclick="closeMobileMenu()">
    Work
  </a>
</li>



<li class="mobile-nav-item">
  <a href="/ai-projects/"
     
     onclick="closeMobileMenu()">
    AI Projects
  </a>
</li>



<li class="mobile-nav-item">
  <a href="/resources/"
     
     onclick="closeMobileMenu()">
    Resources
  </a>
</li>



<li class="mobile-nav-item">
  <a href="/contact/"
     
     onclick="closeMobileMenu()">
    Contact
  </a>
</li>


Original Problems (NOW FIXED):

  1. Any nav change requires updating two places - Now single include
  2. Increases HTML size (duplicated markup) - Eliminated duplication
  3. Higher chance of inconsistencies - Single source prevents mismatches

Solution: Single nav, CSS-controlled visibility:

<nav class="site-nav" id="site-nav">
  <ul class="nav-list">
    
      <li class="nav-item">
        <a href="..." class="nav-link"></a>
      </li>
    
      <li class="nav-item">
        <a href="..." class="nav-link"></a>
      </li>
    
      <li class="nav-item">
        <a href="..." class="nav-link"></a>
      </li>
    
      <li class="nav-item">
        <a href="..." class="nav-link"></a>
      </li>
    
      <li class="nav-item">
        <a href="..." class="nav-link"></a>
      </li>
    
  </ul>
</nav>
.site-nav {
  // Desktop styles

  @media (max-width: 1023px) {
    // Mobile styles (full-screen overlay)
    position: fixed;
    top: 60px;
    left: 0;
    right: 0;
    bottom: 0;
    background: white;
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.3s;

    &.is-open {
      opacity: 1;
      pointer-events: auto;
    }

    .nav-list {
      flex-direction: column;
      align-items: center;
      justify-content: center;
      height: 100%;
    }
  }
}

Impact: Low effort (2 hours), medium value (maintainability)

Problem 3: Imperative DOM Manipulation

File: _layouts/default.html (lines 177-213)

function toggleMobileMenu() {
  const overlay = document.getElementById('mobile-menu-overlay');
  const toggle = document.querySelector('.mobile-menu-toggle');

  if (!overlay || !toggle) {
    return;
  }

  // Check if menu is open
  const isOpen = overlay.style.display === 'block';

  if (!isOpen) {
    // Open menu
    overlay.style.display = 'block';
    toggle.classList.add('active');
    document.body.style.overflow = 'hidden';
  } else {
    // Close menu
    overlay.style.display = 'none';
    toggle.classList.remove('active');
    document.body.style.overflow = '';
  }
}

Problems:

  1. Manipulating style.display directly - Hard to test, brittle
  2. Checking style.display to determine state - Doesn’t reflect actual state
  3. Inline styles mixed with classes - Inconsistent approach
  4. Global function - Pollutes namespace

Modern approach using data attributes:

<button class="mobile-menu-toggle"
        data-mobile-menu-toggle
        aria-expanded="false"
        aria-controls="site-nav">
  <span class="hamburger">...</span>
</button>

<nav class="site-nav" id="site-nav" data-mobile-menu>
  <!-- Navigation -->
</nav>
// /assets/js/mobile-menu.js
class MobileMenu {
  constructor(toggleEl, menuEl) {
    this.toggle = toggleEl;
    this.menu = menuEl;
    this.isOpen = false;

    this.toggle.addEventListener('click', () => this.toggleMenu());
    this.menu.addEventListener('click', (e) => {
      if (e.target.matches('a')) {
        this.closeMenu();
      }
    });
  }

  toggleMenu() {
    this.isOpen ? this.closeMenu() : this.openMenu();
  }

  openMenu() {
    this.isOpen = true;
    this.menu.classList.add('is-open');
    this.toggle.setAttribute('aria-expanded', 'true');
    document.body.classList.add('menu-open');
  }

  closeMenu() {
    this.isOpen = false;
    this.menu.classList.remove('is-open');
    this.toggle.setAttribute('aria-expanded', 'false');
    document.body.classList.remove('menu-open');
  }
}

// Initialize
const toggle = document.querySelector('[data-mobile-menu-toggle]');
const menu = document.querySelector('[data-mobile-menu]');
if (toggle && menu) {
  new MobileMenu(toggle, menu);
}

Why better:

  • State managed in JavaScript, reflected in DOM
  • Uses classes, not inline styles
  • Proper ARIA attributes
  • Testable (can instantiate MobileMenu in tests)
  • Encapsulated (no global functions)

Impact: Medium effort (3 hours), high value (code quality + accessibility)

Problem 4: Complex Language Switcher

File: _layouts/default.html (lines 219-257)

Current implementation: 39 lines of manual URL mapping

function switchLanguage(lang) {
  localStorage.setItem('preferredLanguage', lang);
  const currentPath = window.location.pathname;
  let newPath;

  if (lang === 'es') {
    if (!cleanPath.includes('/es/')) {
      newPath = cleanPath
        .replace('/work/', '/es/trabajo/')
        .replace('/ai-projects/', '/es/proyectos-ia/')
        .replace('/resources/', '/es/recursos/')
        .replace('/contact/', '/es/contacto/');

      if (newPath === cleanPath) {
        newPath = '/es' + cleanPath;
      }
    }
  } else {
    newPath = cleanPath
      .replace('/es/trabajo/', '/work/')
      .replace('/es/proyectos-ia/', '/ai-projects/')
      .replace('/es/recursos/', '/resources/')
      .replace('/es/contacto/', '/contact/')
      .replace('/es/', '/');
  }

  window.location.pathname = baseUrl + newPath;
}

Problems:

  1. Hardcoded paths - Add a new page? Update this function
  2. No single source of truth - Path mappings exist nowhere else
  3. Easy to break - Typo in any path breaks switching
  4. Not scalable - What if you add 10 more pages?

Better approach using data:

// _data/language_paths.yml
paths:
  - en: /work/
    es: /es/trabajo/
  - en: /ai-projects/
    es: /es/proyectos-ia/
  - en: /resources/
    es: /es/recursos/
  - en: /contact/
    es: /es/contacto/
// /assets/js/language-switcher.js
const PATH_MAP = {
  en_to_es: {
    '/work/': '/es/trabajo/',
    '/ai-projects/': '/es/proyectos-ia/',
    '/resources/': '/es/recursos/',
    '/contact/': '/es/contacto/'
  },
  es_to_en: {
    '/es/trabajo/': '/work/',
    '/es/proyectos-ia/': '/ai-projects/',
    '/es/recursos/': '/resources/',
    '/es/contacto/': '/contact/'
  }
};

function switchLanguage(targetLang) {
  localStorage.setItem('preferredLanguage', targetLang);

  const currentPath = window.location.pathname;
  const map = targetLang === 'es' ? PATH_MAP.en_to_es : PATH_MAP.es_to_en;

  // Try exact match first
  if (map[currentPath]) {
    window.location.pathname = map[currentPath];
    return;
  }

  // Try partial match
  for (const [oldPath, newPath] of Object.entries(map)) {
    if (currentPath.includes(oldPath)) {
      window.location.pathname = currentPath.replace(oldPath, newPath);
      return;
    }
  }

  // Fallback: toggle /es/ prefix
  if (targetLang === 'es') {
    window.location.pathname = '/es' + currentPath;
  } else {
    window.location.pathname = currentPath.replace(/^\/es/, '');
  }
}

Even better: Generate this from Jekyll data:

// _includes/language-paths.js
const PATH_MAP = {
  en_to_es: {
    
  },
  es_to_en: {
    
  }
};

Why better:

  • Single source of truth (language_paths.yml)
  • Easy to add new pages
  • Less code to maintain
  • Harder to break

Impact: Medium effort (3 hours), high value (maintainability)

⚠️ PARTIALLY RESOLVED Oct 8, 2025 - Console.log in Production

File: _pages/ai-projects.html (lines 159, 176-189, 207-209)NOW CLEAN

Resolution (Oct 8, 2025):

  • ✅ Removed ALL 8 console.logs from ai-projects.html
  • ✅ Extracted JavaScript modules are production-clean
  • ⚠️ REMAINING: 54 console.logs in /tools/ and /docs/ folders (non-production code)

~~```javascript console.log(‘Initializing AI Projects page - VERSION 2 WITH TOOLTIPS’); // … 6 more console.logs


**Status:** Production pages are now clean. Non-critical tools/docs still have debug logs.

**Original Problems (NOW FIXED for production):**
1. ~~Performance impact~~ - Eliminated from production pages
2. ~~Clutters browser console~~ - Clean console on live site
3. ~~Can leak information~~ - No info leakage in production
4. ~~Unprofessional~~ - Professional production code achieved

**Solution:** Use a debug flag:

```javascript
const DEBUG = false; // Set to true for development

function log(...args) {
  if (DEBUG) {
    console.log('[AI Projects]', ...args);
  }
}

// Usage
log('Processing:', fullText);

Or: Remove entirely and use browser debugger when needed.

Impact: Low effort (15 minutes), medium value (professionalism)

Architecture Recommendations

1. Establish Build Process

Current: Jekyll builds SCSS, that’s it.

Recommended: Add JavaScript bundling and minification

Option A: Simple (esbuild)

npm install --save-dev esbuild
// package.json
{
  "scripts": {
    "js:build": "esbuild assets/js/main.js --bundle --minify --outfile=assets/js/bundle.js",
    "js:watch": "esbuild assets/js/main.js --bundle --watch --outfile=assets/js/bundle.js",
    "build": "npm run js:build && bundle exec jekyll build",
    "dev": "npm run js:watch & bundle exec jekyll serve --livereload"
  }
}

Benefits:

  • Minified JavaScript
  • Module support (import/export)
  • Source maps for debugging
  • Fast build times

Option B: Full (Webpack)

More powerful but more complex. Only if you need advanced features.

Recommendation: Start with esbuild. It’s fast and simple.

2. Testing Strategy

Current: No tests

Recommended: Add basic tests for JavaScript logic

Setup:

npm install --save-dev jest @testing-library/dom
// tests/mobile-menu.test.js
import { MobileMenu } from '../assets/js/mobile-menu.js';

describe('MobileMenu', () => {
  let toggle, menu;

  beforeEach(() => {
    document.body.innerHTML = `
      <button data-mobile-menu-toggle aria-expanded="false"></button>
      <nav data-mobile-menu class="site-nav"></nav>
    `;
    toggle = document.querySelector('[data-mobile-menu-toggle]');
    menu = document.querySelector('[data-mobile-menu]');
  });

  test('opens menu on click', () => {
    const mobileMenu = new MobileMenu(toggle, menu);
    toggle.click();

    expect(menu.classList.contains('is-open')).toBe(true);
    expect(toggle.getAttribute('aria-expanded')).toBe('true');
  });

  test('closes menu when clicking link', () => {
    const mobileMenu = new MobileMenu(toggle, menu);
    menu.innerHTML = '<a href="/work/">Work</a>';

    toggle.click(); // Open
    menu.querySelector('a').click(); // Click link

    expect(menu.classList.contains('is-open')).toBe(false);
  });
});

Benefits:

  • Catch bugs before deployment
  • Confidence when refactoring
  • Documentation through tests
  • Professional development practice

Recommendation: Start with tests for critical interactions (mobile menu, language switcher, project filtering).

3. Code Quality Tools

Recommended additions:

npm install --save-dev eslint prettier stylelint

ESLint config (.eslintrc.json):

{
  "env": {
    "browser": true,
    "es2021": true
  },
  "extends": "eslint:recommended",
  "parserOptions": {
    "ecmaVersion": 12,
    "sourceType": "module"
  },
  "rules": {
    "no-console": "warn",
    "no-unused-vars": "warn"
  }
}

Prettier config (.prettierrc):

{
  "semi": true,
  "singleQuote": true,
  "tabWidth": 2,
  "trailingComma": "es5"
}

Stylelint config (.stylelintrc.json):

{
  "extends": "stylelint-config-standard-scss",
  "rules": {
    "selector-class-pattern": null,
    "color-hex-length": "long"
  }
}

Add to package.json:

{
  "scripts": {
    "lint:js": "eslint assets/js/**/*.js",
    "lint:css": "stylelint _sass/**/*.scss",
    "lint": "npm run lint:js && npm run lint:css",
    "format": "prettier --write assets/js/**/*.js _sass/**/*.scss"
  }
}

Benefits:

  • Consistent code style
  • Catch common bugs
  • Auto-formatting saves time
  • Professional standard

Performance Optimizations

1. Font Loading Strategy

Current (default.html, lines 17-19):

<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Crimson+Text:ital,wght@0,400;0,600;1,400&family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">

Problem: Render-blocking, requires external requests

Better approach: Self-host with font-display

  1. Download fonts from Google Fonts
  2. Add to /assets/fonts/
  3. Use CSS @font-face:
// _sass/_typography.scss
@font-face {
  font-family: 'Inter';
  src: url('/assets/fonts/inter-var.woff2') format('woff2');
  font-weight: 100 900;
  font-display: swap; // Shows fallback immediately
}

@font-face {
  font-family: 'Crimson Text';
  src: url('/assets/fonts/crimson-text-regular.woff2') format('woff2');
  font-weight: 400;
  font-display: swap;
}

Benefits:

  • No external requests (faster)
  • Works offline
  • font-display: swap prevents invisible text
  • Full control over loading

Impact: ~200-400ms faster initial render

2. Image Optimization

Current: JPG/PNG files, lazy loading

Better: WebP with fallbacks, responsive images

<picture>
  <source srcset="/assets/images/project-image.webp" type="image/webp">
  <source srcset="/assets/images/project-image.jpg" type="image/jpeg">
  <img src="/assets/images/project-image.jpg"
       alt="Project screenshot"
       loading="lazy"
       width="800"
       height="600">
</picture>

Automated conversion:

npm install --save-dev sharp

# Convert images
node scripts/convert-images.js
// scripts/convert-images.js
const sharp = require('sharp');
const fs = require('fs');
const path = require('path');

const inputDir = './assets/images';
const files = fs.readdirSync(inputDir);

files.forEach(file => {
  if (file.match(/\.(jpg|png)$/)) {
    const input = path.join(inputDir, file);
    const output = path.join(inputDir, file.replace(/\.(jpg|png)$/, '.webp'));

    sharp(input)
      .webp({ quality: 80 })
      .toFile(output)
      .then(() => console.log(`Converted ${file} to WebP`));
  }
});

Benefits:

  • 30-50% smaller file sizes
  • Faster page loads
  • Better user experience

3. Critical CSS

Current: All CSS loads before render

Better: Inline critical CSS, defer non-critical

Extract critical CSS:

npm install --save-dev critical
// scripts/generate-critical-css.js
const critical = require('critical');

critical.generate({
  inline: true,
  base: '_site/',
  src: 'index.html',
  target: 'index-critical.html',
  width: 1300,
  height: 900
});

Result: Above-the-fold content styled immediately, rest loads async.

Impact: Improved First Contentful Paint (FCP)

Security Considerations

1. Content Security Policy

Add to _layouts/default.html:

<meta http-equiv="Content-Security-Policy"
      content="default-src 'self';
               script-src 'self' 'unsafe-inline';
               style-src 'self' 'unsafe-inline' fonts.googleapis.com;
               font-src 'self' fonts.gstatic.com;
               img-src 'self' data: https:;
               connect-src 'self';">

Adjust as needed for your external resources.

2. Form Security

If you add contact form:

<form action="..." method="POST">
  <input type="hidden" name="_csrf" value="">
  <!-- Form fields -->
</form>

Always validate server-side, even for static sites using form services.

From _layouts/default.html (line 146):


Good: You’re already using rel="noopener noreferrer" for external links.

Recommendation: Apply this to ALL external links consistently:


Code Review Checklist

Use this checklist for future code additions:

JavaScript

  • No inline scripts (use external files)
  • No global functions (use modules or IIFE)
  • Event listeners, not onclick attributes
  • No console.logs in production
  • Proper error handling
  • Accessible (ARIA, keyboard support)
  • Mobile-tested

HTML

  • Semantic elements (<nav>, <main>, <article>, etc.)
  • Proper heading hierarchy (h1 → h2 → h3)
  • Alt text on all images
  • Form labels associated with inputs
  • No duplicated IDs
  • Valid HTML (use validator.w3.org)

CSS/SCSS

  • Uses design system variables
  • No hardcoded colors/spacing
  • Mobile-first media queries
  • No !important (except utilities)
  • Consistent naming (BEM or similar)
  • No overly specific selectors (max 3 levels)

Accessibility

  • Color contrast passes WCAG AA (ideally AAA)
  • Keyboard navigable
  • Screen reader tested (use NVDA/JAWS)
  • Focus indicators visible
  • ARIA attributes where needed
  • Skip links on complex pages

Performance

  • Images optimized (WebP)
  • Images have width/height attributes
  • Lazy loading on below-fold images
  • CSS minified
  • JavaScript bundled and minified
  • No render-blocking resources

Action Plan: Technical Improvements

Week 1: Quick Fixes (4-6 hours)

Day 1: Remove console.logs (15 min)

  • Search for all console.log statements
  • Remove or add DEBUG flag

Day 2: Fix mobile menu accessibility (2 hours)

  • Add aria-expanded
  • Add aria-controls
  • Test with keyboard navigation
  • Test with screen reader

Day 3: Extract project filtering JavaScript (2 hours)

  • Create /assets/js/projects-filter.js
  • Move filtering logic from HTML
  • Update template to load new file

Day 4: Fix language switcher (2 hours)

  • Create _data/language_paths.yml
  • Simplify switchLanguage function
  • Test all language switches

Week 2: Architecture (8-10 hours)

Day 5: Set up build process (3 hours)

  • Install esbuild
  • Create build scripts
  • Test JavaScript bundling
  • Update deployment process

Day 6: Refactor mobile navigation (3 hours)

  • Remove duplicated nav markup
  • Create CSS-only show/hide
  • Refactor JavaScript to class-based
  • Test on multiple devices

Day 7: Code quality tools (2 hours)

  • Install ESLint, Prettier, Stylelint
  • Configure for your preferences
  • Run linters and fix issues
  • Add to npm scripts

Month 1: Major Improvements (16-20 hours)

Week 3: Testing setup (6 hours)

  • Install Jest
  • Write tests for mobile menu
  • Write tests for project filtering
  • Write tests for language switcher

Week 4: Performance optimization (6 hours)

  • Self-host fonts
  • Convert images to WebP
  • Implement responsive images
  • Generate critical CSS

Week 5: Module organization (6 hours)

  • Create proper JavaScript module structure
  • Separate concerns (UI, state, data)
  • Add JSDoc comments
  • Update documentation

Success Metrics (Technical)

Code Quality

Before:

  • 346 lines of inline JavaScript
  • 6 console.logs in production
  • No tests
  • No linting

After:

  • 0 lines of inline JavaScript
  • 0 console.logs in production
  • 80%+ test coverage on critical features
  • ESLint/Prettier configured and passing

Performance

Before (estimated):

  • Lighthouse: 85-90
  • FCP: 1.5-2s
  • LCP: 2.5-3s

After (potential):

  • Lighthouse: 95-100
  • FCP: < 1s
  • LCP: < 2s

Maintainability

Before:

  • Adding a page requires updating 3 places
  • JavaScript mixed with HTML
  • No tests to catch regressions

After:

  • Adding a page requires updating 1 data file
  • Clean separation of concerns
  • Tests catch breaking changes

Final Thoughts

Your technical implementation is already good. These improvements are about going from good to excellent.

Priority ranking:

  1. High Impact, Low Effort: Remove console.logs, fix mobile menu accessibility
  2. High Impact, Medium Effort: Extract JavaScript to files, refactor navigation
  3. Medium Impact, Medium Effort: Set up build process, add linting
  4. Lower Impact, Higher Effort: Testing setup, performance optimizations

Start with #1. You’ll see immediate improvement in code professionalism.

The architecture improvements (#2-4) are investments in maintainability. They pay off when you:

  • Add new features
  • Fix bugs
  • Collaborate with others
  • Come back to the code after months

You write clean code. Now make it maintainable code, and your portfolio will be technically impressive in addition to functionally solid.