Skip to content

detekoi/detekoi.github.io

Repository files navigation

Henry's Portfolio Website

This repository contains the code for my personal portfolio website.

Table of Contents

Features

  • Responsive design
  • Project showcase
  • AI-powered mascot customization using Google's Gemini API
  • Dynamic UI elements

Setup and Installation

  1. Clone the repository
  2. Install dependencies:
    npm install
  3. Create a .env file with your Gemini API key:
    GEMINI_API_KEY=your_api_key_here
    
  4. Start the server:
    node server.js
  5. Open http://localhost:3000 in your browser

Testing

To test the mascot image generation functionality:

node scripts/test-image-generation.js

Technology Stack

  • Frontend: HTML, CSS, JavaScript
  • Backend: Node.js, Express
  • AI Integration: Google Gemini API
  • Deployment: GitHub Actions, Google Cloud Run, GitHub Pages

Deployment

This website uses a modern deployment setup leveraging GitHub Actions and Google Cloud Run for automated deployment and scalable hosting.

Architecture Overview

  • Static frontend files are deployed to GitHub Pages
  • The Gemini API server runs on Google Cloud Run
  • GitHub Actions automates both deployment processes

GitHub Actions Workflow

The repository includes two GitHub Actions workflows:

  1. Frontend Deployment (frontend-deploy.yml):

    name: Deploy Frontend
    on:
      push:
        branches: [main]
        paths:
          - 'public/**'
          - 'index.html'
          - 'styles/**'
    
    jobs:
      deploy:
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v2
          - name: Deploy to GitHub Pages
            uses: peaceiris/actions-gh-pages@v3
            with:
              github_token: ${{ secrets.GITHUB_TOKEN }}
              publish_dir: ./
  2. Backend Deployment (backend-deploy.yml):

    name: Deploy Backend
    on:
      push:
        branches: [main]
        paths:
          - 'server/**'
          - 'package.json'
    
    jobs:
      deploy:
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v2
          
          - name: Set up Cloud SDK
            uses: google-github-actions/setup-gcloud@v0
            with:
              project_id: ${{ secrets.GCP_PROJECT_ID }}
              service_account_key: ${{ secrets.GCP_SA_KEY }}
              
          - name: Build and Deploy to Cloud Run
            run: |
              gcloud builds submit --tag gcr.io/${{ secrets.GCP_PROJECT_ID }}/gemini-server
              gcloud run deploy gemini-server \
                --image gcr.io/${{ secrets.GCP_PROJECT_ID }}/gemini-server \
                --platform managed \
                --region us-central1 \
                --allow-unauthenticated

Setup Requirements

  1. GitHub Repository Settings:

    • Enable GitHub Pages in repository settings
    • Add required secrets:
      • GCP_PROJECT_ID: Your Google Cloud project ID
      • GCP_SA_KEY: Service account key JSON for Google Cloud authentication
  2. Google Cloud Setup:

    • Create a new project
    • Enable Cloud Run and Container Registry APIs
    • Create a service account with required permissions:
      • Cloud Run Admin
      • Artifact Registry Admin
      • Storage Admin
      • Service Account User
      • Service Usage Consumer
    • Download service account key JSON
  3. Environment Configuration:

    • Add GEMINI_API_KEY to Cloud Run environment variables
    • Update frontend API endpoint in scripts/gemini-mascot.js to point to your Cloud Run service

Benefits of this Setup

  • Automated Deployments: Changes to frontend or backend code automatically trigger deployments
  • Scalable Backend: Cloud Run automatically scales based on demand
  • Cost-Effective: Only pay for actual backend usage
  • Secure: API keys and secrets are safely managed through GitHub Secrets and Cloud Run
  • Separated Concerns: Frontend and backend can be deployed and scaled independently

This deployment setup provides a production-ready environment that's both scalable and maintainable. The separation of frontend and backend deployments allows for independent scaling and updates while maintaining a cohesive system through automated workflows.

Customization

Carousel Features

The website features a 3D card carousel for displaying the mascot and AI-generated variations:

  1. Card Management:

    • Maximum of 5 AI-generated images stored
    • Automatic persistence using localStorage
    • Newest images added to the front of the carousel
    • Cards rotate with smooth 3D transitions
  2. Loading and Generation:

    • Dedicated loading card with static noise effect
    • Visual feedback during image generation
    • The loading card appears at the front of the carousel
    • Seamless replacement with the new image when ready
    • Automatic error handling with visual feedback
  3. Navigation and Interaction:

    • Previous/Next buttons for card rotation
    • Cards slide up and fade during transitions
    • Controls visibility based on card count
    • Click-to-enlarge lightbox support
    • Markdown formatting for descriptions
  4. Visual Style:

    • Cards stack with visible depth effect
    • Blur effects increasing with depth
    • Dark mode support with adjusted shadows
    • Responsive sizing across all device sizes
    • Sharp shadow aesthetic matching site design
  5. Performance Optimizations:

    • Optimized canvas rendering for loading effects
    • Debounced resize handling
    • Efficient DOM manipulation
    • Animation frame management
    • Lazy initialization of components

Customizing the Mascot

Changing the Prompt

To customize how the AI generates mascot outfits, modify the prompt in scripts/gemini-mascot.js. Look for the prompt constant:

const prompt = "Your custom prompt here";

The prompt should describe:

  • The mascot's base appearance
  • Desired outfit style changes
  • Any specific fashion elements or aesthetics
  • How to handle existing elements (like accessories)

