Full MVP: workspace layout, visual refresh, PWA, production deploy
Major changes since initial commit: Schema: version branching (parentVersionId, branchLabel), share links, guest comments, track status enum (sketch/in_progress/final/released), track sections, cover art for projects and tracks. API: 29+ endpoints — auth, projects, tracks, versions, comments, share links (public + management), uploads (cover), activity feed, onboarding demo seed. Email templates in German with brand styling. Web: SvelteKit 5 workspace layout with persistent sidebar, breadcrumb top-bar, collapsible right panel. SoundCloud-style waveform player with round play button, avatar comment markers, keyboard shortcuts (Space/JKL/C). Full German UI. Cover art with gradient fallback. Track status pills. Activity feed dashboard. Welcome modal with demo-seed trigger. Landing page with 7-section scroll layout. Login on /login. Public /listen/:token page for guest feedback. Visual: Inter Variable font, Magenta→Orange gradient accent, warm dark neutrals, Lucide-style inline SVG icon set, spring animations on modals, glass-effect toasts, responsive from 360px to 2560px+. PWA: manifest, service worker, icons, iOS/Android installable. Production: adapter-node, server-side API proxy hook, docker-compose with Postgres + MinIO + auto-migration + health checks. Env example included. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,10 +1,19 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
import { checkAuth, user, authLoading } from '$lib/stores/auth.js';
|
||||
import { page } from '$app/stores';
|
||||
import { checkAuth, authLoading } from '$lib/stores/auth.js';
|
||||
import ToastContainer from '$lib/components/ui/ToastContainer.svelte';
|
||||
import '@fontsource-variable/inter';
|
||||
|
||||
let { children } = $props();
|
||||
|
||||
// Public routes that should never block on auth check
|
||||
const isPublic = $derived(
|
||||
$page.url.pathname === '/' ||
|
||||
$page.url.pathname === '/login' ||
|
||||
$page.url.pathname.startsWith('/listen/'),
|
||||
);
|
||||
|
||||
onMount(() => {
|
||||
checkAuth();
|
||||
});
|
||||
@@ -15,7 +24,7 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
</svelte:head>
|
||||
|
||||
{#if $authLoading}
|
||||
{#if $authLoading && !isPublic}
|
||||
<div class="loading">
|
||||
<div class="loading-spinner"></div>
|
||||
</div>
|
||||
@@ -27,33 +36,35 @@
|
||||
|
||||
<style>
|
||||
:global(:root) {
|
||||
/* Background */
|
||||
--color-bg-base: #0a0a0a;
|
||||
--color-bg-raised: #111111;
|
||||
--color-bg-overlay: #1a1a1a;
|
||||
--color-bg-subtle: #222222;
|
||||
/* Background — warm neutrals */
|
||||
--color-bg-base: #0a0910;
|
||||
--color-bg-raised: #131119;
|
||||
--color-bg-overlay: #1a1822;
|
||||
--color-bg-subtle: #221f2c;
|
||||
|
||||
/* Borders */
|
||||
--color-border: #2a2a2a;
|
||||
--color-border-hover: #333333;
|
||||
--color-border-focus: #6366f1;
|
||||
--color-border: #24222e;
|
||||
--color-border-hover: #32303c;
|
||||
--color-border-focus: #f43f5e;
|
||||
|
||||
/* Text */
|
||||
--color-text-primary: #f0f0f0;
|
||||
--color-text-secondary: #a0a0a0;
|
||||
--color-text-tertiary: #666666;
|
||||
--color-text-primary: #f4f0ec;
|
||||
--color-text-secondary: #9b96a8;
|
||||
--color-text-tertiary: #5e596b;
|
||||
|
||||
/* Accent */
|
||||
--color-accent: #6366f1;
|
||||
--color-accent-hover: #5558e6;
|
||||
--color-accent-subtle: #1a1a2e;
|
||||
/* Accent — warm magenta → orange */
|
||||
--color-accent: #f43f5e;
|
||||
--color-accent-2: #fb923c;
|
||||
--color-accent-hover: #e11d48;
|
||||
--color-accent-subtle: #2a121c;
|
||||
--gradient-accent: linear-gradient(135deg, #f43f5e 0%, #fb923c 100%);
|
||||
|
||||
/* Semantic */
|
||||
--color-success: #22c55e;
|
||||
--color-warning: #fbbf24;
|
||||
--color-error: #ef4444;
|
||||
|
||||
/* Spacing */
|
||||
/* Spacing — fluid scale */
|
||||
--space-1: 0.25rem;
|
||||
--space-2: 0.5rem;
|
||||
--space-3: 0.75rem;
|
||||
@@ -63,31 +74,39 @@
|
||||
--space-8: 2rem;
|
||||
--space-10: 2.5rem;
|
||||
--space-12: 3rem;
|
||||
--space-16: 4rem;
|
||||
--space-20: 5rem;
|
||||
|
||||
/* Radii */
|
||||
--radius-sm: 4px;
|
||||
--radius-md: 8px;
|
||||
--radius-lg: 12px;
|
||||
--radius-sm: 6px;
|
||||
--radius-md: 10px;
|
||||
--radius-lg: 14px;
|
||||
--radius-xl: 20px;
|
||||
--radius-full: 9999px;
|
||||
|
||||
/* Shadows */
|
||||
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
|
||||
--shadow-md: 0 4px 12px rgba(0, 0, 0, 0.5);
|
||||
--shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.6);
|
||||
/* Shadows — soft + warm */
|
||||
--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.5);
|
||||
--shadow-md: 0 8px 24px rgba(0, 0, 0, 0.4);
|
||||
--shadow-lg: 0 24px 60px rgba(0, 0, 0, 0.55);
|
||||
--shadow-glow: 0 0 0 1px rgba(244, 63, 94, 0.4), 0 8px 32px rgba(244, 63, 94, 0.18);
|
||||
|
||||
/* Typography */
|
||||
--font-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||
--font-mono: 'SF Mono', 'Fira Code', monospace;
|
||||
/* Typography — Inter first, system never */
|
||||
--font-sans: 'Inter Variable', 'Inter', system-ui, sans-serif;
|
||||
--font-mono: 'JetBrains Mono', 'SF Mono', 'Fira Code', monospace;
|
||||
--text-xs: 0.75rem;
|
||||
--text-sm: 0.85rem;
|
||||
--text-base: 0.9rem;
|
||||
--text-lg: 1.1rem;
|
||||
--text-sm: 0.875rem;
|
||||
--text-base: 0.9375rem;
|
||||
--text-lg: 1.125rem;
|
||||
--text-xl: 1.5rem;
|
||||
--text-2xl: 2rem;
|
||||
--text-3xl: 2.75rem;
|
||||
--text-4xl: 3.75rem;
|
||||
|
||||
/* Transitions */
|
||||
--transition-fast: 150ms ease;
|
||||
--transition-base: 200ms ease;
|
||||
/* Transitions — opinionated easing */
|
||||
--ease-out: cubic-bezier(0.16, 1, 0.3, 1);
|
||||
--ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
|
||||
--transition-fast: 120ms var(--ease-out);
|
||||
--transition-base: 200ms var(--ease-out);
|
||||
|
||||
/* Z-Index */
|
||||
--z-dropdown: 100;
|
||||
@@ -95,31 +114,76 @@
|
||||
--z-toast: 300;
|
||||
}
|
||||
|
||||
:global(html) {
|
||||
background: var(--color-bg-base);
|
||||
}
|
||||
|
||||
:global(body) {
|
||||
margin: 0;
|
||||
font-family: var(--font-sans);
|
||||
background: var(--color-bg-base);
|
||||
background:
|
||||
radial-gradient(ellipse 900px 500px at 12% -10%, rgba(244, 63, 94, 0.10), transparent 55%),
|
||||
radial-gradient(ellipse 700px 400px at 92% 110%, rgba(251, 146, 60, 0.06), transparent 60%),
|
||||
var(--color-bg-base);
|
||||
background-attachment: fixed;
|
||||
color: var(--color-text-secondary);
|
||||
font-size: var(--text-base);
|
||||
line-height: 1.5;
|
||||
line-height: 1.55;
|
||||
font-feature-settings: 'cv11', 'ss01', 'ss03';
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
text-rendering: optimizeLegibility;
|
||||
min-height: 100vh;
|
||||
/* Avoid iOS rubber-band white flash */
|
||||
overscroll-behavior-y: none;
|
||||
}
|
||||
|
||||
:global(*) {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
:global(h1, h2, h3) {
|
||||
:global(h1, h2, h3, h4) {
|
||||
color: var(--color-text-primary);
|
||||
letter-spacing: -0.02em;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
:global(h1) {
|
||||
letter-spacing: -0.03em;
|
||||
}
|
||||
|
||||
:global(a) {
|
||||
color: var(--color-accent);
|
||||
color: var(--color-text-primary);
|
||||
text-decoration: none;
|
||||
transition: color var(--transition-fast);
|
||||
}
|
||||
|
||||
:global(a:hover) {
|
||||
color: var(--color-accent-hover);
|
||||
color: var(--color-accent);
|
||||
}
|
||||
|
||||
:global(*:focus) {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
:global(*:focus-visible) {
|
||||
outline: 2px solid var(--color-accent);
|
||||
outline-offset: 2px;
|
||||
border-radius: var(--radius-sm);
|
||||
}
|
||||
|
||||
:global(::selection) {
|
||||
background: var(--color-accent);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
:global(*),
|
||||
:global(*::before),
|
||||
:global(*::after) {
|
||||
animation-duration: 0.01ms !important;
|
||||
transition-duration: 0.01ms !important;
|
||||
}
|
||||
}
|
||||
|
||||
.loading {
|
||||
|
||||
Reference in New Issue
Block a user