add simple Uberspace deployment option (simpler than Cloudflare)

Instead of the complex Cloudflare Worker setup with CORS proxy,
you can now deploy both PWA and backend on Uberspace (~5€/month).

Changes:
- Add Express.js backend server (server/index.js)
- Update ConfigService to support VITE_API_URL env variable
- Make base path configurable via VITE_BASE_PATH
- Add comprehensive Uberspace deployment guide
- Add .env.production.example for configuration

Deployment options:
1. Uberspace (recommended): Simple, all-in-one hosting
2. GitHub Pages + Cloudflare Workers: Free but complex setup

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-02-06 20:50:56 +01:00
parent 985c61ed74
commit 0fe09f01f8
7 changed files with 263 additions and 11 deletions

16
.env.production.example Normal file
View File

@@ -0,0 +1,16 @@
# Backend URL (wo läuft dein Express Server?)
# Uberspace / eigenes Backend
VITE_API_URL=https://your-username.uber.space
# GitHub Pages (wenn du GitHub Pages nutzt, aber Uberspace Backend)
# VITE_API_URL=https://your-username.uber.space
# Lokales Backend (für Development mit separatem Backend)
# VITE_API_URL=http://localhost:3000
# Base Path (für URLs und Routing)
# GitHub Pages deployment:
# VITE_BASE_PATH=/whattoplay/
# Uberspace deployment (root):
# VITE_BASE_PATH=/

1
.gitignore vendored
View File

@@ -6,6 +6,7 @@ config.local.json
*.local.json
.env
.env.*
!.env.*.example
*.secret.*
*.key
*.pem

150
UBERSPACE.md Normal file
View File

@@ -0,0 +1,150 @@
# Uberspace Deployment
Einfacheres Setup: Hoste sowohl PWA als auch Backend auf Uberspace.
## Voraussetzungen
- Uberspace Account (https://uberspace.de)
- SSH Zugriff
- Node.js (bereits auf Uberspace vorinstalliert)
## 1. Backend deployen
```bash
# SSH auf deinen Uberspace
ssh <username>@<servername>.uberspace.de
# Repository klonen
cd ~
git clone https://github.com/felixfoertsch/whattoplay.git
cd whattoplay/server
# Dependencies installieren
npm install
# Backend als Service einrichten
uberspace web backend set / --http --port 3000
```
### Backend als Daemon (automatischer Start)
Erstelle `~/etc/services.d/whattoplay-server.ini`:
```ini
[program:whattoplay-server]
directory=%(ENV_HOME)s/whattoplay/server
command=node index.js
autostart=yes
autorestart=yes
startsecs=60
environment=PORT="3000"
```
Starte den Service:
```bash
supervisorctl reread
supervisorctl update
supervisorctl start whattoplay-server
supervisorctl status
```
## 2. PWA deployen
```bash
# Auf deinem lokalen Rechner
# Build mit Uberspace URL als base
npm run build
# Upload nach Uberspace
rsync -avz dist/ <username>@<servername>.uberspace.de:~/html/
# Oder direkt auf Uberspace builden:
cd ~/whattoplay
npm install
npm run build
cp -r dist/* ~/html/
```
## 3. Vite Config anpassen
Für Uberspace Deployment brauchst du keine spezielle `base`:
```typescript
// vite.config.ts
export default defineConfig({
// base: "/whattoplay/", // <- entfernen für Uberspace
plugins: [react()],
// ...
});
```
## 4. App Config anpassen
Für Development kannst du die `.env` nutzen:
```bash
# .env.development
VITE_API_URL=http://localhost:3000
# .env.production
VITE_API_URL=https://your-username.uber.space
```
Dann in `ConfigService.ts`:
```typescript
static getApiUrl(endpoint: string): string {
const baseUrl = import.meta.env.VITE_API_URL || '';
return `${baseUrl}${endpoint}`;
}
```
## 5. Domain einrichten (optional)
Falls du eine eigene Domain hast:
```bash
uberspace web domain add your-domain.com
```
Dann DNS Records setzen:
```
A @ <IP von uberspace>
CNAME www <servername>.uberspace.de
```
## Logs
```bash
# Server logs
supervisorctl tail whattoplay-server
# Webserver logs
tail -f ~/logs/webserver/access_log
```
## Updates deployen
```bash
# Backend update
cd ~/whattoplay
git pull
cd server
npm install
supervisorctl restart whattoplay-server
# PWA update
cd ~/whattoplay
npm install
npm run build
cp -r dist/* ~/html/
```
## Kosten
Uberspace: ~5€/Monat (pay what you want, Minimum 1€)
- Unbegrenzter Traffic
- SSH Zugriff
- Node.js, PHP, Python, Ruby Support
- MySQL/PostgreSQL Datenbanken
- Deutlich einfacher als Cloudflare Workers Setup

58
server/index.js Normal file
View File

@@ -0,0 +1,58 @@
import express from 'express';
import cors from 'cors';
import fetch from 'node-fetch';
const app = express();
const PORT = process.env.PORT || 3000;
// Enable CORS for your PWA
app.use(cors({
origin: process.env.ALLOWED_ORIGIN || '*'
}));
app.use(express.json());
// Health check
app.get('/health', (req, res) => {
res.json({ status: 'ok' });
});
// Proxy for Steam API - exactly like the worker
app.all('/api/*', async (req, res) => {
const path = req.url.replace('/api', '');
const steamUrl = `https://store.steampowered.com${path}`;
console.log(`Proxying: ${req.method} ${steamUrl}`);
try {
const response = await fetch(steamUrl, {
method: req.method,
headers: {
'User-Agent': 'WhatToPlay/1.0',
'Accept': 'application/json',
...(req.body && { 'Content-Type': 'application/json' })
},
...(req.body && { body: JSON.stringify(req.body) })
});
const contentType = response.headers.get('content-type');
if (contentType && contentType.includes('application/json')) {
const data = await response.json();
res.json(data);
} else {
const text = await response.text();
res.send(text);
}
} catch (error) {
console.error('Proxy error:', error);
res.status(500).json({
error: 'Proxy error',
message: error.message
});
}
});
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});

