Web HTML CSS JavaScript Tutorial

How I Built My Portfolio Website

An in-depth review of the development process for this website — exploring semantic HTML structure, dynamic layout rendering using custom CSS tokens, client-side live search, and search engine optimization.

Article Summary

Personal websites often suffer from build-tool bloat. By bypassing frameworks and building this site using raw HTML, vanilla CSS, and simple vanilla JavaScript, we achieve nearly perfect performance metrics, total search engine indexability, and clean code that is easy to extend.

1. Philosophical Foundation: No Frameworks

In modern web development, standard practice calls for React, Next.js, or TailwindCSS, even for simple informational sites. For a personal digital portfolio, these frameworks introduce overhead: larger download footprints, Hydration latency, and fragile dependency trees that break after a few years of inactivity.

This website was intentionally built to be zero-dependency:

  • No build steps: The raw HTML files served to visitors are the exact source files checked into version control.
  • Vanilla styling: Pure CSS stylesheets structured around Custom Properties (CSS variables) organize spacing, typography, and dark/light modes.
  • Vanilla script behavior: Responsive menus, scrolling progress, and live site searches are implemented in native modern JavaScript.

2. Designing with CSS Variables

To avoid Tailwind or Sass preprocessors, we structured main.css around CSS custom properties inside a :root scope. This allows global changes to colors, font sizes, and layout gaps from a single location:

:root {
  /* Color Palette */
  --bg-primary: #0b0f19;
  --bg-surface: #111827;
  --bg-surface-elevated: #1f2937;
  --text-primary: #f3f4f6;
  --text-secondary: #9ca3af;
  --text-muted: #6b7280;
  --color-primary: #6366f1;
  --color-primary-hover: #4f46e5;
  
  /* Font Family Tokens */
  --font-body: 'Inter', system-ui, -apple-system, sans-serif;
  --font-display: 'Outfit', var(--font-body);
  
  /* Spacing Scale (8px Grid) */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-4: 1rem;
  --space-6: 1.5rem;
  --space-8: 2rem;
  --space-12: 3rem;
}

Because CSS custom properties are calculated dynamically in the browser, changing themes or layout styles is as simple as toggling a class on the root element.

3. Client-Side Live Search Engine

Without an active server backend, how do we implement a live search box across projects, research articles, and blog entries? We store search data inside a simple data/site.json (or read the DOM structure directly) and index it client-side:

// Client-side search implementation
async function performSearch(query) {
  const response = await fetch('/data/site.json');
  const index = await response.json();
  const searchResults = [];
  
  const cleanQuery = query.toLowerCase().trim();
  if (!cleanQuery) return [];
  
  for (const item of index.documents) {
    const titleMatch = item.title.toLowerCase().includes(cleanQuery);
    const descMatch = item.description.toLowerCase().includes(cleanQuery);
    const contentMatch = item.content ? item.content.toLowerCase().includes(cleanQuery) : false;
    
    if (titleMatch || descMatch || contentMatch) {
      let score = 0;
      if (titleMatch) score += 10;
      if (descMatch) score += 5;
      if (contentMatch) score += 2;
      searchResults.push({ ...item, score });
    }
  }
  
  return searchResults.sort((a, b) => b.score - a.score);
}

This avoids hosting databases or paying for third-party SaaS indexing solutions while returning results in milliseconds.

4. SEO & Structured Metadata

To ensure maximum visibility on search engines, every page on the site implements strict metadata tags, canonical URLs, and Google-readable schema types:

  • Breadcrumbs Navigation: Provides semantic microdata links (using schema.org microdata arrays) so search robots understand structural depth.
  • JSON-LD Structured Data: Injects metadata (such as BlogPosting, SoftwareApplication, or ScholarlyArticle) directly into page headers.
  • Open Graph & Twitter Meta: Curates specific title, image, and description overrides to format previews cleanly when shared on social networks.

5. Performance & Verification

Bypassing complex client frameworks results in excellent speed metrics under Chrome Lighthouse audits:

Lighthouse Category Score achieved Metric Detail
Performance 100 / 100 First Contentful Paint: 0.2s
Accessibility 100 / 100 Strict contrast, screen reader aria attributes
Best Practices 100 / 100 HTTPS, no unsafe script execution, modern libraries
SEO 100 / 100 Valid structured schemas, canonical links, descriptive tags

6. Future Evolution

As the lab expands, we intend to implement a small static building step in Python or Rust to automatically generate data/site.json indexes and compile HTML template files, maintaining our zero-dependency stance for the browser client.