socktop-webterm/STATIC_ASSETS.md
jasonwitty 6e48c095ab Initial commit: Socktop WebTerm with k3s deployment
- Multi-architecture Docker image (ARM64 + AMD64)
- Kubernetes manifests for 3-replica deployment
- Traefik ingress configuration
- NGINX Proxy Manager integration
- ConfigMap-based configuration
- Automated build and deployment scripts
- Session monitoring tools
2025-11-28 01:31:33 -08:00

8.0 KiB

Adding Static Assets to webterm

Overview

This guide explains how to add static assets (images, fonts, CSS files, etc.) to your webterm application.

Directory Structure

webterm/
├── static/              # Your custom static assets
│   ├── bg.png          # Background image
│   ├── terminado-addon.js
│   └── ...             # Other custom files
├── node_modules/        # npm packages (served at /static)
│   ├── @xterm/
│   └── ...
└── templates/          # HTML templates
    └── term.html

How Static Files Are Served

The Rust backend serves static files from two locations:

  1. /assets/* → serves from ./static/ directory
  2. /static/* → serves from ./node_modules/ directory

Configuration (src/server.rs)

let factory = || {
    App::new()
        .service(actix_files::Files::new("/assets", "./static"))
        .service(actix_files::Files::new("/static", "./node_modules"))
        // ... rest of config
};

Adding a Background Image

Step 1: Add the Image File

Place your image in the static/ directory:

cp your-background.png static/bg.png

Step 2: Reference in CSS

In templates/term.html, add CSS to use the image:

<style>
    body {
        background-image: url('/assets/bg.png');
        background-size: cover;
        background-position: center;
        background-repeat: no-repeat;
        background-attachment: fixed;
    }
</style>

Step 3: Test

cargo run
# Open http://localhost:8082/
# Check browser DevTools Network tab to verify /assets/bg.png loads

Adding Other Static Assets

Custom CSS File

1. Create the file:

echo "body { font-family: 'Custom Font'; }" > static/custom.css

2. Reference in HTML:

<link rel="stylesheet" href="/assets/custom.css" />

Custom JavaScript

1. Create the file:

echo "console.log('Custom script loaded');" > static/custom.js

2. Reference in HTML:

<script src="/assets/custom.js"></script>

Fonts

1. Add font files:

mkdir -p static/fonts
cp MyFont.woff2 static/fonts/

2. Use in CSS:

@font-face {
    font-family: 'MyFont';
    src: url('/assets/fonts/MyFont.woff2') format('woff2');
}

body {
    font-family: 'MyFont', sans-serif;
}

Favicon

1. Add favicon:

cp favicon.ico static/

2. Reference in HTML:

<link rel="icon" href="/assets/favicon.ico" type="image/x-icon" />

Path Reference Guide

From HTML Template (templates/term.html)

Asset Location URL Path Example
static/bg.png /assets/bg.png url('/assets/bg.png')
static/custom.css /assets/custom.css href="/assets/custom.css"
node_modules/@xterm/xterm/lib/xterm.js /static/@xterm/xterm/lib/xterm.js Use {{ static_path }}/@xterm/xterm/lib/xterm.js

Template Variables

The HTML template has access to these variables:

  • {{ static_path }} - Resolves to /static (for node_modules)
  • {{ websocket_path }} - Resolves to /websocket (for WebSocket connection)

Example:

<!-- npm packages use {{ static_path }} -->
<script src="{{ static_path }}/@xterm/xterm/lib/xterm.js"></script>

<!-- Custom assets use /assets directly -->
<img src="/assets/logo.png" alt="Logo" />

Best Practices

1. Organize Your Assets

static/
├── images/
│   ├── bg.png
│   └── logo.png
├── fonts/
│   └── CustomFont.woff2
├── css/
│   └── custom.css
└── js/
    ├── terminado-addon.js
    └── custom.js

2. Reference Images in CSS

Use relative paths or absolute paths from the /assets root:

/* Good - absolute path */
background-image: url('/assets/images/bg.png');

/* Also good - for images in CSS files in static/css/ */
background-image: url('../images/bg.png');

3. Optimize Images

Before adding large images:

# Install optimization tools
sudo apt install optipng jpegoptim

# Optimize PNG
optipng -o7 static/bg.png

# Optimize JPEG
jpegoptim --size=500k static/photo.jpg

4. Use Appropriate File Formats

  • PNG: Screenshots, logos, images with transparency
  • JPEG: Photos, complex images
  • SVG: Icons, logos, simple graphics
  • WebP: Modern format, smaller file sizes (check browser support)

Troubleshooting

Image Returns 404

Problem: /assets/bg.png returns 404 Not Found

Solutions:

  1. Check file exists:

    ls -la static/bg.png
    
  2. Verify server is running with updated code:

    cargo build
    cargo run
    
  3. Check server logs for errors:

    # Look for actix_files errors in console output
    
  4. Test the URL directly:

    curl -I http://localhost:8082/assets/bg.png
    

Image Loads But Doesn't Display

Problem: Network tab shows 200 OK but image doesn't appear

Solutions:

  1. Check CSS syntax:

    /* Wrong */
    background: /assets/bg.png;
    
    /* Correct */
    background-image: url('/assets/bg.png');
    
  2. Check image path in browser DevTools:

    • Open DevTools → Elements
    • Inspect the element with background
    • Check computed styles
  3. Verify image format is supported:

    file static/bg.png
    # Should show: PNG image data
    

CORS Issues

If loading assets from different origins, you may need CORS headers.

Add to src/server.rs:

use actix_cors::Cors;

let factory = || {
    App::new()
        .wrap(
            Cors::default()
                .allow_any_origin()
                .allow_any_method()
                .allow_any_header()
        )
        .service(actix_files::Files::new("/assets", "./static"))
        // ... rest of config
};

Add to Cargo.toml:

[dependencies]
actix-cors = "0.5"

Performance Considerations

Caching

For production, consider adding cache headers:

.service(
    actix_files::Files::new("/assets", "./static")
        .use_etag(true)
        .use_last_modified(true)
)

Compression

Enable gzip compression for text assets:

use actix_web::middleware::Compress;

let factory = || {
    App::new()
        .wrap(Compress::default())
        .service(actix_files::Files::new("/assets", "./static"))
        // ... rest
};

CDN for Large Assets

For production websites, consider:

  • Hosting large images on a CDN
  • Using external image hosting (imgur, cloudinary, etc.)
  • Optimizing and compressing all assets

Example: Complete Background Setup

Here's a complete example adding a background image:

1. Add the image:

cp ~/my-background.png static/bg.png

2. Update templates/term.html:

<style>
    body {
        background-image: url('/assets/bg.png');
        background-size: cover;
        background-position: center;
        background-repeat: no-repeat;
        background-attachment: fixed;
        /* Add overlay to improve text readability */
        position: relative;
    }
    
    body::before {
        content: '';
        position: fixed;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        background: rgba(0, 0, 0, 0.5); /* Dark overlay */
        z-index: -1;
    }
</style>

3. Run and test:

cargo run
# Open http://localhost:8082/

Summary

  • Custom static files go in ./static/ directory
  • Access them via /assets/* URLs
  • npm packages are accessed via /static/* URLs
  • Always rebuild and restart after changing Rust code
  • Use browser DevTools to debug loading issues
  • Optimize images before adding them

Quick Reference:

I want to add... Put it in... Access it at...
Background image static/bg.png /assets/bg.png
Custom CSS static/style.css /assets/style.css
Custom JS static/script.js /assets/script.js
Font file static/fonts/font.woff2 /assets/fonts/font.woff2
Logo static/logo.png /assets/logo.png