Add Nostr relay + seed data to Docker deployment

- Add nostr-rs-relay service to docker-compose for persistent
  comments, reactions, and profiles on the dev server
- Add one-shot seeder container that auto-populates the relay
  with test personas, reactions, and comments on first deploy
- Proxy WebSocket connections through nginx at /relay so the
  frontend connects to the relay on the same host (no CORS)
- Make relay URL dynamic: reads from VITE_NOSTR_RELAYS in dev,
  auto-detects /relay proxy path in production Docker builds
- Make seed scripts configurable via RELAY_URL and ORIGIN env vars
- Add wait-for-relay script for reliable container orchestration
- Add "Resume last played" hero banner on My List tab

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Dorian
2026-02-12 12:33:22 +00:00
parent 725896673c
commit 0a7543cf32
9 changed files with 162 additions and 12 deletions

View File

@@ -11,8 +11,8 @@ import {
TASTEMAKER_PERSONAS,
} from '../src/data/testPersonas.js'
const RELAY_URL = 'ws://localhost:7777'
const ORIGIN = 'http://localhost:5174'
const RELAY_URL = process.env.RELAY_URL || 'ws://localhost:7777'
const ORIGIN = process.env.ORIGIN || 'http://localhost:5174'
// ── Content catalog (matching src/data/indeeHubFilms.ts) ──────────
const CONTENT = [

View File

@@ -5,7 +5,7 @@ import {
TASTEMAKER_PERSONAS,
} from '../src/data/testPersonas.js'
const RELAY_URL = 'ws://localhost:7777'
const RELAY_URL = process.env.RELAY_URL || 'ws://localhost:7777'
type Persona = { name: string; nsec: string; pubkey: string }

View File

@@ -0,0 +1,40 @@
/**
* Waits for the Nostr relay to be reachable before seeding.
* Used by the Docker seeder container.
*
* Usage: node scripts/wait-for-relay.mjs
* Env: RELAY_URL (default ws://localhost:7777)
*/
import http from 'node:http'
const wsUrl = process.env.RELAY_URL || 'ws://localhost:7777'
const httpUrl = wsUrl.replace('ws://', 'http://').replace('wss://', 'https://')
const maxAttempts = 30
const intervalMs = 2000
console.log(`Waiting for relay at ${httpUrl} ...`)
for (let i = 1; i <= maxAttempts; i++) {
const ok = await new Promise((resolve) => {
const req = http.get(httpUrl, (res) => {
res.resume() // drain response
resolve(res.statusCode >= 200 && res.statusCode < 400)
})
req.on('error', () => resolve(false))
req.setTimeout(3000, () => {
req.destroy()
resolve(false)
})
})
if (ok) {
console.log(`Relay is ready! (attempt ${i}/${maxAttempts})`)
process.exit(0)
}
console.log(` attempt ${i}/${maxAttempts} — not ready yet`)
await new Promise((r) => setTimeout(r, intervalMs))
}
console.error(`Relay did not become ready after ${maxAttempts} attempts`)
process.exit(1)