Using Your Own Mascot Images

To use your own mascot, you'll need to update several files:

  1. Prepare your mascot images:

    • Main display image (e.g., with background/scene)
    • Use clear, high-quality images
    • Recommended size: at least 512x512 pixels
    • Format: PNG or JPEG
  2. Place your images in the assets/images directory:

    • Save your main display image (e.g., YourMascot.jpg)
    • Save your transparent version as PolarBearTransparent4K.png (or update the path in the files below)
  3. Update the image paths in these files:

    • index.html: Update the main display image
      <img src="assets/images/YourMascot.jpg" alt="Your Mascot Description" class="mascot">
    • server.js: Update the AI generation image path (around line 50)
      const imagePath = 'assets/images/PolarBearTransparent4K.png';
    • scripts/test-image-generation.js: Update the test script image path
      const imagePath = 'assets/images/PolarBearTransparent4K.png';
  4. Adjust the prompt to match your mascot's characteristics

  5. Test the image generation using the test script:

    node scripts/test-image-generation.js
    

Gemini API Performance

  1. Image Size Considerations

    • Keep mascot images at recommended size (512x512px)
    • Larger images increase API response time and costs
    • Smaller images may reduce generation quality
  2. Rate Limiting

    • Default cooldown period between generations
    • Prevents API abuse and manages costs
    • Adjust in server.js if needed:
      const RATE_LIMIT_MS = 5000; // 5 seconds between generations
  3. Caching Strategy

    • Generated outfits are cached server-side
    • Reduces API calls and improves response times
    • Configure cache size in server.js:
      const CACHE_SIZE = 10; // Number of recent generations to keep
  4. Error Handling

    • Graceful fallbacks when API is unavailable
    • Automatic retries for failed generations
    • User feedback through UI state changes

Static Background Customization

The website features a dynamic static noise background effect that can be customized by modifying parameters in scripts/static-background.js. The effect includes both a normal state and an enhanced "magic mode" that activates during certain interactions.

Basic Parameters

To adjust the basic static effect, modify these parameters in the config object:

const config = {
    pixelSize: 1,       // Size of each static pixel
    density: 0.8,       // Density of static dots
    baseAlpha: 0.85,    // Base opacity of static
    alphaVariance: 0.25 // Random variance in opacity
};

Color Settings

The static effect automatically adapts to light/dark mode. Customize the intensity ranges:

const config = {
    // Dark mode settings (bright dots on dark background)
    darkIntensityMin: 30,
    darkIntensityMax: 100,
    
    // Light mode settings (dark dots on light background)
    lightIntensityMin: 135,
    lightIntensityMax: 200
};

Magic Mode Effects

When magic mode activates (during certain interactions), the static becomes more intense and colorful. Customize these effects:

const config = {
    intenseDensity: 1.8,    // Density during magic mode
    intenseColor: [200, 120, 255], // Purple magic color [R,G,B]
    transitionSpeed: 0.012   // Speed of transition to/from magic mode
};
### Magic Mode and Gemini Integration

The static loading effect is designed to enhance the user experience during Gemini AI image generation. When you click the Style Inspiration button to generate a new outfit for the mascot:

1. A loading card appears with a purple-tinted static effect
2. This visual feedback indicates that the AI is processing your request
3. The static effect continues until the new image is ready
4. Once the new image loads, the loading card and static effect are smoothly replaced

This creates a cohesive experience where the loading state provides clear visual feedback during AI interactions, making the website feel more dynamic and responsive.

### Performance Settings

Adjust performance-related parameters:

```javascript
const config = {
    frameInterval: 45, // Milliseconds between frames (~20fps)
};

Triggering Magic Mode Programmatically

You can trigger the enhanced static effect from your JavaScript code:

// Enable magic mode
window.staticBackground.enableMagicMode();

// Disable magic mode
window.staticBackground.disableMagicMode();

Static Background Performance

The static background effect is designed to be performant while maintaining visual quality. Here are key considerations:

  1. Frame Rate Control

    • Default runs at ~20fps (45ms intervals) to balance smoothness and CPU usage
    • Automatically pauses when tab is not visible
    • Adjust frameInterval for different performance targets:
      const config = {
          frameInterval: 45, // Increase for better performance, decrease for smoother animation
      };
  2. Density Scaling

    • Static density automatically scales with screen size
    • Adjust density and intenseDensity for performance:
      const config = {
          density: 0.8,        // Decrease for better performance
          intenseDensity: 1.8  // Decrease for better performance in magic mode
      };
  3. Pixel Size Optimization

    • Larger pixelSize values improve performance but reduce quality
    • Consider increasing on lower-end devices:
      const config = {
          pixelSize: 1, // Increase to 2 or 3 for better performance
      };
  4. Dark Mode Optimizations

    • Automatically reduces effects intensity in dark mode
    • Fewer particles and lower opacity for better visibility and performance

Browser Support

  • Static effect uses requestAnimationFrame for optimal performance
  • Fallback to simpler static effect on older browsers
  • Automatically adjusts quality based on device capabilities
  • Supports both mouse and touch interactions

Network Optimization

  1. API Endpoint Location

    • Deploy Cloud Run backend in regions close to your users
    • Use CDN for static assets
    • Configure CORS appropriately for your deployment
  2. Asset Loading

    • Mascot images are lazy-loaded
    • Static effect starts immediately while assets load
    • Progressive enhancement approach