Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

350 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Portfolio Website - Jen Rumery

A modern, responsive portfolio website showcasing professional experience, projects, and blog content for Jen Rumery, a Product Manager with 15+ years of experience in healthcare technology.

πŸš€ Quick Start

# Install dependencies
npm install

# Start development server
npm run dev

# Build for production
npm run build

# Preview production build
npm run preview

πŸ“¦ Tech Stack

This project is built with:

  • Vite - Fast build tool and development server
  • TypeScript - Type-safe JavaScript (strict mode enabled)
  • React - UI library (v18.3.1) with code splitting
  • shadcn-ui - High-quality UI components built on Radix UI
  • Tailwind CSS - Utility-first CSS framework
  • React Router DOM - Client-side routing with lazy loading
  • React Helmet Async - Dynamic SEO meta tags
  • React Hook Form + Zod - Form handling and validation
  • Lucide React - Icon library
  • next-themes - Dark mode support

πŸ“ Project Structure

portfolio/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ components/
β”‚   β”‚   β”œβ”€β”€ layout/          # Layout components (Header, Footer, Layout)
β”‚   β”‚   β”œβ”€β”€ ui/              # shadcn-ui components (48 components)
β”‚   β”‚   β”œβ”€β”€ ErrorBoundary.tsx # Error handling wrapper
β”‚   β”‚   β”œβ”€β”€ PageLoader.tsx   # Loading state component
β”‚   β”‚   β”œβ”€β”€ SEO.tsx          # SEO meta tags component
β”‚   β”‚   └── ScrollToTop.tsx  # Route change scroll handler
β”‚   β”œβ”€β”€ data/
β”‚   β”‚   β”œβ”€β”€ blogPosts.ts     # Blog post data
β”‚   β”‚   └── caseStudies.ts   # Project data
β”‚   β”œβ”€β”€ types/               # TypeScript type definitions
β”‚   β”‚   β”œβ”€β”€ blog.ts          # BlogPost interface
β”‚   β”‚   β”œβ”€β”€ caseStudy.ts     # CaseStudy interface
β”‚   β”‚   └── index.ts         # Type exports
β”‚   β”œβ”€β”€ hooks/               # Custom React hooks
β”‚   β”‚   β”œβ”€β”€ use-toast.ts     # Toast notifications
β”‚   β”‚   └── use-mobile.tsx   # Mobile detection
β”‚   β”œβ”€β”€ lib/
β”‚   β”‚   β”œβ”€β”€ utils.ts         # Utility functions
β”‚   β”‚   └── routes.ts        # Centralized route constants
β”‚   β”œβ”€β”€ pages/               # Page components (lazy loaded)
β”‚   β”‚   β”œβ”€β”€ Index.tsx        # Home page
β”‚   β”‚   β”œβ”€β”€ About.tsx        # About page
β”‚   β”‚   β”œβ”€β”€ Blog.tsx         # Blog listing
β”‚   β”‚   β”œβ”€β”€ BlogPost.tsx     # Individual blog post
β”‚   β”‚   β”œβ”€β”€ CaseStudies.tsx  # Projects showcase with image lightbox
β”‚   β”‚   β”œβ”€β”€ Contact.tsx      # Contact form
β”‚   β”‚   └── NotFound.tsx     # 404 page
β”‚   β”œβ”€β”€ App.tsx              # Main app with routing & error boundary
β”‚   └── main.tsx             # Entry point with HelmetProvider
β”œβ”€β”€ public/                  # Static assets
└── .env.local               # Environment variables (gitignored)

✨ Features

  • Responsive Design - Mobile-first approach with Tailwind CSS
  • Type Safety - Full TypeScript implementation with strict mode
  • Component Library - Extensive shadcn-ui component collection (48 components)
  • Code Splitting - Route-level lazy loading for optimal performance
  • SEO Optimized - Dynamic meta tags with react-helmet-async + static HTML for crawlers
  • Social Media Ready - Pre-rendered Open Graph tags for LinkedIn, Facebook, Twitter
  • Error Handling - Error boundaries for graceful error recovery
  • Routing - React Router with /portfolio base path + GitHub Pages SPA support
  • Dark Mode Support - Theme switching with next-themes
  • Professional Portfolio - Showcases work experience, projects, and blog posts
  • Image Lightbox - Click project images to view enlarged in modal dialog
  • Cohesive Design - Dark header/footer bookend design with bronze accent colors
  • Performance - Optimized bundle sizes (main: 182KB, pages: 2-15KB each)

