389 lines
8.0 KiB
Markdown
389 lines
8.0 KiB
Markdown
|
|
# 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)
|
||
|
|
|
||
|
|
```rust
|
||
|
|
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:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
cp your-background.png static/bg.png
|
||
|
|
```
|
||
|
|
|
||
|
|
### Step 2: Reference in CSS
|
||
|
|
|
||
|
|
In `templates/term.html`, add CSS to use the image:
|
||
|
|
|
||
|
|
```html
|
||
|
|
<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
|
||
|
|
|
||
|
|
```bash
|
||
|
|
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:**
|
||
|
|
```bash
|
||
|
|
echo "body { font-family: 'Custom Font'; }" > static/custom.css
|
||
|
|
```
|
||
|
|
|
||
|
|
**2. Reference in HTML:**
|
||
|
|
```html
|
||
|
|
<link rel="stylesheet" href="/assets/custom.css" />
|
||
|
|
```
|
||
|
|
|
||
|
|
### Custom JavaScript
|
||
|
|
|
||
|
|
**1. Create the file:**
|
||
|
|
```bash
|
||
|
|
echo "console.log('Custom script loaded');" > static/custom.js
|
||
|
|
```
|
||
|
|
|
||
|
|
**2. Reference in HTML:**
|
||
|
|
```html
|
||
|
|
<script src="/assets/custom.js"></script>
|
||
|
|
```
|
||
|
|
|
||
|
|
### Fonts
|
||
|
|
|
||
|
|
**1. Add font files:**
|
||
|
|
```bash
|
||
|
|
mkdir -p static/fonts
|
||
|
|
cp MyFont.woff2 static/fonts/
|
||
|
|
```
|
||
|
|
|
||
|
|
**2. Use in CSS:**
|
||
|
|
```css
|
||
|
|
@font-face {
|
||
|
|
font-family: 'MyFont';
|
||
|
|
src: url('/assets/fonts/MyFont.woff2') format('woff2');
|
||
|
|
}
|
||
|
|
|
||
|
|
body {
|
||
|
|
font-family: 'MyFont', sans-serif;
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Favicon
|
||
|
|
|
||
|
|
**1. Add favicon:**
|
||
|
|
```bash
|
||
|
|
cp favicon.ico static/
|
||
|
|
```
|
||
|
|
|
||
|
|
**2. Reference in HTML:**
|
||
|
|
```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:**
|
||
|
|
```html
|
||
|
|
<!-- 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:
|
||
|
|
|
||
|
|
```css
|
||
|
|
/* 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:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# 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:
|
||
|
|
```bash
|
||
|
|
ls -la static/bg.png
|
||
|
|
```
|
||
|
|
|
||
|
|
2. Verify server is running with updated code:
|
||
|
|
```bash
|
||
|
|
cargo build
|
||
|
|
cargo run
|
||
|
|
```
|
||
|
|
|
||
|
|
3. Check server logs for errors:
|
||
|
|
```bash
|
||
|
|
# Look for actix_files errors in console output
|
||
|
|
```
|
||
|
|
|
||
|
|
4. Test the URL directly:
|
||
|
|
```bash
|
||
|
|
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:
|
||
|
|
```css
|
||
|
|
/* 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:
|
||
|
|
```bash
|
||
|
|
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:**
|
||
|
|
|
||
|
|
```rust
|
||
|
|
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:**
|
||
|
|
```toml
|
||
|
|
[dependencies]
|
||
|
|
actix-cors = "0.5"
|
||
|
|
```
|
||
|
|
|
||
|
|
## Performance Considerations
|
||
|
|
|
||
|
|
### Caching
|
||
|
|
|
||
|
|
For production, consider adding cache headers:
|
||
|
|
|
||
|
|
```rust
|
||
|
|
.service(
|
||
|
|
actix_files::Files::new("/assets", "./static")
|
||
|
|
.use_etag(true)
|
||
|
|
.use_last_modified(true)
|
||
|
|
)
|
||
|
|
```
|
||
|
|
|
||
|
|
### Compression
|
||
|
|
|
||
|
|
Enable gzip compression for text assets:
|
||
|
|
|
||
|
|
```rust
|
||
|
|
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:**
|
||
|
|
```bash
|
||
|
|
cp ~/my-background.png static/bg.png
|
||
|
|
```
|
||
|
|
|
||
|
|
**2. Update templates/term.html:**
|
||
|
|
```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:**
|
||
|
|
```bash
|
||
|
|
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` |
|