Files
MelodyMuse/deploy/README.md
T
Jannik d8b25ec6ab Move LLM key to the server, add random-style buttons
Architectural change

The browser no longer talks to the LLM directly. A new Node server
(server.mjs) sits in the middle:

  [Browser] → [Node :3000] → [LLM provider]
    (no key)    (key in .env)

server.mjs is the production runtime: it serves the built SPA out of
dist/ and exposes three JSON endpoints that proxy to the LLM with
credentials held in process.env. The browser-side llm.ts is now a thin
fetch wrapper.

- server.mjs: single-file Node server, no production deps
- server/prompts.mjs: system + user prompt construction (was client-side)
- src/lib/prompts.ts removed (moved server-side)
- src/lib/llm.ts rewritten — no more direct LLM calls, no more
  JSON extraction, no more validation; just fetch the proxy
- src/lib/types.ts: drop SaveConfigPayload/TestConnectionResult, add
  style_hint and ServerStatus
- vite.config.ts: proxy /api/* → localhost:3000 in dev
- .env.example: LLM_* and PORT/CORS_ORIGIN instead of Supabase values

New feature: random style buttons

The Options → Music style field now has two AI buttons that fill it
with a fresh Suno style description:
- 'Surprise me' → coherent, production-ready style (max 25 words)
- 'Go crazy'   → deliberately clashing genre mashup (max 25 words)

The buttons hit a dedicated /api/style/random endpoint on the server
that uses a small, focused system prompt. Each click overwrites the
field. Both buttons show a spinner and disable while a request is
in flight. Errors surface as toasts. AbortController is used so a
fast second click cancels the first.

When the Music style field is non-empty at generation time, its value
is sent to the model as style_hint and used as the basis for the full
120-word style field (per the updated system prompt).

Other UX

- Settings page is now a server-status page: green/red indicator,
  model + endpoint, re-check button. The API key is no longer
  configurable in the browser (it never was reachable anyway — now
  the UI is honest about that).
- Home page header shows a small 'Server offline' warning when the
  server is unreachable.
- Settings has a Local data section: list what's in localStorage
  with one-click clear-history and clear-all buttons (with confirm).
- Esc cancels any in-flight generation.
- ZIP filename falls back to 'song' if the title sanitizes to empty.

Deployment

deploy/ holds reference files (Dockerfile, docker-compose example,
Caddy fragment, generate-env.sh, README) for adding the service to a
Jannik-Cloud-style stack. The repo is intentionally not wired into
the Jannik-Cloud repo; copy the four files when ready.
2026-06-03 08:01:21 +02:00

2.6 KiB

Deploying MelodyMuse

The files in this folder are reference templates. MelodyMuse is a single Node.js server (server.mjs in the repo root) that serves the built SPA and proxies LLM calls. To deploy it you can:

  • Run node server.mjs directly (after npm run build)
  • Use the included Dockerfile + docker-compose.yml
  • Copy these into your Jannik-Cloud services/melodymuse/ directory

Required environment variables

Var Required? Default Notes
LLM_ENDPOINT yes OpenAI-compatible base URL, e.g. https://api.minimax.chat/v1
LLM_API_KEY yes Provider secret key. Never set this in the browser.
LLM_MODEL no MiniMax-M3 Model name
PORT no 3000 Listen port
CORS_ORIGIN no * Set to a specific origin in production if you split SPA and server

The server refuses to start if LLM_ENDPOINT or LLM_API_KEY is missing.

Option 1 — Bare Node

# Clone, build, run
git clone https://git.orfel.de/Jannik/MelodyMuse.git
cd MelodyMuse
npm ci
npm run build

# Set the secrets and start
export LLM_ENDPOINT=https://api.minimax.chat/v1
export LLM_API_KEY=sk-...
npm start

Option 2 — Docker

# Build
docker build -f deploy/Dockerfile -t melodymuse .

# Run
docker run --rm -p 3000:3000 \
  -e LLM_ENDPOINT=https://api.minimax.chat/v1 \
  -e LLM_API_KEY=sk-... \
  melodymuse

Option 3 — Add to Jannik-Cloud

  1. Create services/melodymuse/ in your Jannik-Cloud repo.
  2. Copy the four files from this folder into it:
    • Dockerfile
    • docker-compose.yml (rename from docker-compose.example.yml)
    • melodymuse.caddy
    • generate-env.sh
  3. touch services/melodymuse/service.enabled
  4. bash services/melodymuse/generate-env.sh — answer the prompts.
  5. Commit services/melodymuse/.env.age and the four non-secret files.
  6. sudo bash /opt/Jannik-Cloud/deploy_script.sh — Caddy will pick up melodymuse.orfel.de and route it to the container.

Endpoints exposed by the server

Method Path Purpose
GET /api/health Health check. Returns { ok, llm_configured, model, endpoint }.
POST /api/generate Main generation. Body matches the GenerateRequest shape.
POST /api/style/random Returns a one-line Suno style. Body: { mode: "normal" | "crazy" }.
GET everything else Serves the built SPA from dist/, with SPA fallback to index.html.

Image footprint

The runtime image is node:20-alpine with only server.mjs and the built SPA. No production npm install (server.mjs uses only Node built-ins). Total image size is roughly 200 MB.