# Godot HTML5 Export Best Practices Guide

A comprehensive guide for exporting Godot games to HTML5/Web and deploying them properly.

## Table of Contents
- [Pre-Export Checklist](#pre-export-checklist)
- [Export Configuration](#export-configuration)
- [Post-Export Optimization](#post-export-optimization)
- [Deployment Best Practices](#deployment-best-practices)
- [Common Issues & Solutions](#common-issues--solutions)
- [Security Considerations](#security-considerations)

---

## Pre-Export Checklist

### 1. Set Project Icon
**Location:** `Project → Project Settings → Application → Config → Icon`

```
✅ Use a square PNG image (ideally 512x512 or 1024x1024)
✅ Godot will auto-generate smaller sizes (16x16, 32x32, etc.)
✅ This icon becomes your favicon and app icons
```

**Why:** Prevents 404 errors for `/favicon.ico` and provides proper branding.

### 2. Configure Export Presets
**Location:** `Project → Export → Add → HTML5`

#### Essential Settings:
```
Export Type: Regular (or Threads if you need SharedArrayBuffer)
Export With Debug: OFF for production
Texture Format: Compress for Smaller Downloads
```

#### Head Include (Optional):
Only add custom meta tags if needed:
```html
<meta name="description" content="Your game description">
<meta name="keywords" content="game, webgl, godot">
<meta name="author" content="Your Name">
```

### 3. Audio Configuration
**Location:** `Project → Project Settings → Audio`

```
✅ Mix Rate: 44100 Hz (standard web audio)
✅ Output Latency: 15ms (balance between quality and performance)
✅ Enable Audio Input: Only if needed (requires user permissions)
```

### 4. Display Settings
**Location:** `Project → Project Settings → Display → Window`

```
✅ Size: Set your target resolution (e.g., 1920x1080)
✅ Resizable: Enable if you want responsive sizing
✅ Stretch Mode: "2d" or "viewport" for web games
✅ Stretch Aspect: "expand" or "keep" based on your needs
```

---

## Export Configuration

### Recommended HTML5 Export Settings

#### 1. **Vram Texture Compression**
Enable both formats for maximum compatibility:
```
✅ For Desktop: s3tc (DXT1/DXT5)
✅ For Mobile: etc2 (or astc if targeting newer devices)
```

#### 2. **Custom HTML Shell**
Leave default unless you need:
- Custom loading screens
- Analytics integration
- Special PWA features

#### 3. **Export Mode**
- **Release:** Production builds (optimized, no debug symbols)
- **Debug:** Development builds (larger, has debug info)

### 4. **Progressive Web App (PWA)**
Enable if you want installable web apps:
```
Export → HTML5 → Progressive Web App: ON
Offline Page: Enable for offline support
Icon Sizes: Godot auto-generates these
```

---

## Post-Export Optimization

### 1. File Size Optimization

#### Compress WASM Files
The `.wasm` file is usually the largest. Use Brotli or Gzip:

```bash
# Using Brotli (best compression)
brotli -9 YourGame.wasm

# Using Gzip (better compatibility)
gzip -9 YourGame.wasm
```

#### Nginx Configuration:
```nginx
# Enable compression for Godot files
gzip on;
gzip_types application/wasm application/javascript text/html;
gzip_min_length 1000;

# Better: Use Brotli
brotli on;
brotli_types application/wasm application/javascript text/html;
```

### 2. Caching Strategy

```nginx
# Cache static assets aggressively
location ~* \.(wasm|js|pck)$ {
    expires 1y;
    add_header Cache-Control "public, immutable";
}

# Cache images
location ~* \.(png|jpg|jpeg|gif|ico)$ {
    expires 1y;
    add_header Cache-Control "public, immutable";
}

# Don't cache the HTML file
location ~* \.html$ {
    expires -1;
    add_header Cache-Control "no-cache, no-store, must-revalidate";
}
```

### 3. Required HTTP Headers

For SharedArrayBuffer/Threads support:
```nginx
add_header Cross-Origin-Embedder-Policy "require-corp" always;
add_header Cross-Origin-Opener-Policy "same-origin" always;
```

**Note:** These are already in your nginx.conf - good job!

---

## Deployment Best Practices

### 1. Directory Structure

```
your-game/
├── index.html              # Main entry (or YourGame.html)
├── YourGame.js            # Godot engine
├── YourGame.wasm          # Compiled game
├── YourGame.pck           # Game assets
├── YourGame.worker.js     # Service worker
├── YourGame.icon.png      # Favicon/Icon
├── favicon.ico            # Browser favicon (convert from icon)
├── manifest.json          # PWA manifest
└── assets/                # Optional: separate assets folder
```

### 2. Serving Files

#### Option A: Simple HTTP Server (Development)
```bash
# Python 3
python3 -m http.server 8000

# Python 2
python -m SimpleHTTPServer 8000

# Node.js (http-server)
npx http-server -p 8000
```

#### Option B: Production (Nginx/Caddy)
Use your current Kubernetes deployment approach.

### 3. HTTPS Requirement

Modern browsers require HTTPS for:
- SharedArrayBuffer (threads)
- Service Workers (offline)
- WebGL 2.0 features
- Clipboard API
- Gamepad API

**Your setup already has this via cert-manager + Let's Encrypt ✅**

---

## Common Issues & Solutions

### Issue 1: "SharedArrayBuffer is not defined"

**Cause:** Missing CORS headers or HTTP (not HTTPS)

**Solution:**
```nginx
add_header Cross-Origin-Embedder-Policy "require-corp" always;
add_header Cross-Origin-Opener-Policy "same-origin" always;
```

### Issue 2: Blank Screen or "Failed to load"

**Debug Steps:**
1. Open browser DevTools (F12)
2. Check Console for errors
3. Check Network tab for failed requests

**Common Causes:**
- Missing files (check all exports completed)
- Wrong MIME types
- File path mismatches (case-sensitive on Linux)

**Solution:** Verify nginx MIME types:
```nginx
types {
    application/wasm wasm;
    application/javascript js;
    text/html html;
}
```

### Issue 3: Audio Not Playing

**Cause:** Browsers require user interaction before playing audio

**Solution:** In Godot, show a "Click to Start" screen:
```gdscript
func _ready():
    # Don't autoplay audio
    # Wait for user input first
    pass

func _on_start_button_pressed():
    $AudioStreamPlayer.play()
```

### Issue 4: Poor Performance

**Optimization Tips:**
1. **Reduce Draw Calls:** Batch sprites, use TileMaps
2. **Optimize Shaders:** Simple shaders = better performance
3. **Texture Compression:** Use compressed textures
4. **Object Pooling:** Reuse nodes instead of creating/destroying
5. **Profile:** Use Godot's built-in profiler

### Issue 5: Large File Sizes

**Solutions:**
1. **Enable Compression:** Gzip/Brotli on server
2. **Optimize Assets:**
   - Convert PNGs to WebP
   - Compress audio (OGG Vorbis instead of WAV)
   - Use texture compression
3. **Lazy Loading:** Load assets on-demand, not all at startup
4. **Asset Streaming:** Use Godot's asset streaming features

---

## Security Considerations

### 1. Content Security Policy (CSP)

If you need CSP headers:
```nginx
# Relaxed CSP for Godot games
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'wasm-unsafe-eval' 'unsafe-inline'; worker-src 'self' blob:; connect-src 'self'; img-src 'self' data:; style-src 'self' 'unsafe-inline';" always;
```

### 2. X-Frame-Options

Prevent clickjacking:
```nginx
add_header X-Frame-Options "SAMEORIGIN" always;
```

**Your nginx.conf already has this ✅**

### 3. Input Validation

If your game has:
- User-generated content
- Multiplayer features
- External data loading

**Always validate and sanitize inputs!**

---

## Testing Checklist

Before deploying to production:

### Browser Compatibility
- [ ] Chrome/Chromium (Latest)
- [ ] Firefox (Latest)
- [ ] Safari (Latest)
- [ ] Edge (Latest)
- [ ] Mobile browsers (iOS Safari, Chrome Mobile)

### Performance Testing
- [ ] Load time < 10 seconds on 3G
- [ ] 60 FPS on target hardware
- [ ] Memory usage stable over time
- [ ] No memory leaks after extended play

### Functionality Testing
- [ ] Audio works (after user interaction)
- [ ] Input (keyboard, mouse, touch, gamepad)
- [ ] Fullscreen mode works
- [ ] Save/Load functionality
- [ ] All game mechanics work as expected

### Accessibility
- [ ] Works without sound (visual feedback)
- [ ] Keyboard-only controls (if applicable)
- [ ] Colorblind-friendly (if applicable)

---

## Advanced: Custom Docker Build

For building in CI/CD (like your Kaniko setup):

### Dockerfile Example:
```dockerfile
FROM nginx:alpine

# Copy game files
COPY htlm/ /usr/share/nginx/html/

# Copy custom nginx config
COPY nginx.conf /etc/nginx/conf.d/default.conf

# Set proper permissions
RUN chown -R nginx:nginx /usr/share/nginx/html

# Expose port
EXPOSE 8080

# Health check
HEALTHCHECK --interval=30s --timeout=3s \
    CMD wget --no-verbose --tries=1 --spider http://localhost:8080/ || exit 1
```

### nginx.conf (Your current one is excellent):
```nginx
server {
    listen 8080;
    server_name _;

    root /usr/share/nginx/html;
    index YourGame.html;

    # Compression
    gzip on;
    gzip_types application/wasm application/javascript text/html;

    # CORS for SharedArrayBuffer
    add_header Cross-Origin-Embedder-Policy "require-corp" always;
    add_header Cross-Origin-Opener-Policy "same-origin" always;

    # Security headers
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;

    # Caching
    location ~* \.(wasm|js|pck)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }
}
```

---

## Resources

### Official Documentation
- [Godot HTML5 Export Docs](https://docs.godotengine.org/en/stable/tutorials/export/exporting_for_web.html)
- [Godot Web Editor](https://editor.godotengine.org/)

### Tools
- [Godot Web Export Validator](https://pwa-directory.appspot.com/)
- [WebPageTest](https://www.webpagetest.org/) - Performance testing
- [Lighthouse](https://developers.google.com/web/tools/lighthouse) - PWA audit

### Community
- [Godot Forums - HTML5 Export](https://godotengine.org/community)
- [r/godot](https://reddit.com/r/godot)

---

## Your Current Setup Analysis

### What You're Doing Right ✅
1. **Proper CORS Headers** for SharedArrayBuffer
2. **Security Headers** (X-Frame-Options, X-Content-Type-Options)
3. **Compression** enabled (gzip)
4. **Proper MIME types** for .wasm files
5. **Cache headers** for static assets
6. **Service Worker** for offline support
7. **GitOps deployment** with Flux
8. **Container orchestration** with Kubernetes

### Recommendations
1. ✅ **Keep the favicon.ico** (converted from your icon)
2. ❌ **Don't create empty stub files** for scanner requests
3. ✅ **Monitor logs** but ignore 404s for files your app doesn't use
4. ✅ **Consider adding** a robots.txt to reduce scanner noise
5. ✅ **Consider adding** rate limiting to prevent abuse

### About Those 404 Errors
The files being requested (`support_parent.css`, `twint_ch.js`, `lkk_ch.js`) are:
- **Not part of Godot exports**
- **Not needed by your game**
- **Requested by bots/scanners** looking for e-commerce vulnerabilities
- **Safe to ignore** - they don't affect your game

**Best Practice:** Monitor real errors, ignore scanner noise in logs.

---

## License
This guide is provided as-is for educational purposes.
Feel free to adapt for your own projects.

---

**Last Updated:** November 2025
**Godot Version:** 4.x (applicable to 3.x with minor changes)
