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
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
- Windows: Ruby+Devkit from RubyInstaller
- macOS:
brew install ruby - Linux:
sudo apt-get install -y ruby-full build-essential zlib1g-dev
Then install Bundler:
gem install bundler-
Clone the repository:
git clone https://github.com/jvlevinson/modern_jekyll.git cd modern_jekyll -
Install dependencies:
bundle install
-
Serve locally:
bundle exec jekyll serveOpen http://localhost:4000 in your browser.
-
Serve with live reload:
bundle exec jekyll serve --livereload
Take a look at the ELI5.README.md file for a quick overview of the project.
This project follows Jekyll best practices with a fully tokenized, modular architecture that separates content from presentation.
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
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.jpgEach page section lives in its own include file (_includes/):
header.html→ Hero section with configurable background imageservices.html→ Services grid (loops throughsite.services.list)portfolio.html→ Portfolio grid with flip animations (loops throughsite.portfolio_items)resume.html→ Resume download sectioncontact.html→ Contact section with social linksfooter.html→ Footer with copyrightnav.html→ Navigation with theme toggle button
These components are:
- Reusable - Include anywhere in any layout
- Composable - Reorder by changing include order in
_layouts/front.html - Self-contained - Each manages its own markup and styling
- Data-driven - All content pulled from
_config.yml
✅ 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
All site content is managed through _config.yml. No need to edit HTML files!
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: yourhandlebrand_name: Your Brand # Top-left navbar brand🎨 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.
- orange - Warm, energetic (#f97316)
- blue - Professional, trustworthy (#3b82f6)
- green - Fresh, growth-oriented (#22c55e)
- purple - Creative, sophisticated (#a855f7)
- red - Bold, attention-grabbing (#ef4444)
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, autoThen rebuild your site:
bundle exec jekyll buildThat's it! All buttons, links, navigation, portfolio overlays, and the favicon will automatically use your chosen colors.
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.
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
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.
- ✅ 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", andmode: "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
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 imageTechnical 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
cta:
heading: Section heading
description: Longer description text
button_text: Button text
button_link: "#services"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: .1sAvailable Font Awesome Icons: See Font Awesome 6 Free icons
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 projectInteractive 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:
heading: Resume & Credentials
description: Download my complete resume...
file_path: /public/files/your-resume.pdf
view_button_text: View Resume
download_button_text: Download ResumeA prominent call-out section:
aside:
heading: Explore My Full Portfolio
button_text: More Coming Soon!
button_link: "https://yoursite.com"contact:
heading: Let's Get In Touch!
description: Contact prompt or additional infoSocial links (Twitter, Email, GitHub, LinkedIn) are shown automatically using the usernames defined at the top of _config.yml.
footer:
copyright: Your Name
year: 2025.
├── _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.
This project uses the 7-1 Pattern with modern Sass module system (@use/@forward):
- No deprecation warnings - Uses
color.adjust()instead of deprecateddarken() - 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
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
- Reads color selection from
Your Custom Styles (Modular):
css/main.scss→ Compiles tomain.css_sass/→ Modular SCSS architecture (7-1 pattern)abstracts/- Variables, functions, mixins (now includes token documentation)base/- Reset, typography, utilitiescomponents/- Buttons, service boxes, portfolio boxes with flip animations, theme togglelayout/- Navigation with glassmorphism, header, sections, contactpages/- Page-specific stylesvendors/- 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
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 -
addEventListenerinstead 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
This project includes comprehensive QA tools for maintaining code quality and preventing regressions.
JSON Schema validation ensures _config.yml is correct before deployment:
pnpm run validate:configFeatures:
- 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)
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 reportTests 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
axe-core ensures WCAG 2.1 AA compliance:
pnpm run test:a11yChecks:
- 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
pnpm testRuns config validation, visual regression tests, and accessibility audit in sequence.
The build script automatically validates config before building:
pnpm run build # Runs validate:config first- 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.
This site supports both user sites (username.github.io) and project sites (username.github.io/repo-name).
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:
- Go to your repository on GitHub
- Navigate to Settings → Pages
- Under Build and deployment, select GitHub Actions (not "Deploy from branch")
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 exactlygit add .
git commit -m "Deploy site to GitHub Pages"
git push origin main # Push to main branch (triggers GitHub Actions)GitHub Actions will automatically:
- Build the Jekyll site with modern Sass compilation
- 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!
- Add your image to
img/portfolio/(recommended size: 650x350px) - Update
_config.ymlportfolio_items section with the new item - 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 flippedThe site includes a blue "W" SVG favicon by default. To customize:
- Create your favicon (SVG, ICO, or PNG)
- Place it in
img/directory - Update
_config.yml:favicon: img/your-custom-favicon.svg
SVG favicons are recommended for scalability and theme integration.
For advanced users who want colors not in the pre-defined palettes:
- Add a new palette to
_data/color-palettes.yml(system file) - Follow the same structure as existing palettes (shades 50-900)
- Reference your custom palette name in
theme.brand_primaryortheme.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.
"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 ""
- Option 1: Visit
404 Error on GitHub Pages
- ✅ GitHub Pages enabled: Settings → Pages → Source: "GitHub Actions"
- ✅ Branch is correct: Workflow triggers on
mainbranch (push tomainto deploy) - ✅ Workflow file exists:
.github/workflows/jekyll.ymlis present - ✅ URLs match: For user site use
baseurl: "", for project site usebaseurl: "/repo-name"
CSS/JS/Images don't load on GitHub Pages
- Check that
baseurlin_config.ymlmatches your deployment type - Verify all asset links use
| relative_urlfilter in templates - Check browser console for 404 errors
GitHub Actions build fails
- Check the Actions tab for error details
- Common issues:
- Missing
Gemfileor syntax errors in_config.yml - Image paths pointing to non-existent files
- SCSS compilation errors (check build logs)
- Missing
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.jsis loading - Try clearing localStorage:
localStorage.clear()in browser console
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
- Jekyll: Static site generator - jekyllrb.com
- Creative Theme: Start Bootstrap - startbootstrap.com
- Bootstrap: Front-end framework - getbootstrap.com
- Font Awesome: Icon library - fontawesome.com
See LICENSE file for details.