16
server/package.json Normal file
View File

@@ -0,0 +1,16 @@
{
"name": "whattoplay-server",
"version": "1.0.0",
"type": "module",
"description": "Simple proxy server for WhatToPlay Steam API calls",
"main": "index.js",
"scripts": {
"start": "node index.js",
"dev": "node --watch index.js"
},
"dependencies": {
"express": "^4.18.2",
"cors": "^2.8.5",
"node-fetch": "^3.3.2"
}
}

View File

@@ -130,8 +130,10 @@ export class ConfigService {
/**
* Get API URL for Steam refresh
* Development: Use local Vite server
* Production: Use Cloudflare Worker
* Supports multiple deployment scenarios:
* - Development: Vite dev server proxy
* - Uberspace: Backend on same domain via VITE_API_URL
* - Cloudflare Workers: User-configured Worker URL (fallback)
*/
static getApiUrl(endpoint: string, workerUrl?: string): string {
// Development mode: Use Vite dev server middleware
@@ -139,15 +141,22 @@ export class ConfigService {
return endpoint;
}
// Production mode: Use Cloudflare Worker
if (!workerUrl) {
throw new Error(
"Worker URL not configured. Please set up your Cloudflare Worker in Settings.",
);
// Production: Check for backend URL from environment
const backendUrl = import.meta.env.VITE_API_URL;
if (backendUrl) {
const baseUrl = backendUrl.replace(/\/$/, "");
return `${baseUrl}${endpoint}`;
}
// Ensure workerUrl doesn't have trailing slash
const baseUrl = workerUrl.replace(/\/$/, "");
return `${baseUrl}${endpoint}`;
// Fallback: Cloudflare Worker (if configured)
if (workerUrl) {
const baseUrl = workerUrl.replace(/\/$/, "");
return `${baseUrl}${endpoint}`;
}
// No backend configured
throw new Error(
"Backend not configured. Please deploy the server or set up a Cloudflare Worker.",
);
}
}

View File

@@ -23,7 +23,9 @@ const apiMiddlewarePlugin = {
};
export default defineConfig({
base: "/whattoplay/",
// GitHub Pages: /whattoplay/
// Uberspace: /
base: process.env.VITE_BASE_PATH || "/whattoplay/",
plugins: [react(), apiMiddlewarePlugin],
server: {
port: 5173,