πŸ› οΈ Available Scripts

Command Description
npm run dev Start development server
npm run build Production build (runs prebuild automatically)
npm run prebuild Generate static HTML for blog posts (runs before build)
npm run build:dev Development build
npm run preview Preview production build
npm run lint Run ESLint

Note: The prebuild script runs automatically before build to generate static HTML files for social media crawler compatibility.

🎨 Design System

  • UI Components: shadcn-ui (Radix UI primitives)
  • Styling: Tailwind CSS with custom theme
  • Animations: Custom fade-in animations with staggered delays
  • Typography: Custom display and body fonts with responsive sizing
  • Color Scheme: Professional color palette with warm shadows
  • Layout: Dark header (#3a3a3a) and footer bookend design
  • Accent Colors: Bronze (#B8733E) for hover states and highlights
  • Responsive Typography: Mobile-first with breakpoint-specific sizing

🧭 Routes

The application uses React Router with these routes (defined in src/lib/routes.ts):

  • / - Home page (ROUTES.HOME)
  • /projects - Projects showcase (ROUTES.PROJECTS)
  • /blog - Blog listing (ROUTES.BLOG)
  • /blog/:slug - Individual blog post (ROUTES.BLOG_POST)
  • /contact - Contact form (ROUTES.CONTACT)
  • /about - About page (ROUTES.ABOUT)
  • * - 404 Not Found page

All routes are lazy-loaded for optimal performance.

πŸ’» Development Guidelines

Path Aliases

  • @/ is aliased to src/ directory
  • Use absolute imports: import Layout from "@/components/layout/Layout"

Component Structure

  • Page components β†’ src/pages/ (lazy-loaded)
  • Layout components β†’ src/components/layout/
  • UI components β†’ src/components/ui/ (shadcn-ui)
  • Custom components β†’ src/components/
  • Type definitions β†’ src/types/
  • Data files β†’ src/data/

Best Practices

  • TypeScript: Strict mode enabled - all types required
  • Routing: Always use ROUTES constants from src/lib/routes.ts
  • Navigation: Use <Link> from React Router (never <a> tags)
  • SEO: Add <SEO> component to all pages with unique metadata
  • Imports: Use TypeScript types from src/types/
  • Styling: Tailwind CSS utility classes (mobile-first)
  • Icons: Lucide React icon library
  • Animations: Subtle, professional fade-ins with staggered delays
  • Error Handling: Pages wrapped in ErrorBoundary
  • Loading States: Use Suspense with PageLoader fallback

Environment Variables

Create a .env.local file (gitignored) with:

VITE_WEB3FORMS_ACCESS_KEY=your-api-key-here

πŸ“ Data Management

  • Blog posts: src/data/blogPosts.ts (BlogPost type from src/types/blog.ts)
  • Projects: src/data/caseStudies.ts (CaseStudy type from src/types/caseStudy.ts)
  • Static data only: No backend/API (except Web3Forms for contact form)
  • Type safety: All data uses centralized TypeScript interfaces

Adding New Blog Posts

When adding a new blog post, you need to update TWO files:

  1. Add blog data to src/data/blogPosts.ts:

    {
      id: 6,
      slug: "new-blog-post",
      title: "Your Blog Post Title",
      excerpt: "Brief description for social media previews",
      image: "/your-image.png",
      imageAlt: "Image description",
      // ... other fields
    }
  2. Update static HTML generator in scripts/generate-blog-pages.js:

    const blogPosts = [
      // ... existing posts
      {
        slug: "new-blog-post",
        title: "Your Blog Post Title",
        excerpt: "Brief description for social media previews",
        image: "/your-image.png",
        imageAlt: "Image description",
      },
    ];

Why both? The SPA uses blogPosts.ts for the interactive site. The script generates static HTML for social media crawlers (LinkedIn, Facebook, Twitter) that don't execute JavaScript. See scripts/README.md for details.

πŸ” SEO & Social Media Optimization

This portfolio implements a dual-layer approach for optimal SEO and social media sharing:

Dynamic Meta Tags (SPA)

  • Component: src/components/SEO.tsx with react-helmet-async
  • Purpose: Provides meta tags for browsers and search engines that execute JavaScript
  • Used by: Google, Bing, and human visitors

Static HTML Generation (Crawlers)

  • Script: scripts/generate-blog-pages.js
  • Purpose: Pre-renders HTML with Open Graph meta tags for social media crawlers
  • Used by: LinkedIn Post Inspector, Facebook, Twitter, and other social platforms

How it works:

  1. Social media crawlers access /portfolio/blog/your-post
  2. They receive static HTML with complete meta tags (no JavaScript needed)
  3. Browsers execute a redirect to load the full SPA experience
  4. Users get the interactive React app, crawlers get the meta tags

Testing social media previews:

For detailed documentation, see scripts/README.md.

πŸ“ Portfolio Projects

The portfolio showcases 4 case studies in priority order:

  1. Cornerstone Help Hub - Cloud migration & virtual assistant (90% adoption, 1,000+ paths)
  2. AI Product from Concept to Production - 8 weeks to launch (95% accuracy, 200+ beta users)
  3. OpenAPI Platform Management - 20+ integrations (50% faster onboarding, 2x adoption)
  4. UX Teardown Methodology - Systematic research (14+ studies, 1,300+ practices)

Homepage features the top 3 projects. All projects include clickable image lightbox for detailed viewing.

🌐 Deployment

This project is configured for deployment with a /portfolio base path (e.g., GitHub Pages).

The router has basename="/portfolio" configured for proper routing in deployed environments.

GitHub Pages Configuration

The portfolio implements a complete GitHub Pages setup with SPA routing and crawler support:

SPA Routing (For Browsers)

  1. 404.html (public/404.html) - Catches 404s and redirects to the main app
  2. Redirect Handler (index.html) - Restores the original URL via sessionStorage
  3. .nojekyll (public/.nojekyll) - Prevents Jekyll from processing files

How it works:

  • User navigates to /portfolio/blog/post-name
  • GitHub Pages serves 404.html (path doesn't exist as a file)
  • 404.html stores path in sessionStorage and redirects to /portfolio/
  • index.html reads sessionStorage and restores the original URL
  • React Router handles the route normally

Social Media Crawler Support (For LinkedIn/Facebook/Twitter)

  1. Static HTML Generation (scripts/generate-blog-pages.js) - Creates static HTML for each blog post
  2. Pre-rendered Meta Tags - All Open Graph tags included without JavaScript
  3. Automatic Build Integration - Runs via prebuild script before every build

How it works:

  • Crawler accesses /portfolio/blog/post-name/
  • Gets static index.html with complete meta tags
  • Crawler reads tags without executing JavaScript
  • Result: Perfect social media previews with images

Deployment Checklist

  • βœ… Set VITE_WEB3FORMS_ACCESS_KEY environment variable for contact form
  • βœ… Ensure all blog posts are in scripts/generate-blog-pages.js
  • βœ… Run npm run build to generate static HTML and bundle
  • βœ… Test social media previews with LinkedIn Post Inspector after deployment

Testing After Deployment:

Bundle Sizes (Production Build)

  • Main bundle: 182KB
  • Layout chunk: 30KB
  • Blog data: 43KB (lazy-loaded)
  • Individual pages: 2-15KB each (lazy-loaded)

πŸ“„ License

Private project - all rights reserved.

πŸ‘€ About

This portfolio showcases the work of Jen Rumery, highlighting expertise in:

  1. Cloud Migration & Platform Development (6,500+ practices served)
  2. AI Product Development (0-to-1 building, 8 weeks to production)
  3. OpenAPI Platform Management (20+ integrations)
  4. UX Research & Teardown Methodology (14+ studies conducted)

For more detailed technical documentation, see CLAUDE.MD.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages