Skip to content

Repository files navigation

Personal Profile Site

A personal portfolio website built with Jekyll 4.4+ using the Creative Theme from Start Bootstrap. This is a fully customizable, single-page Bootstrap site with a modern, tokenized configuration system and advanced theming capabilities.

✨ Key Features:

  • Fully tokenized configuration - All content managed through _config.yml
  • User-customizable theming - Choose colors and light/dark modes without touching CSS
  • Theme toggle button - Manual theme switcher with localStorage persistence
  • Modern modular SCSS architecture - 7-1 pattern with Sass modules (@use/@forward)
  • Bootstrap 5.3.8 with responsive design
  • Vanilla JavaScript - No jQuery dependencies (2025 best practices)
  • Font Awesome 6.7.2 icons
  • Interactive portfolio - Flip animations with hover indicators
  • Glassmorphism navbar - Blur effects for modern UI
  • SVG favicon - Customizable brand icon
  • GitHub Pages ready - Automated deployment

🔗 Live Site: https://williammorr.com


Quick Start

Prerequisites

You'll need these installed on your machine:

Git

  • Windows: Git for Windows
  • macOS: xcode-select --install
  • Linux: sudo apt-get install -y git

Ruby + Bundler

Then install Bundler:

gem install bundler

Local Development

  1. Clone the repository:

    git clone https://github.com/jvlevinson/modern_jekyll.git
    cd modern_jekyll
  2. Install dependencies:

    bundle install
  3. Serve locally:

    bundle exec jekyll serve

    Open http://localhost:4000 in your browser.

  4. Serve with live reload:

    bundle exec jekyll serve --livereload

Not a Developer?

Take a look at the ELI5.README.md file for a quick overview of the project.


Architecture: Tokenization & Modularity

This project follows Jekyll best practices with a fully tokenized, modular architecture that separates content from presentation.

Why Tokenization?

Traditional static sites hard-code content directly into HTML templates, making updates tedious and error-prone. This site uses Liquid template variables to pull all content from a central configuration file (_config.yml), providing:

  • Single source of truth - All content in one place
  • Zero HTML editing - Update text, images, and links without touching templates
  • Type safety - Structured YAML prevents formatting errors
  • Version control friendly - Content changes are clearly visible in diffs
  • Rapid customization - Fork, edit config, deploy

How It Works

Traditional approach (❌ Hard-coded):

<h1>Your Favorite Source of Free Bootstrap Themes</h1>
<p>Start Bootstrap can help you build...</p>

This project (✅ Tokenized):

<h1>{{ site.hero.heading }}</h1>
<p>{{ site.hero.description }}</p>

Configuration (_config.yml):

hero:
  heading: Your Favorite Source of Free Bootstrap Themes
  description: Start Bootstrap can help you build...
  background_image: img/header.jpg

Modular Components

Each page section lives in its own include file (_includes/):

  • header.html → Hero section with configurable background image
  • services.html → Services grid (loops through site.services.list)
  • portfolio.html → Portfolio grid with flip animations (loops through site.portfolio_items)
  • resume.html → Resume download section
  • contact.html → Contact section with social links
  • footer.html → Footer with copyright
  • nav.html → Navigation with theme toggle button

These components are:

  1. Reusable - Include anywhere in any layout
  2. Composable - Reorder by changing include order in _layouts/front.html
  3. Self-contained - Each manages its own markup and styling
  4. Data-driven - All content pulled from _config.yml

Benefits

✅ No code knowledge required - Edit YAML, not HTML ✅ Maintainable - Update content without breaking markup ✅ Scalable - Add portfolio items, services, etc. as array entries ✅ Static & fast - No database, all compiled at build time ✅ GitHub Pages compatible - Uses only standard Jekyll features


Customization

All site content is managed through _config.yml. No need to edit HTML files!

Site Metadata

title: Your Site Title
email: your-email@example.com
description: 'Your site description'
author: Your Name
favicon: img/favicon.svg          # Path to favicon (SVG supported!)
twitter_username: yourhandle
github_username: yourhandle
linkedin_username: yourhandle

Navigation

brand_name: Your Brand              # Top-left navbar brand

Color Theme & Dark Mode

🎨 User-Customizable Color Theming System

Your site supports easy color customization and light/dark themes! Choose from 5 pre-defined color palettes without editing any CSS.

Available Color Palettes

  • orange - Warm, energetic (#f97316)
  • blue - Professional, trustworthy (#3b82f6)
  • green - Fresh, growth-oriented (#22c55e)
  • purple - Creative, sophisticated (#a855f7)
  • red - Bold, attention-grabbing (#ef4444)

How to Change Colors & Theme Mode

Edit the theme section in _config.yml:

theme:
  brand_primary: "blue"          # Main brand color
  brand_secondary: "green"       # Optional accent color (or null)
  neutral: "slate"               # Text/backgrounds - Choose: slate, gray
  mode: "light"                  # Choose: light, dark, auto

Then rebuild your site:

bundle exec jekyll build

That's it! All buttons, links, navigation, portfolio overlays, and the favicon will automatically use your chosen colors.

Theme Modes

The theming system supports three modes:

  • light - Always display light theme (white background, dark text)
  • dark - Always display dark theme (dark background, light text)
  • auto - Automatically respect user's OS/browser theme preference

Theme Toggle Button: Users can manually switch themes using the sun/moon icon button in the navigation bar. Their preference is saved in localStorage and persists across sessions.

Link Styling: Both light and dark themes use consistent hover behavior - links change color on hover with no underlines, providing a clean, modern user experience across all theme modes.

Separation of Concerns

The theming system separates user configuration from system files:

User Configuration (_config.yml):

  • ✅ Simple color selection (brand_primary, brand_secondary, neutral, mode)
  • ✅ No technical knowledge required
  • ✅ Clear options and comments

System Files (not user-editable):

  • _data/color-palettes.yml - Color palette library (5 palettes × 10 shades each)
  • _includes/design-tokens.html - Dynamic token generation logic
  • _sass/ - Component styles using semantic tokens

Under the Hood

The theming system uses:

  • Color Palette Library - 5 palettes × 10 shades each (50-900) in _data/color-palettes.yml
  • Liquid Template Engine - Resolves user selection to CSS custom properties
  • Semantic Tokens - Components reference meaningful names (--color-primary, --color-text, --navbar-bg)
  • CSS Custom Properties - Runtime theming without recompilation
  • JavaScript Theme Toggle - Manual theme switching with localStorage persistence

See _includes/design-tokens.html for the full token architecture.

Implementation Status

  • ✅ Phase 1 (Complete): Color palette selection system
  • ✅ Phase 2 (Complete): Multi-color support (5 palettes)
  • ✅ Phase 3 (Complete): Dark theme support with mode: "light", mode: "dark", and mode: "auto"
  • ✅ Phase 4 (Complete): Theme toggle button with localStorage persistence
  • ✅ Phase 5 (Complete): Quality Assurance with JSON Schema validation, Playwright visual regression testing, and WCAG 2.1 AA compliance

Hero Section

The landing section with heading, description, and configurable background:

hero:
  heading: Your main headline
  description: Your tagline or description
  button_text: Call to Action
  button_link: "#about"              # Anchor link or URL
  background_image: img/header.jpg   # Configurable background image

Technical Details:

  • Full viewport height on desktop (min-height: 100vh) for immersive hero experience
  • Responsive mobile layout with auto height
  • Configurable overlay for text contrast in dark mode

Call-to-Action Section

cta:
  heading: Section heading
  description: Longer description text
  button_text: Button text
  button_link: "#services"

Services Section

Define your services or skills:

services:
  heading: Services Heading
  list:
    - icon: fa-diamond              # Font Awesome icon
      title: Service Name
      description: Service description
      delay: 0                      # Animation delay
    - icon: fa-paper-plane
      title: Another Service
      description: Another description
      delay: .1s

Available Font Awesome Icons: See Font Awesome 6 Free icons

Portfolio Section

Showcase projects with flip animations and hover effects:

portfolio_heading: My Work          # Optional section heading
portfolio_items:
  - image: img/portfolio/1.jpg      # Image path
    category: Project Type
    name: Project Name
    link: "#"                       # Project URL or anchor
    flip_description: Detailed description shown on back of card when clicked
  - image: img/portfolio/2.jpg
    category: Another Type
    name: Another Project
    link: "https://example.com"
    flip_description: More details about this project

Interactive Features:

  • Click to flip - Cards flip to show detailed description
  • Hover indicators - Animated corner brackets and "Click to flip" text
  • Responsive - Works on all screen sizes

Add your images to img/portfolio/ and reference them here.

Resume Section

resume:
  heading: Resume & Credentials
  description: Download my complete resume...
  file_path: /public/files/your-resume.pdf
  view_button_text: View Resume
  download_button_text: Download Resume

Aside Section

A prominent call-out section:

aside:
  heading: Explore My Full Portfolio
  button_text: More Coming Soon!
  button_link: "https://yoursite.com"

Contact Section

contact:
  heading: Let's Get In Touch!
  description: Contact prompt or additional info

Social links (Twitter, Email, GitHub, LinkedIn) are shown automatically using the usernames defined at the top of _config.yml.

Footer Section

footer:
  copyright: Your Name
  year: 2025

Site Structure

.
├── _includes/          # Reusable HTML components
│   ├── head.html       # <head> metadata with favicon support
│   ├── nav.html        # Navigation bar with theme toggle
│   ├── header.html     # Hero section with configurable background
│   ├── call-to-action.html
│   ├── services.html   # Services grid
│   ├── portfolio.html  # Portfolio grid with flip animations
│   ├── resume.html     # Resume download section
│   ├── aside.html      # CTA aside
│   ├── contact.html    # Contact section
│   ├── footer.html     # Footer
│   ├── design-tokens.html  # Dynamic color token generator
│   └── scripts.html    # JavaScript includes
├── _layouts/
│   └── front.html      # Main layout composing all sections
├── _sass/              # Modern SCSS architecture (7-1 pattern)
│   ├── abstracts/      # Variables, functions, mixins
│   ├── base/           # Reset, typography, utilities
│   ├── components/     # Buttons, service-box, portfolio-box, theme-toggle
│   ├── layout/         # Navigation, header, sections, contact
│   ├── pages/          # Page-specific styles
│   └── vendors/        # Bootstrap overrides
├── _data/
│   └── color-palettes.yml  # System color palette library
├── css/
│   └── main.scss       # Master stylesheet (uses @use/@forward)
├── img/                # Images and graphics
│   ├── favicon.svg     # SVG favicon (blue "W" icon)
│   ├── header.jpg      # Hero background image
│   └── portfolio/      # Portfolio images
├── js/
│   ├── creative.js     # Custom scripts (vanilla JS, no jQuery!)
│   └── wow.min.js      # Scroll animations
├── _config.yml         # Site configuration (edit this!)
├── Gemfile             # Ruby dependencies
├── CLAUDE.md           # Claude Code AI assistant instructions
├── THEMING.md          # Detailed theming documentation
└── index.html          # Entry point

To reorder or remove sections: Edit _layouts/front.html and rearrange the {% include %} statements.

Modern SCSS Architecture

This project uses the 7-1 Pattern with modern Sass module system (@use/@forward):

  • No deprecation warnings - Uses color.adjust() instead of deprecated darken()
  • CSS Custom Properties - Runtime theming support for light/dark modes
  • Modular & maintainable - Each component in its own file
  • ✅ BEM Architecture - All components use BEM naming convention (.btn--primary, .service-box__icon, .portfolio-box--flippable)
  • Bootstrap 5 compatible - Modern grid and components
  • User-Customizable Colors - Choose from 5 color palettes via _config.yml
  • Glassmorphism Effects - Navbar with backdrop-filter blur

CSS File Structure

Design Tokens (Dynamic):

  • _includes/design-tokens.html → Generates CSS custom properties from user theme selection
    • Reads color selection from _config.yml (brand_primary, brand_secondary, neutral, mode)
    • Resolves palettes from _data/color-palettes.yml (system file)
    • Creates 30+ CSS custom properties including:
      • Color scales (--color-primary-50 through --color-primary-900)
      • Semantic tokens (--color-primary, --color-secondary, --color-text, --bg-dark, --navbar-bg)
      • Theme-aware tokens that invert for dark mode
    • Injected into <head> before main.css for proper cascade

Your Custom Styles (Modular):

  • css/main.scss → Compiles to main.css
  • _sass/ → Modular SCSS architecture (7-1 pattern)
    • abstracts/ - Variables, functions, mixins (now includes token documentation)
    • base/ - Reset, typography, utilities
    • components/ - Buttons, service boxes, portfolio boxes with flip animations, theme toggle
    • layout/ - Navigation with glassmorphism, header, sections, contact
    • pages/ - Page-specific styles
    • vendors/ - Bootstrap 5 overrides

Third-Party Libraries (CDN):

  • Bootstrap 5.3.8 - Framework via CDN (no local files)
  • Font Awesome 6.7.2 - Icons via CDN (no local files)

Vendor CSS (Local):

  • css/animate.min.css - Animate.css library for WOW.js animations
    • Not modularized - Third-party library kept separate per best practices

JavaScript Architecture

Modern Vanilla JavaScript (No jQuery!)

The site uses pure vanilla JavaScript following 2025 best practices:

  • ✅ No jQuery dependency - Removed for performance and modern standards
  • ✅ Bootstrap 5 native APIs - Uses built-in ScrollSpy, Collapse, etc.
  • ✅ Native smooth scrolling - window.scrollTo({ behavior: 'smooth' })
  • ✅ Modern event listeners - addEventListener instead of jQuery .on()
  • ✅ localStorage with fallbacks - Private browsing detection with graceful degradation

Features in js/creative.js:

  • Smooth scroll navigation
  • Sticky navbar with glassmorphism
  • Mobile menu auto-close
  • Responsive text sizing
  • Portfolio flip animations
  • Theme toggle with persistence
  • WOW.js scroll animations

Testing & Quality Assurance

This project includes comprehensive QA tools for maintaining code quality and preventing regressions.

Config Validation

JSON Schema validation ensures _config.yml is correct before deployment:

pnpm run validate:config

Features:

  • Validates all required fields (title, email, theme settings)
  • Checks color palette names (orange, blue, green, purple, red)
  • Validates theme mode (light, dark, auto)
  • Enforces email format, URL structure
  • Colorful terminal output with helpful error messages

Schema: _data/config-schema.json (114 lines, comprehensive validation)

Visual Regression Testing

Playwright tests ensure UI consistency across browsers:

pnpm run test:visual           # Run all visual tests
pnpm run test:visual:update    # Update baseline screenshots
pnpm run test:visual:ui        # Interactive UI mode
pnpm run test:visual:report    # View latest report

Tests include:

  • Homepage rendering (light/dark themes)
  • Navigation scroll behavior
  • Portfolio flip animations
  • Button hover states
  • Mobile responsive layouts
  • Theme toggle functionality

Browsers tested: Chrome, Firefox, Safari, Mobile Chrome, Mobile Safari

Accessibility Testing

axe-core ensures WCAG 2.1 AA compliance:

pnpm run test:a11y

Checks:

  • ARIA landmarks (role="banner", role="main", role="navigation", role="contentinfo")
  • Color contrast ratios (4.5:1 minimum)
  • Keyboard navigation
  • Screen reader compatibility
  • Semantic HTML structure

Run All Tests

pnpm test

Runs config validation, visual regression tests, and accessibility audit in sequence.

Pre-Build Validation

The build script automatically validates config before building:

pnpm run build  # Runs validate:config first

Why These Tools?

  • Playwright - Microsoft-backed, industry standard with huge community
  • AJV - Most popular JSON Schema validator (used by major frameworks)
  • axe-core - Powers Google Lighthouse accessibility tests
  • pnpm - Fast, disk-efficient package manager (2025 best practice)

All tools chosen for open source compatibility, active maintenance, and ease of use.


Deploying to GitHub Pages

This site supports both user sites (username.github.io) and project sites (username.github.io/repo-name).

Automated Deployment (Recommended)

The repository includes a GitHub Actions workflow (.github/workflows/jekyll.yml) that automatically builds and deploys your site on every push to the main branch.

Setup Steps:

Step 1: Enable GitHub Pages

  1. Go to your repository on GitHub
  2. Navigate to Settings → Pages
  3. Under Build and deployment, select GitHub Actions (not "Deploy from branch")

Step 2: Configure URLs

For a user site (williammorr.github.io):

# _config.yml
url: "https://williammorr.github.io"
baseurl: ""

For a project site (williammorr.github.io/Personal-Profile):

# _config.yml
url: "https://williammorr.github.io"
baseurl: "/Personal-Profile"  # Must match repo name exactly

Step 3: Push Changes

git add .
git commit -m "Deploy site to GitHub Pages"
git push origin main  # Push to main branch (triggers GitHub Actions)

GitHub Actions will automatically:

  1. Build the Jekyll site with modern Sass compilation
  2. Deploy to GitHub Pages

Monitor progress: Check the Actions tab in your repository for build status.

Once the workflow completes (✅ green checkmark), your site will be live!


Adding New Portfolio Images

  1. Add your image to img/portfolio/ (recommended size: 650x350px)
  2. Update _config.yml portfolio_items section with the new item
  3. Commit and push

Example:

portfolio_items:
  - image: img/portfolio/my-new-project.jpg
    category: Web Development
    name: My Awesome Project
    link: "https://github.com/williammorr/my-project"
    flip_description: Detailed description of the project shown when card is flipped

Advanced Customization

Custom Favicon

The site includes a blue "W" SVG favicon by default. To customize:

  1. Create your favicon (SVG, ICO, or PNG)
  2. Place it in img/ directory
  3. Update _config.yml:
    favicon: img/your-custom-favicon.svg

SVG favicons are recommended for scalability and theme integration.

Custom Colors

For advanced users who want colors not in the pre-defined palettes:

  1. Add a new palette to _data/color-palettes.yml (system file)
  2. Follow the same structure as existing palettes (shades 50-900)
  3. Reference your custom palette name in theme.brand_primary or theme.brand_secondary

Example (_data/color-palettes.yml):

teal:
  50: "#f0fdfa"
  100: "#ccfbf1"
  # ... continue with 200-800
  500: "#14b8a6"    # Base color
  900: "#134e4a"

Then use in _config.yml:

theme:
  brand_primary: "teal"

See _includes/design-tokens.html for the complete token architecture.


Troubleshooting

Local Development Issues

"Could not locate Gemfile"

  • Make sure you're in the project directory
  • Run bundle install

"bundle: command not found"

  • Bundler isn't installed. Run gem install bundler

Site builds but CSS/images don't load locally

  • If using project site config with baseurl: "/Personal-Profile":
    • Option 1: Visit http://localhost:4000/Personal-Profile/
    • Option 2: Serve with: bundle exec jekyll serve --baseurl ""

GitHub Pages Deployment Issues

404 Error on GitHub Pages

  • ✅ GitHub Pages enabled: Settings → Pages → Source: "GitHub Actions"
  • ✅ Branch is correct: Workflow triggers on main branch (push to main to deploy)
  • ✅ Workflow file exists: .github/workflows/jekyll.yml is present
  • ✅ URLs match: For user site use baseurl: "", for project site use baseurl: "/repo-name"

CSS/JS/Images don't load on GitHub Pages

  • Check that baseurl in _config.yml matches your deployment type
  • Verify all asset links use | relative_url filter in templates
  • Check browser console for 404 errors

GitHub Actions build fails

  • Check the Actions tab for error details
  • Common issues:
    • Missing Gemfile or syntax errors in _config.yml
    • Image paths pointing to non-existent files
    • SCSS compilation errors (check build logs)

Changes not appearing on live site

  • Wait 1-2 minutes for GitHub Actions to rebuild
  • Check the Actions tab to verify build succeeded (green checkmark)
  • Hard refresh your browser (Ctrl+Shift+R or Cmd+Shift+R)
  • Clear browser cache or use private/incognito window

Theme toggle not working

  • Check browser console for JavaScript errors
  • Verify js/creative.js is loading
  • Try clearing localStorage: localStorage.clear() in browser console

Technology Stack

Core Technologies:

  • Jekyll 4.4+ - Static site generator
  • Bootstrap 5.3.8 - Front-end framework (CDN)
  • Sass/SCSS - CSS preprocessor with modern module system (@use/@forward)
  • Liquid - Templating engine
  • Font Awesome 6.7.2 - Icon library (CDN)
  • Vanilla JavaScript - No dependencies (jQuery removed)
  • WOW.js - Scroll reveal animations
  • GitHub Actions - Automated deployment

Quality Assurance Tools:

  • Playwright 1.40+ - Visual regression testing across 5 browsers
  • AJV 8.12+ - JSON Schema validation for config files
  • axe-core 4.8+ - WCAG 2.1 AA accessibility compliance testing
  • pnpm - Fast, disk-efficient package manager

Credits


License

See LICENSE file for details.

Releases

Packages

Used by

Contributors

Languages