A stunning, fully customizable portfolio website inspired by Sony PlayStation 3's iconic XrossMediaBar (XMB) interface. Built with dynamic configuration, WebGL shaders, responsive design, and an integrated blog system.
- 🎯 Authentic XMB Navigation - Faithful recreation of PS3's horizontal/vertical menu system
- 🔧 Dynamic Configuration - Fully customizable through environment variables and JSON files
- 🎛️ Unlimited Menu Items - Add/remove menu sections and items without touching code
- 🌊 Configurable WebGL Backgrounds - Customizable colors, animations, and effects
- 📝 Integrated Blog System - Markdown-powered blog posts with automated GitHub Actions indexing
- 🤖 Automated Blog Indexing - GitHub Actions automatically generates blog post index (no API rate limits!)
- 📱 Smart Mobile Positioning - Intelligent menu centering that keeps active items and submenus visible
- 🖱️ Mousewheel Navigation - Scroll through submenu items with mousewheel on desktop
- 📱 Cross-Platform Responsive - Optimized for desktop, mobile, and tablet with touch support
- ⌨️ Multiple Input Methods - Keyboard arrows, touch gestures, mouse clicks, and mousewheel
- 🚀 Zero-Code Customization - Change everything through configuration files
# Clone and navigate
git clone https://github.com/jetsharklambo/xmbfolio.git
cd xmbfolio/
# Serve locally (required for dynamic loading)
python3 -m http.server 8000
# OR
npx serve .
# Open http://localhost:8000# Clone and navigate
git clone https://github.com/jetsharklambo/xmbfolio.git
cd xmbfolio/v4
# Copy configuration template
cp .env.example .env
# Edit .env with your information (see Configuration section below)
nano .env
# Install build dependencies (optional)
npm install
# Build with your configuration
npm run build
# Serve the customized site
npm run servev4/
├── index.html # Main entry point
├── config.js # Configuration system
├── main.js # Core navigation logic with mousewheel support
├── menu-system.js # Dynamic menu loader
├── blog-system.js # Static JSON blog integration (no API rate limits!)
├── mesh-gradient.js # WebGL shader backgrounds
├── menu-config.js # Menu positioning config with submenu focus settings
├── menu-position-manager.js # Cross-platform positioning system
├── menu-focus-manager.js # Smart mobile submenu positioning (NEW!)
├── menu-control-panel.js # Debug controls (hidden on mobile)
├── menu-debug.js # Debug overlay and visualization
├── style.css # Responsive styling with mobile improvements
├── menu-structure.json # Dynamic menu configuration
├── .env.example # Configuration template
├── build.js # Build script for environment variables
├── package.json # NPM scripts and dependencies
├── SETUP.md # Detailed setup guide
├── .github/
│ └── workflows/
│ └── generate-blog-index.yml # Automated blog indexing (NEW!)
├── scripts/
│ ├── generate-blog-index.js # Blog index generator (NEW!)
│ └── package.json # Script dependencies
└── blog/ # Markdown blog posts
├── 2024-12-01-vibecode-journey.md
└── 2024-12-15-saltfree-story.md
# Personal Information
SITE_TITLE="Your Name"
USERNAME="yourhandle"
BIO_URL="https://yourwebsite.com"
# Social Links
GITHUB_USERNAME="yourusername"
TWITTER_HANDLE="yourhandle"
FARCASTER_USERNAME="yourhandle"
# Visual Customization
PRIMARY_COLORS="#000000,#1a3b1a,#2d5a27,#0f1f0f"
SECONDARY_COLORS="#0f1f0f,#1a3b1a,#2d5a27,#4a7c59"
GRADIENT_SPEED="0.3"
GRADIENT_DISTORTION="0.8"
# Blog System
ENABLE_BLOG="true"
BLOG_GITHUB_REPO="yourusername/yourrepo"The menu structure is completely customizable. Edit menu-structure.json to:
- Add unlimited menu sections
- Customize social links
- Add project portfolios
- Create custom categories
Example menu item:
{
"id": "projects",
"title": "My Projects",
"icon": "folder",
"description": "What I've Built",
"subItems": [
{
"name": "Cool App",
"url": "https://mycoolapp.com",
"icon": "rocket",
"action": "external_link"
}
]
}- File is served locally -
menu-structure.jsonloads from the same directory - No GitHub needed - Works immediately for testing and development
- Perfect for customization - Edit files and see changes instantly
- Push to GitHub - Commit
menu-structure.jsonto your repository - Dynamic loading - Menu loads from GitHub API automatically
- Live updates - Change menu by editing GitHub files (no redeploy needed)
- Environment variables - Set all config in hosting platform
- Build process - Run
npm run buildto generate configuration - Deploy anywhere - Works on Vercel, Netlify, GitHub Pages, etc.
- On page load - Menu system checks for
menu-structure.json - Try local first - Loads from same directory if available
- Fallback to GitHub - Uses GitHub API if local file not found
- Fallback to defaults - Uses hardcoded menu if both fail
- Template variables - Replaces
{username},{github.username}, etc.
Edit menu-structure.json to add unlimited:
- Social platforms (Twitter, LinkedIn, Instagram, etc.)
- Project portfolios (GitHub repos, live sites, app stores)
- Custom sections (Services, Resume, Gallery, etc.)
- External links (Blog, YouTube, Podcast, etc.)
{username}- Your display name{siteTitle}- Site title from config{github.username}- GitHub username{twitter.url}- Full Twitter URL{farcaster.url}- Full Farcaster URL{bioUrl}- Personal website URL
- Arrow Keys: Navigate through menus (left/right for main menu, up/down for submenus)
- Mousewheel: Scroll through submenu items when a submenu is active
- Spacebar/Enter: Activate selected item (open links)
- Mouse: Click on menu items to navigate and activate
- Hover: Visual feedback on interactive elements
- Touch: Tap menu items to navigate
- Swipe Gestures:
- Horizontal swipes: Navigate main menu
- Vertical swipes: Navigate sub-menus
- Smart Positioning: Active menu items automatically center with submenu visible
The integrated blog system uses GitHub Actions to automatically generate a static index of blog posts, eliminating API rate limits and improving performance. Blog posts appear dynamically in the Log menu section.
- GitHub Actions Automation: Workflow runs daily at midnight UTC and on every push to
blog/folder - Static Index Generation: Script scans all
.mdfiles and generatesblog-posts.jsonwith metadata - Direct File Fetch: Client loads blog index from
raw.githubusercontent.com(unlimited requests!) - GitHub Links: Clicking a blog post opens the GitHub page with an anchor to the first heading
- ✅ No API Rate Limits - Fetches static JSON file instead of using GitHub API
- ✅ Automatic Updates - Posts automatically indexed when you commit to
blog/folder - ✅ Fast Loading - Single JSON file loads all post metadata at once
- ✅ Zero Maintenance - Workflow handles everything automatically
- Create a new
.mdfile in theblog/folder - Add frontmatter with required fields:
---
title: "Your Post Title"
date: "2024-01-15"
excerpt: "Brief description of your post"
---
# Your Post Content
Write your blog content in Markdown format...- Commit to GitHub - GitHub Actions automatically rebuilds the index (usually within 1 minute!)
- GitHub Actions Integration: Automated blog post indexing with no rate limits
- Smart Link Generation: Links to GitHub with anchors to first headings
- Frontmatter Parsing: Automatic title, date, and excerpt extraction
- Metadata Display: Blog posts show title, date, and excerpt in the menu
- Zero Configuration: No manual file registration required
- GitHub Rendering: Posts display with GitHub's native Markdown renderer
- Sorted by Date: Posts automatically sorted newest first
- Configurable: Enable/disable via
ENABLE_BLOGenvironment variable
- Enable GitHub Actions in your repository settings (Settings → Actions → Allow all actions)
- Update blog-system.js with your repository name:
constructor() { this.blogIndexUrl = 'https://raw.githubusercontent.com/YOUR-USERNAME/YOUR-REPO/main/blog-posts.json'; }
- Add blog posts to the
blog/folder - GitHub Actions handles the rest! - Manual trigger: Go to Actions tab → "Generate Blog Index" → "Run workflow" to force regeneration
Problem: You see "Loading..." but no menu items appear.
Solutions:
-
For local development: Make sure you're serving with a web server (not opening
file://directly)python3 -m http.server 8000 # Required for local file loading -
Check browser console for error messages:
- Right-click → Inspect → Console
- Look for network errors or JavaScript errors
-
Verify menu-structure.json is valid:
# Check if file exists and is valid JSON cat menu-structure.json | python3 -m json.tool
Problem: Menu loads but blog posts don't appear in the Log section.
Solutions:
- Check GitHub Actions: Go to Actions tab and verify "Generate Blog Index" workflow completed successfully
- Verify blog-posts.json: Check if
blog-posts.jsonexists in your repository root - Repository URL: Ensure
blogIndexUrlinblog-system.jspoints to your repository - Repository privacy: Ensure repository is public (raw.githubusercontent.com requires public repos)
- Manual trigger: Run the workflow manually from Actions tab → "Generate Blog Index" → "Run workflow"
- Check browser console: Look for fetch errors or CORS issues
Problem: Changed .env but nothing happens.
Solutions:
- Run build process:
npm run build # Generates config from .env - Clear browser cache: Configuration is cached by browsers.
- Check generated files: Look for
config.generated.jsafter build.
Problem: Modified color values but background stays the same.
Solutions:
- Hex format: Ensure colors are 6-digit hex values like
#000000 - Comma separation: Multiple colors should be comma-separated
- Build process: Run
npm run buildto apply changes - Hard refresh: Clear cache with Ctrl+F5 (or Cmd+Shift+R on Mac)
- Connect repository to Vercel
- Add environment variables in Vercel dashboard
- Deploy - automatically builds and serves
- Connect repository to Netlify
- Set build command:
npm run build - Add environment variables in site settings
- Deploy - builds automatically on push
- Create
.github/workflows/deploy.yml:name: Deploy on: push jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - uses: actions/setup-node@v2 - run: npm install - run: npm run build - uses: peaceiris/actions-gh-pages@v3
- Add secrets for environment variables
- Enable GitHub Pages from Actions
For any static host (Firebase, AWS S3, etc.):
- Build locally:
npm run build - Upload entire v4 folder to hosting
- Ensure web server serves
index.htmlfor root requests
The blog system is configured to work with this repository by default. To use with your own repository:
// In blog-system.js, update these values:
this.githubRepo = 'yourusername/yourrepository';
this.githubPath = 'blog'; // or your preferred folder nameModify the gradient colors in main.js:
// Primary gradient layer
const primaryGradient = new MeshGradientRenderer('background-primary', {
colors: ['#000000', '#1a3b1a', '#2d5a27', '#0f1f0f'], // Customize these
speed: 0.3,
distortion: 0.8,
opacity: 1.0
});Edit the menu structure in index.html:
<div class="menu-item">
<div class="menu-item-header">
<svg class="menu-item-icon" viewBox="0 0 24 24">
<!-- Your custom SVG icon -->
</svg>
<div class="menu-item-description">Your Menu Item</div>
</div>
<!-- Sub-menu items -->
</div>Adjust menu positioning for different browsers in main.js:
// Mobile positioning
let rightPercent = isMobileDevice ? 0.0 : 0.25;
let horizontalOffset = isMobileDevice ? 0 : 0;- WebGL Required: Modern browsers with WebGL support
- Tested Browsers:
- Chrome/Chromium (Desktop & Mobile)
- Safari (Desktop & Mobile) - with specific positioning adjustments
- Firefox (Desktop & Mobile)
- Edge (Desktop & Mobile)
- Smart Submenu Positioning - MenuFocusManager automatically centers active items at 25% from left edge
- Submenu Visibility Priority - Ensures submenu content is always visible and properly positioned
- Touch-first Design - Optimized touch targets and gestures
- Improved Text Display - Blog post excerpts show 2 lines on mobile with proper word wrapping
- Z-index Management - Active menu items elevated above adjacent menus for proper click handling
- Hidden Debug Controls - Control panel automatically hidden on mobile devices
- Performance - Reduced animations and optimized rendering
- Responsive Layout - Adaptive sizing for different screen sizes
- Safari Compatibility - Special positioning adjustments for Safari mobile
- Vanilla JavaScript - No external dependencies
- WebGL/WebGL2 - Hardware-accelerated background rendering
- GitHub Actions - Automated blog post indexing (no rate limits!)
- CSS3 Transforms - Smooth menu animations
- Frontmatter Parsing - Custom YAML-like parser
- Responsive CSS - Mobile-first design approach
- Hardware Acceleration - WebGL rendering for smooth animations
- Static JSON Loading - No API rate limits with GitHub Actions automation
- Smart Mobile Focus - MenuFocusManager calculates optimal viewport positioning
- Z-index Stacking - Proper layering prevents click-through issues
- Comprehensive Positioning System - Platform-specific configurations with debug controls
- Mobile Optimization - Touch-optimized interface with hidden debug controls
- Cross-Browser Compatibility - Browser-specific positioning adjustments
- MenuFocusManager - Smart algorithm for centering active menu items and submenus on mobile
- Mousewheel Navigation - Natural scrolling through submenu items on desktop
- Debug Control Panel - Real-time menu positioning with visual feedback (hidden on mobile)
- Environment Detection - Automatic device, browser, and viewport detection
- User Preferences - LocalStorage persistence for custom positioning
- Touch Gesture Support - Native touch events with conflict resolution
- GitHub Link Anchors - Smart heading detection for direct navigation
- Automated Blog Indexing - GitHub Actions workflow generates static index on every commit
- Blog System: GitHub Actions generates
blog-posts.jsonautomatically on every commit toblog/folder - MenuFocusManager: Calculates optimal translateX to position active menu items at 25% from left (mobile/tablet)
- Positioning System: Comprehensive cross-platform menu positioning with debug controls (hidden on mobile)
- Mousewheel Support: Uses
{ passive: false }event listener to enable preventDefault() for scroll blocking - Z-index Strategy: Active menu items use z-index: 100 to elevate above adjacent menus, preventing click-through
- Pointer Events: Uses CSS pointer-events to control which elements capture clicks in active menus
- WebGL Backgrounds: Dual-layer mesh gradient rendering for visual depth
- Mobile Optimization: Smart submenu centering with word-wrapping and improved text display
- Browser Detection: Automatic environment detection with platform-specific configurations
- v4 (Current) - Enhanced mobile experience with smart positioning, automated blog indexing, and mousewheel support
- Added GitHub Actions workflow for automated blog post indexing
- Implemented MenuFocusManager for smart mobile submenu positioning
- Added mousewheel navigation support for desktop
- Improved mobile UI with better text display and z-index management
- Hidden debug controls on mobile for cleaner interface
- Eliminated GitHub API rate limits with static JSON approach
- v3 - Full-featured XMB with blog system and WebGL backgrounds
- v2 - Simplified XMB implementation with gradient backgrounds
- v1 - Initial XMB recreation with basic navigation
This project builds upon the excellent work of:
- Menu System: Inspired by and adapted from ps3-xmb-menu by mustafaHTP
- WebGL Background: Based on mesh gradient shaders from Paper Design Shaders
This project is open source and available under the MIT License.
Created with ❤️ as a tribute to the iconic PlayStation 3 XrossMediaBar interface
