Commit Graph
7 Commits
Author SHA1 Message Date
Jannik d34d34565f feat: complete UI overhaul (liquid glass theme, i18n, FontAwesome) 2026-06-03 22:00:37 +02:00
Jannik 9980d5ba20 Remove duplicate MelodyMuse brand row in InputPanel
The home page header already shows a small equalizer + 'MelodyMuse'
wordmark. Having a second brand row inside the InputPanel was
redundant and pushed the textarea down. Removed it; the form now
starts directly with the 'Music idea' label. Bumped the textarea
rows from 4 to 5 to fill the freed space.

Also added: the server-status check on the home page now re-runs
every 30s, so the 'Server offline' hint in the header stays current
without a manual refresh.
2026-06-03 17:37:11 +02:00
Jannik 81aefe0700 Modernize the UI and fix the equalizer sizing bug
Bug fix

- EqualizerIcon: the SVG was rendering at the wrong size (filling
  its parent) because it had no explicit width/height attributes.
  Now it accepts a size prop with a 24px default and the SVG element
  carries the size as width/height attributes, with the className
  on top. Can't accidentally balloon.

Design

- Stripped the light-mode CSS — the app is dark-only now, and the
  theme toggle was a no-op (clicking it just toggled a class that
  had no matching rules). ThemeToggle.tsx and lib/theme.ts are
  gone; initTheme() call removed from main.tsx.

- Reworked the input form:
    • brand row is now small + refined (icon + wordmark, no huge
      gradient title)
    • Options is a single subtle collapsible card with a chevron and
      a count badge showing how many options are non-default
    • Vocals is now a segmented pill (single rounded container, two
      flat segments) instead of two full-width grid buttons
    • Generate button is slightly smaller (py-3.5, text-sm) and
      uses a softer shadow (shadow-violet-900/20)

- Empty state in the results panel: dashed-border card, soft
  gradient blur behind the music icon, cleaner copy.

- Results header: smaller heading, the 'Regenerate All' and
  'Cancel' buttons are now tiny ghost-style pills in the top-right.

- Sticky ZIP bar: softer shadow, more refined copy.

- Result cards: smaller icon, single-line title, the Regenerate
  button is now an inline pill that fits next to Revert + Copy.

- Home page header now has a tiny equalizer icon + 'MelodyMuse'
  wordmark on the left (was just text). Settings page header has
  the back arrow on the left and the title, no theme toggle.

- Global CSS: added modern focus-visible ring, custom selection
  color, subtle scrollbar thumb, slightly tweaked the gradient
  text to a softer violet-300 → cyan-300 instead of the loud
  violet-400 → fuchsia-400 → cyan-400.
2026-06-03 10:49:58 +02:00
Jannik 3096669a13 Polish: draft autosave, history refresh, outdated footer, more
Bug fixes / UX

- Footer: the privacy line still claimed 'generation runs in your
  browser'. Now correctly says the generation runs on the server and
  the key never reaches the browser.

- History panel: when the panel was open while a new generation
  completed, the new entry didn't appear until the user closed and
  re-opened the panel. The history module now dispatches a custom
  'melodymuse-history-updated' event on every write; the panel
  listens and re-reads. removeFromHistory/clearHistory emit too.
  writeAll is also now try/catch'd against quota errors.

- Auto-save the input form: the input is persisted to localStorage
  ('melodymuse-draft', debounced 400ms) so a refresh doesn't wipe
  what the user was typing. The initial state hydrates from the
  draft on mount.

- Cmd/Ctrl+Enter now works in the Music style field as well as
  the idea field — shared onKeyDown handler, propagated through the
  StyleField sub-component.

- Full regen ('Generate' / 'Regenerate All') now clears the previous
  assets before kicking off the new request, so the skeleton state
  shows during the round-trip instead of stale cards with a spinner
  on top. Per-section regen still leaves the other cards intact.

- Settings → Local data: the in-progress draft is now listed
  alongside history and theme, and has its own 'Clear in-progress
  draft' button. The 'Clear all local data' button clears it too.
2026-06-03 08:59:31 +02:00
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
Jannik b945417773 Add cancel, history, revert, and quality-of-life features
UX

- Add elapsed-time counter and Cancel button to in-flight generations,
  wired through AbortController so partial responses are discarded
  cleanly. The cancel action is available from both the input panel
  and the results header.
- Add a Recent generations panel below the input. The last 6 successful
  generations are saved to localStorage; one click reloads both the
  input fields and the generated assets.
- Add a Revert button to every editable card. It appears the moment
  the current value diverges from the last generated value and restores
  the field with a single click.
- Add an Empty state to the right panel with a friendly hint pointing
  at the Generate button and the Settings page.
- Add a 'Try an example' button that fills the input with a random
  starter idea (idea + mood + vocals).
- Add Cmd/Ctrl+Enter as a keyboard shortcut to generate.
- Add a Footer with project info and a privacy reminder.
- Add a 'Clear saved key' button to the Settings page so the user can
  remove the API key without overwriting it.

Bug fix

- Settings > Test Connection used to save the in-progress form values
  to localStorage before testing. It now uses the in-memory candidate
  config, so failed tests don't pollute the saved config.

Code quality

- Extract the duplicated useAutoHeight hook to src/lib/useAutoHeight.ts.
- Extract a useElapsed hook for the loading timer.
- Move InputValues into src/lib/types.ts (was duplicated in
  InputPanel.tsx) and add SECTION_LABELS, replacing the humanizeSection
  switch in HomePage.
- Centralize the filename sanitization: HomePage now calls
  sanitizeFilename from zip.ts instead of duplicating the regex.
- Add previewConfig / testConnectionWithConfig helpers to llm.ts to
  support in-memory connection tests.
2026-06-03 01:47:11 +02:00
Jannik d42410560f Build standalone MelodyMuse SPA
Drop the Supabase backend and call the AI provider directly from the
browser. The endpoint URL, API key, and model name are stored in
localStorage and used for direct /chat/completions requests.

- src/lib/llm.ts: config persistence, direct fetch, JSON extraction,
  shape validation, connection test
- src/lib/prompts.ts: full + partial-regeneration system prompts and
  user-message builder
- src/lib/{api,supabase}.ts removed
- supabase/ directory removed
- @supabase/supabase-js dropped from package.json
- README updated to describe the standalone architecture and CORS caveats
- .gitignore: drop Supabase entries, exclude *.tsbuildinfo
2026-06-03 01:25:22 +02:00