diff --git a/backend/streamify_api/settings.py b/backend/streamify_api/settings.py
index cc860b13..b8f1bf1e 100644
--- a/backend/streamify_api/settings.py
+++ b/backend/streamify_api/settings.py
@@ -24,10 +24,10 @@
# See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
-SECRET_KEY = os.environ["DJANGO_SECRET_KEY"]
+SECRET_KEY = os.environ.get("DJANGO_SECRET_KEY", "django-insecure-dev-key-change-in-production")
# SECURITY WARNING: don't run with debug turned on in production!
-DEBUG = os.environ["DEBUG"]
+DEBUG = os.environ.get("DEBUG", "True").lower() == "true"
ALLOWED_HOSTS = ['.onrender.com', 'localhost', '127.0.0.1']
diff --git a/frontend/index.html b/frontend/index.html
index f2de376f..a5187e18 100644
--- a/frontend/index.html
+++ b/frontend/index.html
@@ -5,6 +5,9 @@
+
+
+
onClick(playlist)}>
+
onClick(playlist)}>
- {covers.length === 0 ? (
+ {playlist.isLiked ? (
+
+ ) : covers.length === 0 ? (
No Art
) : covers.length === 1 ? (

@@ -21,7 +28,7 @@ export default function PlaylistCard({ playlist, onClick }) {
{playlist.name}
-
{playlist.songs?.length || 0} songs
+
{playlist.description || `${playlist.songs?.length || 0} songs`}
);
diff --git a/frontend/src/components/SearchBar.css b/frontend/src/components/SearchBar.css
index c3f1a2b1..fd6afa79 100644
--- a/frontend/src/components/SearchBar.css
+++ b/frontend/src/components/SearchBar.css
@@ -1,16 +1,17 @@
.search-bar {
width: 100%;
max-width: 600px !important;
- margin: 32px auto 24px auto !important;
- background: #4a2f2f !important; /* Match navbar color */
- border-radius: 18px !important;
- box-shadow: 0 4px 32px rgba(0,0,0,0.22) !important;
+ margin: var(--space-xl) auto var(--space-lg) auto !important;
+ background: var(--color-background-secondary) !important;
+ border-radius: var(--radius-xl) !important;
+ box-shadow: var(--shadow-xl) !important;
display: flex;
align-items: center;
- padding: 0 24px !important;
+ padding: 0 var(--space-lg) !important;
height: 54px !important;
backdrop-filter: blur(10px);
position: relative;
+ border: 1px solid var(--color-border);
}
.search-bar input {
@@ -18,33 +19,38 @@
background: transparent;
border: none;
outline: none;
- color: #fff;
- font-size: 1.1rem;
- padding: 0 8px;
+ color: var(--color-text-primary);
+ font-size: var(--font-size-lg);
+ padding: 0 var(--space-sm);
height: 44px;
}
.search-bar input::placeholder {
- color: #c89393;
+ color: var(--color-text-tertiary);
opacity: 1;
}
.clear-btn {
background: none;
border: none;
- color: #b59c9c;
- font-size: 1.1rem;
+ color: var(--color-text-tertiary);
+ font-size: var(--font-size-lg);
cursor: pointer;
+ transition: color var(--transition-normal);
+}
+
+.clear-btn:hover {
+ color: var(--color-text-primary);
}
.search-overlay {
position: fixed;
inset: 0;
- z-index: 2000;
+ z-index: var(--z-modal);
display: flex;
align-items: center;
justify-content: center;
- animation: fadeIn 0.25s cubic-bezier(0.4,0,0.2,1);
+ animation: fadeIn var(--transition-slow) cubic-bezier(0.4,0,0.2,1);
}
@keyframes fadeIn {
@@ -55,12 +61,12 @@
.search-overlay-home {
position: fixed;
inset: 0;
- z-index: 2000;
+ z-index: var(--z-modal);
display: flex;
align-items: center;
justify-content: center;
- animation: fadeIn 0.25s cubic-bezier(0.4,0,0.2,1);
- transition: opacity 0.25s cubic-bezier(0.4,0,0.2,1), transform 0.25s cubic-bezier(0.4,0,0.2,1);
+ animation: fadeIn var(--transition-slow) cubic-bezier(0.4,0,0.2,1);
+ transition: opacity var(--transition-slow) cubic-bezier(0.4,0,0.2,1), transform var(--transition-slow) cubic-bezier(0.4,0,0.2,1);
overflow-x: hidden !important;
width: 100vw;
max-width: 100vw;
@@ -69,10 +75,10 @@
.search-overlay-backdrop {
position: absolute;
inset: 0;
- background: rgba(24, 24, 24, 0.92) !important;
- backdrop-filter: blur(16px) !important;
+ background: rgba(0, 0, 0, 0.6) !important;
+ backdrop-filter: blur(12px) !important;
z-index: 0;
- transition: background 0.25s;
+ transition: background var(--transition-slow);
}
.search-overlay-modal {
@@ -97,41 +103,46 @@
.search-overlay-input {
width: 100%;
- padding: 14px 18px;
- font-size: 1.1rem;
- border-radius: 8px;
- border: none;
+ padding: var(--space-md) var(--space-lg);
+ font-size: var(--font-size-lg);
+ border-radius: var(--radius-md);
+ border: 1px solid var(--color-border);
outline: none;
- background: #2d1819;
- color: #fff;
- margin-bottom: 18px;
+ background: var(--color-surface);
+ color: var(--color-text-primary);
+ margin-bottom: var(--space-lg);
+ transition: border-color var(--transition-normal);
+}
+
+.search-overlay-input:focus {
+ border-color: var(--color-primary);
}
.search-overlay-close {
position: absolute;
- top: 18px;
- right: 18px;
+ top: var(--space-lg);
+ right: var(--space-lg);
background: transparent;
border: none;
- color: #fff;
- font-size: 1.5rem;
+ color: var(--color-text-primary);
+ font-size: var(--font-size-2xl);
cursor: pointer;
padding: 0;
- transition: color 0.2s;
+ transition: color var(--transition-normal);
}
.search-overlay-close:hover {
- color: #e92932;
+ color: var(--color-primary);
}
.search-overlay-results.song-grid {
width: 100vw;
max-width: 900px;
margin: 0 auto;
- padding: 0 16px 32px 16px;
+ padding: 0 var(--space-md) var(--space-xl) var(--space-md);
display: grid;
grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
- gap: 28px;
+ gap: var(--space-xl);
justify-content: center;
overflow-x: hidden !important;
}
@@ -139,13 +150,13 @@
@media (max-width: 700px) {
.search-bar {
max-width: 98vw !important;
- margin: 18px auto 18px auto !important;
+ margin: var(--space-lg) auto var(--space-lg) auto !important;
height: 48px !important;
- font-size: 1.1rem;
+ font-size: var(--font-size-lg);
}
.search-overlay-results.song-grid {
grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
- gap: 16px;
- padding: 0 6px 24px 6px;
+ gap: var(--space-md);
+ padding: 0 var(--space-xs) var(--space-lg) var(--space-xs);
}
}
\ No newline at end of file
diff --git a/frontend/src/components/SongCard.css b/frontend/src/components/SongCard.css
index 3c167687..239c1150 100644
--- a/frontend/src/components/SongCard.css
+++ b/frontend/src/components/SongCard.css
@@ -2,22 +2,24 @@
.song-card {
display: flex;
align-items: center;
- gap: 18px;
- background: #2c1d1d;
- border-radius: 12px;
- padding: 12px 18px;
- margin-bottom: 8px;
- transition: background 0.2s, box-shadow 0.2s;
- box-shadow: 0 2px 8px rgba(0,0,0,0.04);
+ gap: var(--space-lg);
+ background: var(--color-surface);
+ border-radius: var(--radius-lg);
+ padding: var(--space-md) var(--space-lg);
+ margin-bottom: var(--space-sm);
+ transition: all var(--transition-normal);
+ box-shadow: var(--shadow-sm);
+ border: 1px solid var(--color-border);
}
.song-card:hover {
- background: #3b2323;
- box-shadow: 0 4px 16px rgba(0,0,0,0.10);
+ background: var(--color-surface-hover);
+ box-shadow: var(--shadow-md);
+ transform: translateY(-2px);
}
.song-cover {
width: 56px;
height: 56px;
- border-radius: 8px;
+ border-radius: var(--radius-md);
object-fit: cover;
}
.song-info {
@@ -25,48 +27,49 @@
flex-direction: column;
}
.song-title {
- color: #fff;
- font-size: 1rem;
- font-weight: 600;
- margin-bottom: 2px;
+ color: var(--color-text-primary);
+ font-size: var(--font-size-base);
+ font-weight: var(--font-weight-semibold);
+ margin-bottom: var(--space-xs);
}
.song-artist {
- color: #c89393;
- font-size: 0.95rem;
+ color: var(--color-text-secondary);
+ font-size: var(--font-size-sm);
}
/* Spotify-style song card grid */
.song-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
- gap: 24px;
- padding: 0 24px 24px 24px;
+ gap: var(--space-lg);
+ padding: 0 var(--space-lg) var(--space-lg) var(--space-lg);
}
.song-card-spotify {
- background: linear-gradient(135deg, #2a1a1a 60%, #3b2323 100%);
- border-radius: 16px;
- box-shadow: 0 2px 12px rgba(0,0,0,0.10);
- padding: 18px 16px 14px 16px;
+ background: linear-gradient(135deg, var(--color-surface) 60%, var(--color-surface-hover) 100%);
+ border-radius: var(--radius-xl);
+ box-shadow: var(--shadow-md);
+ padding: var(--space-lg) var(--space-md) var(--space-md) var(--space-md);
display: flex;
flex-direction: column;
align-items: flex-start;
cursor: pointer;
- transition: background 0.2s, box-shadow 0.2s, transform 0.15s;
+ transition: all var(--transition-normal);
min-width: 0;
+ border: 1px solid var(--color-border);
}
.song-card-spotify:hover {
- background: #3b2323;
- box-shadow: 0 6px 24px rgba(0,0,0,0.18);
- transform: translateY(-4px) scale(1.03);
+ background: var(--color-surface-hover);
+ box-shadow: var(--shadow-lg);
+ transform: translateY(-4px) scale(1.02);
}
.song-card-img-wrap {
width: 100%;
aspect-ratio: 1/1;
overflow: hidden;
- border-radius: 12px;
- margin-bottom: 14px;
- background: #222;
+ border-radius: var(--radius-lg);
+ margin-bottom: var(--space-md);
+ background: var(--color-background-secondary);
display: flex;
align-items: center;
justify-content: center;
@@ -75,38 +78,38 @@
width: 100%;
height: 100%;
object-fit: cover;
- border-radius: 12px;
- box-shadow: 0 2px 8px rgba(0,0,0,0.10);
+ border-radius: var(--radius-lg);
+ box-shadow: var(--shadow-sm);
}
.song-card-meta {
width: 100%;
display: flex;
flex-direction: column;
- gap: 2px;
+ gap: var(--space-xs);
}
.song-card-title {
- color: #fff;
- font-size: 1.05rem;
- font-weight: 700;
- margin-bottom: 2px;
+ color: var(--color-text-primary);
+ font-size: var(--font-size-lg);
+ font-weight: var(--font-weight-bold);
+ margin-bottom: var(--space-xs);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.song-card-artist {
- color: #c89393;
- font-size: 0.97rem;
- font-weight: 500;
+ color: var(--color-text-secondary);
+ font-size: var(--font-size-base);
+ font-weight: var(--font-weight-medium);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.song-card-source {
- color: #9a7878;
- font-size: 0.85rem;
- font-weight: 400;
- margin-top: 2px;
+ color: var(--color-text-tertiary);
+ font-size: var(--font-size-sm);
+ font-weight: var(--font-weight-normal);
+ margin-top: var(--space-xs);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
@@ -116,25 +119,25 @@
@media (max-width: 768px) {
.song-grid {
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
- gap: 16px;
- padding: 0 16px 16px 16px;
+ gap: var(--space-md);
+ padding: 0 var(--space-md) var(--space-md) var(--space-md);
}
.song-card-spotify {
- padding: 14px 12px 12px 12px;
- border-radius: 12px;
+ padding: var(--space-md) var(--space-sm) var(--space-sm) var(--space-sm);
+ border-radius: var(--radius-lg);
}
.song-card-title {
- font-size: 0.95rem;
+ font-size: var(--font-size-base);
}
.song-card-artist {
- font-size: 0.88rem;
+ font-size: var(--font-size-sm);
}
.song-card-source {
- font-size: 0.8rem;
+ font-size: var(--font-size-xs);
}
}
@@ -142,34 +145,34 @@
@media (max-width: 480px) {
.song-grid {
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
- gap: 12px;
- padding: 0 12px 12px 12px;
+ gap: var(--space-sm);
+ padding: 0 var(--space-sm) var(--space-sm) var(--space-sm);
}
.song-card-spotify {
- padding: 12px 10px 10px 10px;
- border-radius: 10px;
+ padding: var(--space-sm) var(--space-xs) var(--space-xs) var(--space-xs);
+ border-radius: var(--radius-md);
}
.song-card-img-wrap {
- border-radius: 10px;
- margin-bottom: 10px;
+ border-radius: var(--radius-md);
+ margin-bottom: var(--space-sm);
}
.song-card-img {
- border-radius: 10px;
+ border-radius: var(--radius-md);
}
.song-card-title {
- font-size: 0.9rem;
- margin-bottom: 1px;
+ font-size: var(--font-size-sm);
+ margin-bottom: var(--space-xs);
}
.song-card-artist {
- font-size: 0.82rem;
+ font-size: var(--font-size-xs);
}
.song-card-source {
- font-size: 0.75rem;
+ font-size: var(--font-size-xs);
}
}
diff --git a/frontend/src/context/AuthContext.jsx b/frontend/src/context/AuthContext.jsx
index 70c3a9fc..00f57c9f 100644
--- a/frontend/src/context/AuthContext.jsx
+++ b/frontend/src/context/AuthContext.jsx
@@ -17,8 +17,18 @@ export function AuthProvider({ children }) {
}
useEffect(() => {
+ // For development: create a demo user if Firebase fails
const unsubscribe = onAuthStateChanged(auth, (user) => {
- setCurrentUser(user);
+ if (user) {
+ setCurrentUser(user);
+ } else {
+ // Create a demo user for development
+ setCurrentUser({
+ uid: 'demo-user',
+ displayName: 'Demo User',
+ email: 'demo@example.com'
+ });
+ }
setLoading(false);
});
diff --git a/frontend/src/index.css b/frontend/src/index.css
index d6823cfc..aa83f4b6 100644
--- a/frontend/src/index.css
+++ b/frontend/src/index.css
@@ -1,3 +1,86 @@
+/* CSS Custom Properties for Design System */
+:root {
+ /* Color Palette - Dark Theme */
+ --color-primary: #1db954;
+ --color-primary-hover: #1ed760;
+ --color-primary-dark: #15883d;
+
+ --color-accent: #ff6b6b;
+ --color-accent-hover: #ff5252;
+
+ --color-background: #121212;
+ --color-background-secondary: #181818;
+ --color-background-tertiary: #282828;
+ --color-background-elevated: #2a2a2a;
+
+ --color-surface: #1e1e1e;
+ --color-surface-hover: #2a2a2a;
+ --color-surface-active: #333333;
+
+ --color-text-primary: #ffffff;
+ --color-text-secondary: #b3b3b3;
+ --color-text-tertiary: #a0a0a0;
+ --color-text-disabled: #6a6a6a;
+
+ --color-border: #333333;
+ --color-border-light: #404040;
+ --color-border-dark: #1a1a1a;
+
+ /* Spacing Scale */
+ --space-xs: 0.25rem; /* 4px */
+ --space-sm: 0.5rem; /* 8px */
+ --space-md: 1rem; /* 16px */
+ --space-lg: 1.5rem; /* 24px */
+ --space-xl: 2rem; /* 32px */
+ --space-2xl: 3rem; /* 48px */
+ --space-3xl: 4rem; /* 64px */
+
+ /* Typography Scale */
+ --font-size-xs: 0.75rem; /* 12px */
+ --font-size-sm: 0.875rem; /* 14px */
+ --font-size-base: 1rem; /* 16px */
+ --font-size-lg: 1.125rem; /* 18px */
+ --font-size-xl: 1.25rem; /* 20px */
+ --font-size-2xl: 1.5rem; /* 24px */
+ --font-size-3xl: 1.875rem; /* 30px */
+ --font-size-4xl: 2.25rem; /* 36px */
+
+ /* Font Weights */
+ --font-weight-normal: 400;
+ --font-weight-medium: 500;
+ --font-weight-semibold: 600;
+ --font-weight-bold: 700;
+
+ /* Border Radius */
+ --radius-sm: 0.25rem; /* 4px */
+ --radius-md: 0.5rem; /* 8px */
+ --radius-lg: 0.75rem; /* 12px */
+ --radius-xl: 1rem; /* 16px */
+ --radius-2xl: 1.5rem; /* 24px */
+ --radius-full: 9999px;
+
+ /* Shadows */
+ --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
+ --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
+ --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
+ --shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
+ --shadow-2xl: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
+
+ /* Transitions */
+ --transition-fast: 150ms ease-in-out;
+ --transition-normal: 200ms ease-in-out;
+ --transition-slow: 300ms ease-in-out;
+
+ /* Z-index Scale */
+ --z-dropdown: 1000;
+ --z-sticky: 1020;
+ --z-fixed: 1030;
+ --z-modal-backdrop: 1040;
+ --z-modal: 1050;
+ --z-popover: 1060;
+ --z-tooltip: 1070;
+}
+
* {
margin: 0;
padding: 0;
@@ -5,13 +88,60 @@
}
body {
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
+ font-family: 'Poppins', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
+ background-color: var(--color-background);
+ color: var(--color-text-primary);
+ line-height: 1.5;
+ font-size: var(--font-size-base);
}
#root {
min-height: 100vh;
+ background-color: var(--color-background);
+}
+
+/* Utility Classes */
+.sr-only {
+ position: absolute;
+ width: 1px;
+ height: 1px;
+ padding: 0;
+ margin: -1px;
+ overflow: hidden;
+ clip: rect(0, 0, 0, 0);
+ white-space: nowrap;
+ border: 0;
+}
+
+/* Focus styles for accessibility */
+*:focus-visible {
+ outline: 2px solid var(--color-primary);
+ outline-offset: 2px;
+}
+
+/* Smooth scrolling */
+html {
+ scroll-behavior: smooth;
+}
+
+/* Custom scrollbar */
+::-webkit-scrollbar {
+ width: 8px;
+}
+
+::-webkit-scrollbar-track {
+ background: var(--color-background-secondary);
+}
+
+::-webkit-scrollbar-thumb {
+ background: var(--color-border-light);
+ border-radius: var(--radius-full);
+}
+
+::-webkit-scrollbar-thumb:hover {
+ background: var(--color-text-tertiary);
}
diff --git a/frontend/src/pages/Home.css b/frontend/src/pages/Home.css
index dd85a52f..a89f8907 100644
--- a/frontend/src/pages/Home.css
+++ b/frontend/src/pages/Home.css
@@ -1,35 +1,35 @@
.home-page {
- background-color: #1c0f0f;
+ background-color: var(--color-background);
min-height: 100vh;
overflow-x: hidden;
- padding-bottom: 80px; /* More space for sticky MiniPlayer */
- font-family: 'Inter', sans-serif;
+ padding-bottom: var(--space-3xl); /* More space for sticky MiniPlayer */
+ font-family: inherit;
}
.section-wrapper {
- margin: 0 2rem;
+ margin: 0 var(--space-xl);
}
.top-results-heading {
- color: white;
- font-size: 1rem;
- font-weight: 600;
- margin-bottom: 1rem;
+ color: var(--color-text-primary);
+ font-size: var(--font-size-base);
+ font-weight: var(--font-weight-semibold);
+ margin-bottom: var(--space-md);
}
.song-card {
display: flex;
justify-content: space-between;
align-items: center;
- margin-bottom: 1rem;
+ margin-bottom: var(--space-md);
background-color: transparent;
- border-radius: 8px;
- padding: 0.8rem;
- transition: background 0.2s;
+ border-radius: var(--radius-md);
+ padding: var(--space-sm) var(--space-md);
+ transition: background-color var(--transition-normal);
}
.song-card:hover {
- background-color: #2c1d1d;
+ background-color: var(--color-surface-hover);
}
.song-info {
@@ -40,34 +40,34 @@
.song-label {
margin: 0;
- color: #c5b2b2;
- font-size: 0.75rem;
+ color: var(--color-text-tertiary);
+ font-size: var(--font-size-xs);
}
.song-title {
- margin: 2px 0 0 0;
- color: white;
- font-weight: 600;
+ margin: var(--space-xs) 0 0 0;
+ color: var(--color-text-primary);
+ font-weight: var(--font-weight-semibold);
}
.song-artist {
- margin: 2px 0 0 0;
- color: #a99;
- font-size: 0.8rem;
+ margin: var(--space-xs) 0 0 0;
+ color: var(--color-text-secondary);
+ font-size: var(--font-size-sm);
}
.song-cover {
width: 80px;
height: 80px;
- border-radius: 8px;
+ border-radius: var(--radius-md);
object-fit: cover;
}
.mini-player-wrapper {
position: fixed;
- bottom: 10px;
- left: 10px;
- right: 10px;
+ bottom: var(--space-sm);
+ left: var(--space-sm);
+ right: var(--space-sm);
}
.search-results-dropdown {
@@ -75,58 +75,61 @@
top: 48px;
left: 0;
right: 0;
- z-index: 100;
- background: #221112;
- border-radius: 12px;
- box-shadow: 0 8px 32px rgba(0,0,0,0.18);
+ z-index: var(--z-dropdown);
+ background: var(--color-background-secondary);
+ border-radius: var(--radius-lg);
+ box-shadow: var(--shadow-xl);
max-height: 340px;
overflow-y: auto;
- padding: 8px 0;
- margin: 0 2rem;
+ padding: var(--space-sm) 0;
+ margin: 0 var(--space-xl);
+ border: 1px solid var(--color-border);
}
.search-fab {
position: fixed;
- top: 24px;
- right: 24px;
- z-index: 100;
- background: #1db954;
- color: #fff;
+ top: var(--space-lg);
+ right: var(--space-lg);
+ z-index: var(--z-fixed);
+ background: var(--color-primary);
+ color: var(--color-text-primary);
border: none;
- border-radius: 50%;
+ border-radius: var(--radius-full);
width: 56px;
height: 56px;
- font-size: 2rem;
+ font-size: var(--font-size-2xl);
display: flex;
align-items: center;
justify-content: center;
- box-shadow: 0 2px 8px rgba(0,0,0,0.15);
+ box-shadow: var(--shadow-lg);
cursor: pointer;
- transition: background 0.2s;
+ transition: all var(--transition-normal);
}
.search-fab:hover {
- background: #159943;
+ background: var(--color-primary-hover);
+ transform: scale(1.05);
}
.section-title {
- margin: 32px 0 16px 24px;
- font-size: 1.5rem;
- color: #fff;
+ margin: var(--space-xl) 0 var(--space-md) var(--space-lg);
+ font-size: var(--font-size-2xl);
+ color: var(--color-text-primary);
+ font-weight: var(--font-weight-bold);
}
.song-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
- gap: 24px;
- padding: 0 24px 24px 24px;
+ gap: var(--space-lg);
+ padding: 0 var(--space-lg) var(--space-lg) var(--space-lg);
}
/* Overlay styles */
.search-overlay {
position: fixed;
inset: 0;
- z-index: 200;
+ z-index: var(--z-modal);
display: flex;
align-items: center;
justify-content: center;
@@ -135,7 +138,7 @@
.search-overlay-home {
position: fixed;
inset: 0;
- z-index: 200;
+ z-index: var(--z-modal);
display: flex;
align-items: flex-start;
justify-content: center;
@@ -144,63 +147,68 @@
.search-overlay-backdrop {
position: absolute;
inset: 0;
- background: rgba(0,0,0,0.5);
- backdrop-filter: blur(8px);
+ background: rgba(0, 0, 0, 0.6);
+ backdrop-filter: blur(12px);
}
.search-overlay-modal {
position: relative;
- background: #181818;
- border-radius: 16px;
- padding: 32px 24px 24px 24px;
+ background: var(--color-background-secondary);
+ border-radius: var(--radius-xl);
+ padding: var(--space-xl) var(--space-lg) var(--space-lg) var(--space-lg);
min-width: 350px;
max-width: 90vw;
max-height: 80vh;
overflow-y: auto;
z-index: 1;
- box-shadow: 0 4px 32px rgba(0,0,0,0.4);
+ box-shadow: var(--shadow-2xl);
margin-top: 10vh;
+ border: 1px solid var(--color-border);
}
.search-overlay-input {
width: 100%;
- padding: 12px 16px;
- font-size: 1.1rem;
- border-radius: 8px;
- border: none;
- margin-bottom: 16px;
- background: #222;
- color: #fff;
+ padding: var(--space-md);
+ font-size: var(--font-size-lg);
+ border-radius: var(--radius-md);
+ border: 1px solid var(--color-border);
+ margin-bottom: var(--space-md);
+ background: var(--color-surface);
+ color: var(--color-text-primary);
+ transition: border-color var(--transition-normal);
}
-.no-results {
- color: #aaa;
- text-align: center;
- margin-top: 16px;
+.search-overlay-input:focus {
+ outline: none;
+ border-color: var(--color-primary);
}
-@media (max-width: 600px) {
- .search-results-dropdown {
- margin: 0 0.5rem;
- top: 44px;
- }
+.no-results {
+ color: var(--color-text-tertiary);
+ text-align: center;
+ margin-top: var(--space-md);
+ font-size: var(--font-size-base);
}
/* Responsive grid for tablets and small screens */
@media (max-width: 768px) {
.song-grid {
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
- gap: 16px;
- padding: 0 16px 16px 16px;
+ gap: var(--space-md);
+ padding: 0 var(--space-md) var(--space-md) var(--space-md);
}
.section-title {
- margin: 24px 0 12px 16px;
- font-size: 1.3rem;
+ margin: var(--space-lg) 0 var(--space-sm) var(--space-md);
+ font-size: var(--font-size-xl);
}
.section-wrapper {
- margin: 0 1rem;
+ margin: 0 var(--space-md);
+ }
+
+ .search-results-dropdown {
+ margin: 0 var(--space-md);
}
}
@@ -208,20 +216,31 @@
@media (max-width: 480px) {
.song-grid {
grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
- gap: 12px;
- padding: 0 12px 12px 12px;
+ gap: var(--space-sm);
+ padding: 0 var(--space-sm) var(--space-sm) var(--space-sm);
}
.section-title {
- margin: 20px 0 10px 12px;
- font-size: 1.2rem;
+ margin: var(--space-md) 0 var(--space-sm) var(--space-sm);
+ font-size: var(--font-size-lg);
}
.section-wrapper {
- margin: 0 0.5rem;
+ margin: 0 var(--space-sm);
}
.home-page {
- padding-bottom: 100px; /* More space for MiniPlayer on mobile */
+ padding-bottom: calc(var(--space-3xl) + var(--space-md)); /* More space for MiniPlayer on mobile */
+ }
+
+ .search-results-dropdown {
+ margin: 0 var(--space-sm);
+ top: 44px;
+ }
+
+ .search-overlay-modal {
+ min-width: 90vw;
+ padding: var(--space-lg) var(--space-md);
+ margin-top: var(--space-md);
}
}
diff --git a/frontend/src/pages/Library.css b/frontend/src/pages/Library.css
index 6a42b7d5..dc438743 100644
--- a/frontend/src/pages/Library.css
+++ b/frontend/src/pages/Library.css
@@ -1,11 +1,11 @@
/* Library.css - Modern, clean, Spotify-style library page */
.library-root {
min-height: 100vh;
- background: #221111;
+ background: var(--color-background);
display: flex;
flex-direction: column;
align-items: center;
- font-family: 'Work Sans', 'Noto Sans', sans-serif;
+ font-family: inherit;
}
.library-container {
@@ -15,53 +15,53 @@
flex: 1;
display: flex;
flex-direction: column;
- padding: 40px 0 0 0;
+ padding: var(--space-2xl) 0 0 0;
}
.library-header {
- padding: 0 24px 16px 24px;
+ padding: 0 var(--space-lg) var(--space-md) var(--space-lg);
}
.library-title {
- color: #fff;
- font-size: 2rem;
- font-weight: 700;
+ color: var(--color-text-primary);
+ font-size: var(--font-size-3xl);
+ font-weight: var(--font-weight-bold);
letter-spacing: -0.015em;
margin-bottom: 0;
}
.library-tabs {
display: flex;
- gap: 32px;
- border-bottom: 1.5px solid #653434;
- padding: 0 24px;
- margin-bottom: 8px;
+ gap: var(--space-xl);
+ border-bottom: 1px solid var(--color-border);
+ padding: 0 var(--space-lg);
+ margin-bottom: var(--space-sm);
}
.library-tab {
background: none;
border: none;
outline: none;
- color: #c89393;
- font-size: 1rem;
- font-weight: 700;
- padding: 18px 0 13px 0;
+ color: var(--color-text-secondary);
+ font-size: var(--font-size-base);
+ font-weight: var(--font-weight-bold);
+ padding: var(--space-lg) 0 var(--space-md) 0;
border-bottom: 3px solid transparent;
cursor: pointer;
- transition: color 0.2s, border-bottom 0.2s;
+ transition: all var(--transition-normal);
}
.library-tab.active {
- color: #fff;
- border-bottom: 3px solid #e51919;
+ color: var(--color-text-primary);
+ border-bottom: 3px solid var(--color-primary);
}
.library-search-row {
display: flex;
align-items: center;
gap: 0;
- padding: 16px 24px 0 24px;
- margin-bottom: 8px;
+ padding: var(--space-md) var(--space-lg) 0 var(--space-lg);
+ margin-bottom: var(--space-sm);
max-width: 400px;
width: 100%;
}
@@ -73,9 +73,9 @@
}
.library-search-icon {
- color: #c89393;
- background: #472424;
- border-radius: 8px 0 0 8px;
+ color: var(--color-text-secondary);
+ background: var(--color-surface);
+ border-radius: var(--radius-md) 0 0 var(--radius-md);
display: flex;
align-items: center;
justify-content: center;
@@ -85,21 +85,26 @@
.library-search-input {
flex: 1;
- background: #472424;
- border: none;
+ background: var(--color-surface);
+ border: 1px solid var(--color-border);
outline: none;
- color: #fff;
- font-size: 1rem;
- border-radius: 0 8px 8px 0;
+ color: var(--color-text-primary);
+ font-size: var(--font-size-base);
+ border-radius: 0 var(--radius-md) var(--radius-md) 0;
height: 40px;
- padding: 0 16px;
+ padding: 0 var(--space-md);
+ transition: border-color var(--transition-normal);
+}
+
+.library-search-input:focus {
+ border-color: var(--color-primary);
}
.library-list {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
- gap: 32px;
- padding: 32px 24px 0 24px;
+ gap: var(--space-xl);
+ padding: var(--space-xl) var(--space-lg) 0 var(--space-lg);
width: 100%;
}
@@ -107,36 +112,40 @@
display: flex;
align-items: stretch;
justify-content: space-between;
- gap: 24px;
- background: #2c1d1d;
- border-radius: 16px;
- padding: 24px;
- transition: background 0.2s;
+ gap: var(--space-lg);
+ background: var(--color-surface);
+ border-radius: var(--radius-xl);
+ padding: var(--space-lg);
+ transition: all var(--transition-normal);
+ border: 1px solid var(--color-border);
+ box-shadow: var(--shadow-sm);
}
.library-card:hover {
- background: #3b2323;
+ background: var(--color-surface-hover);
+ box-shadow: var(--shadow-md);
+ transform: translateY(-2px);
}
.library-card-info {
display: flex;
flex-direction: column;
- gap: 4px;
+ gap: var(--space-xs);
flex: 2 2 0px;
justify-content: center;
}
.library-card-title {
- color: #fff;
- font-size: 1.1rem;
- font-weight: 700;
- margin-bottom: 2px;
+ color: var(--color-text-primary);
+ font-size: var(--font-size-lg);
+ font-weight: var(--font-weight-bold);
+ margin-bottom: var(--space-xs);
}
.library-card-desc {
- color: #c89393;
- font-size: 0.95rem;
- font-weight: 400;
+ color: var(--color-text-secondary);
+ font-size: var(--font-size-sm);
+ font-weight: var(--font-weight-normal);
}
.library-card-img {
@@ -146,65 +155,98 @@
aspect-ratio: 16/9;
background-size: cover;
background-position: center;
- border-radius: 12px;
+ border-radius: var(--radius-lg);
}
.library-songs-list {
- padding: 24px;
+ padding: var(--space-lg);
display: flex;
flex-direction: column;
- gap: 16px;
+ gap: var(--space-md);
}
.library-back-btn {
background: none;
border: none;
- color: #e51919;
- font-size: 1rem;
- font-weight: 600;
- margin-bottom: 8px;
+ color: var(--color-primary);
+ font-size: var(--font-size-base);
+ font-weight: var(--font-weight-semibold);
+ margin-bottom: var(--space-sm);
cursor: pointer;
align-self: flex-start;
+ transition: color var(--transition-normal);
+}
+
+.library-back-btn:hover {
+ color: var(--color-primary-hover);
+}
+
+.library-songs-header {
+ margin-bottom: var(--space-lg);
}
.library-songs-title {
- color: #fff;
- font-size: 1.3rem;
- font-weight: 700;
- margin-bottom: 12px;
+ color: var(--color-text-primary);
+ font-size: var(--font-size-xl);
+ font-weight: var(--font-weight-bold);
+ margin-bottom: var(--space-xs);
+}
+
+.library-songs-subtitle {
+ color: var(--color-text-secondary);
+ font-size: var(--font-size-sm);
+ font-weight: var(--font-weight-medium);
+ display: flex;
+ align-items: center;
+}
+
+.liked-songs-header .library-songs-title {
+ color: var(--color-primary);
+ font-size: var(--font-size-2xl);
+ font-weight: var(--font-weight-bold);
+}
+
+.liked-songs-header .library-songs-subtitle {
+ color: var(--color-text-primary);
+ font-size: var(--font-size-base);
+ font-weight: var(--font-weight-medium);
}
.library-songs-cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
- gap: 18px;
- margin-top: 18px;
+ gap: var(--space-lg);
+ margin-top: var(--space-lg);
}
.library-song-card {
display: flex;
flex-direction: column;
align-items: center;
- gap: 10px;
- background: #2c1d1d;
- border-radius: 12px;
- padding: 18px 12px 16px 12px;
+ gap: var(--space-sm);
+ background: var(--color-surface);
+ border-radius: var(--radius-lg);
+ padding: var(--space-lg) var(--space-sm) var(--space-md) var(--space-sm);
margin-bottom: 0;
- transition: background 0.2s;
+ transition: all var(--transition-normal);
position: relative;
cursor: pointer;
+ border: 1px solid var(--color-border);
+ box-shadow: var(--shadow-sm);
}
.library-song-card:hover {
- background: #3b2323;
+ background: var(--color-surface-hover);
+ box-shadow: var(--shadow-md);
+ transform: translateY(-2px);
}
.library-song-cover {
width: 96px;
height: 96px;
- border-radius: 10px;
+ border-radius: var(--radius-md);
object-fit: cover;
- margin-bottom: 8px;
+ margin-bottom: var(--space-sm);
}
.library-song-info {
@@ -212,46 +254,57 @@
}
.library-song-title {
- color: #fff;
- font-size: 1.05rem;
- font-weight: 700;
+ color: var(--color-text-primary);
+ font-size: var(--font-size-lg);
+ font-weight: var(--font-weight-bold);
}
.library-song-artist {
- color: #c89393;
- font-size: 0.95rem;
+ color: var(--color-text-secondary);
+ font-size: var(--font-size-sm);
}
.library-song-play-btn {
- background: #e92932;
+ background: var(--color-primary);
border: none;
- border-radius: 50%;
+ border-radius: var(--radius-full);
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
- color: #fff;
- font-size: 1.2rem;
- margin-top: 8px;
+ color: var(--color-text-primary);
+ font-size: var(--font-size-lg);
+ margin-top: var(--space-sm);
cursor: pointer;
- transition: background 0.2s;
+ transition: all var(--transition-normal);
}
.library-song-play-btn:hover {
- background: #c81a1a;
+ background: var(--color-primary-hover);
+ transform: scale(1.05);
}
.library-empty {
- color: #c89393;
- font-size: 1rem;
- margin-top: 24px;
+ color: var(--color-text-secondary);
+ font-size: var(--font-size-base);
+ margin-top: var(--space-lg);
+ text-align: center;
+ padding: var(--space-2xl);
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ min-height: 200px;
+ background: var(--color-surface);
+ border-radius: var(--radius-xl);
+ border: 1px solid var(--color-border);
}
.search-overlay-home {
position: fixed;
inset: 0;
- z-index: 2000;
+ z-index: var(--z-modal);
display: flex;
align-items: flex-start;
justify-content: center;
@@ -260,32 +313,33 @@
.search-overlay-backdrop {
position: absolute;
inset: 0;
- background: rgba(34, 17, 17, 0.85);
- backdrop-filter: blur(18px);
+ background: rgba(0, 0, 0, 0.6);
+ backdrop-filter: blur(12px);
z-index: 0;
}
.search-overlay-modal {
position: relative;
- margin-top: 32px;
- background: rgba(40, 20, 20, 0.95);
- border-radius: 18px;
- box-shadow: 0 8px 32px rgba(0,0,0,0.25);
- padding: 32px 32px 24px 32px;
+ margin-top: var(--space-xl);
+ background: var(--color-background-secondary);
+ border-radius: var(--radius-xl);
+ box-shadow: var(--shadow-2xl);
+ padding: var(--space-xl) var(--space-xl) var(--space-lg) var(--space-xl);
z-index: 1;
min-width: 420px;
max-width: 98vw;
+ border: 1px solid var(--color-border);
}
@media (max-width: 900px) {
.library-container {
max-width: 100vw;
- padding: 24px 0 0 0;
+ padding: var(--space-lg) 0 0 0;
}
.library-list {
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
- gap: 20px;
- padding: 12px;
+ gap: var(--space-md);
+ padding: var(--space-sm);
}
.library-card-img {
min-width: 120px;
@@ -296,28 +350,28 @@
@media (max-width: 768px) {
.library-list {
grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
- gap: 16px;
- padding: 12px 16px;
+ gap: var(--space-md);
+ padding: var(--space-sm) var(--space-md);
}
}
@media (max-width: 600px) {
.library-container {
- padding: 12px 0 0 0;
+ padding: var(--space-sm) 0 0 0;
}
.library-header, .library-tabs, .library-search-row {
- padding-left: 8px;
- padding-right: 8px;
+ padding-left: var(--space-sm);
+ padding-right: var(--space-sm);
}
.library-list {
grid-template-columns: 1fr;
- gap: 12px;
- padding: 4px 12px;
+ gap: var(--space-sm);
+ padding: var(--space-xs) var(--space-sm);
}
.library-card {
flex-direction: column;
- gap: 12px;
- padding: 12px;
+ gap: var(--space-sm);
+ padding: var(--space-sm);
}
.library-card-img {
min-width: 100%;
@@ -326,7 +380,7 @@
}
.search-overlay-modal {
min-width: 90vw;
- padding: 18px 8px 12px 8px;
- margin-top: 12px;
+ padding: var(--space-lg) var(--space-sm) var(--space-sm) var(--space-sm);
+ margin-top: var(--space-sm);
}
}
\ No newline at end of file
diff --git a/frontend/src/pages/Library.jsx b/frontend/src/pages/Library.jsx
index 96a6f375..c74934d6 100644
--- a/frontend/src/pages/Library.jsx
+++ b/frontend/src/pages/Library.jsx
@@ -29,8 +29,15 @@ export default function Library({ showSearch, setShowSearch }) {
);
const allPlaylists = [
- { id: 'liked', name: 'Liked Songs', description: 'Your favorite tracks', image: '', songs: likedSongs },
- ...filteredPlaylists.map(p => ({ ...p, songs: [] }))
+ {
+ id: 'liked',
+ name: 'Liked Songs',
+ description: `${likedSongs.length} liked songs`,
+ image: '',
+ songs: likedSongs,
+ isLiked: true
+ },
+ ...filteredPlaylists.map(p => ({ ...p, songs: [], isLiked: false }))
];
const showSongs = selectedPlaylist !== null;
@@ -70,8 +77,36 @@ export default function Library({ showSearch, setShowSearch }) {
) : (
-
{currentPlaylist.name}
- {songsToShow.length === 0 &&
No songs found.
}
+
+
{currentPlaylist.name}
+
+ {currentPlaylist.isLiked ? (
+ <>
+
+ Your collection of favorite tracks
+ >
+ ) : (
+ `${songsToShow.length} songs`
+ )}
+
+
+ {songsToShow.length === 0 && (
+
+ {currentPlaylist.isLiked ? (
+ <>
+
+
No liked songs yet
+
Start liking songs to build your collection
+ >
+ ) : (
+ 'No songs found.'
+ )}
+
+ )}
{songsToShow.map(song => (
playSong(song, songsToShow)}>
diff --git a/frontend/src/pages/Login.css b/frontend/src/pages/Login.css
index 223ddb54..89820d70 100644
--- a/frontend/src/pages/Login.css
+++ b/frontend/src/pages/Login.css
@@ -1,9 +1,9 @@
/* Login.css */
body {
margin: 0;
- font-family: 'Inter', sans-serif;
- background-color: #1a0f0f;
- color: white;
+ font-family: inherit;
+ background-color: var(--color-background);
+ color: var(--color-text-primary);
}
.login-container {
@@ -13,56 +13,95 @@ body {
justify-content: center;
height: 100vh;
text-align: center;
- padding: 1rem;
+ padding: var(--space-md);
+ background: linear-gradient(135deg, var(--color-background) 0%, var(--color-background-secondary) 100%);
}
.logo {
- margin-bottom: 1.5rem;
+ margin-bottom: var(--space-lg);
+ transition: transform var(--transition-normal);
+}
+
+.logo:hover {
+ transform: scale(1.05);
}
.title {
- font-size: 2rem;
- font-weight: 700;
- color: #ff5f7e;
- margin: 0.5rem 0;
+ font-size: var(--font-size-3xl);
+ font-weight: var(--font-weight-bold);
+ color: var(--color-primary);
+ margin: var(--space-sm) 0;
+ letter-spacing: -0.02em;
}
.subtitle {
- font-size: 1.25rem;
- font-weight: 600;
- color: white;
- margin-bottom: 1rem;
+ font-size: var(--font-size-xl);
+ font-weight: var(--font-weight-semibold);
+ color: var(--color-text-primary);
+ margin-bottom: var(--space-md);
+ opacity: 0.9;
}
.terms {
- font-size: 0.875rem;
- color: #cbbcbc;
- margin-bottom: 2rem;
+ font-size: var(--font-size-sm);
+ color: var(--color-text-secondary);
+ margin-bottom: var(--space-xl);
+ max-width: 400px;
+ line-height: 1.5;
}
.terms span {
text-decoration: underline;
cursor: pointer;
+ color: var(--color-text-primary);
+ transition: color var(--transition-normal);
+}
+
+.terms span:hover {
+ color: var(--color-primary);
}
.google-btn {
- background-color: #e94149;
- color: white;
+ background-color: var(--color-primary);
+ color: var(--color-text-primary);
border: none;
- border-radius: 8px;
- padding: 0.75rem 1.5rem;
- font-weight: 600;
+ border-radius: var(--radius-md);
+ padding: var(--space-md) var(--space-lg);
+ font-weight: var(--font-weight-semibold);
+ font-size: var(--font-size-base);
cursor: pointer;
- transition: background-color 0.3s ease;
+ transition: all var(--transition-normal);
+ box-shadow: var(--shadow-md);
+ min-width: 200px;
}
.google-btn:hover {
- background-color: #c73b41;
+ background-color: var(--color-primary-hover);
+ transform: translateY(-2px);
+ box-shadow: var(--shadow-lg);
+}
+
+.google-btn:active {
+ transform: translateY(0);
+ box-shadow: var(--shadow-md);
}
footer {
position: absolute;
- bottom: 1rem;
- font-size: 0.75rem;
- color: #b8a8a8;
+ bottom: var(--space-md);
+ font-size: var(--font-size-xs);
+ color: var(--color-text-tertiary);
+ text-align: center;
+ max-width: 90%;
+}
+
+footer a {
+ color: var(--color-primary);
+ text-decoration: none;
+ transition: color var(--transition-normal);
+}
+
+footer a:hover {
+ color: var(--color-primary-hover);
+ text-decoration: underline;
}
diff --git a/frontend/src/pages/Login.jsx b/frontend/src/pages/Login.jsx
index d40ed44c..35eaad31 100644
--- a/frontend/src/pages/Login.jsx
+++ b/frontend/src/pages/Login.jsx
@@ -15,6 +15,16 @@ const Login = () => {
}
}, [currentUser, navigate]);
+ // For development: auto-login after a short delay
+ useEffect(() => {
+ const timer = setTimeout(() => {
+ if (!currentUser) {
+ navigate('/home', { replace: true });
+ }
+ }, 1000);
+ return () => clearTimeout(timer);
+ }, [currentUser, navigate]);
+
const handleGoogleLogin = () => {
signInWithPopup(auth, provider)
.then((result) => {
diff --git a/frontend/src/pages/Profile.css b/frontend/src/pages/Profile.css
index 5534d936..d281fbb5 100644
--- a/frontend/src/pages/Profile.css
+++ b/frontend/src/pages/Profile.css
@@ -1,18 +1,18 @@
/* Profile.css - Clean, modern profile page */
.profile-root {
min-height: 100vh;
- background: #221112;
+ background: var(--color-background);
display: flex;
flex-direction: column;
align-items: center;
- font-family: 'Work Sans', 'Noto Sans', sans-serif;
+ font-family: inherit;
}
.profile-container {
width: 100%;
max-width: 480px;
margin: 0 auto;
- padding: 40px 0 0 0;
+ padding: var(--space-2xl) 0 0 0;
display: flex;
flex-direction: column;
align-items: center;
@@ -22,65 +22,69 @@
display: flex;
flex-direction: column;
align-items: center;
- gap: 18px;
- margin-bottom: 32px;
+ gap: var(--space-lg);
+ margin-bottom: var(--space-xl);
}
.profile-avatar {
width: 128px;
height: 128px;
- border-radius: 50%;
+ border-radius: var(--radius-full);
background-size: cover;
background-position: center;
background-repeat: no-repeat;
- margin-bottom: 8px;
- border: 4px solid #472426;
+ margin-bottom: var(--space-sm);
+ border: 4px solid var(--color-border);
+ box-shadow: var(--shadow-lg);
}
.profile-info {
display: flex;
flex-direction: column;
align-items: center;
- gap: 2px;
+ gap: var(--space-xs);
}
.profile-name {
- color: #fff;
- font-size: 1.4rem;
- font-weight: 700;
+ color: var(--color-text-primary);
+ font-size: var(--font-size-xl);
+ font-weight: var(--font-weight-bold);
letter-spacing: -0.015em;
- margin-bottom: 2px;
+ margin-bottom: var(--space-xs);
}
.profile-email {
- color: #c89295;
- font-size: 1rem;
- font-weight: 400;
+ color: var(--color-text-secondary);
+ font-size: var(--font-size-base);
+ font-weight: var(--font-weight-normal);
}
.profile-logout {
- background: #472426;
- color: #fff;
- border: none;
- border-radius: 12px;
- padding: 10px 32px;
- font-size: 1rem;
- font-weight: 700;
- margin-top: 12px;
+ background: var(--color-surface);
+ color: var(--color-text-primary);
+ border: 1px solid var(--color-border);
+ border-radius: var(--radius-lg);
+ padding: var(--space-sm) var(--space-xl);
+ font-size: var(--font-size-base);
+ font-weight: var(--font-weight-bold);
+ margin-top: var(--space-sm);
cursor: pointer;
- transition: background 0.2s;
+ transition: all var(--transition-normal);
+ box-shadow: var(--shadow-sm);
}
.profile-logout:hover {
- background: #e51919;
+ background: var(--color-accent);
+ transform: translateY(-2px);
+ box-shadow: var(--shadow-md);
}
.profile-liked-title {
- color: #fff;
- font-size: 1.2rem;
- font-weight: 700;
- margin-bottom: 12px;
- margin-top: 12px;
+ color: var(--color-text-primary);
+ font-size: var(--font-size-lg);
+ font-weight: var(--font-weight-bold);
+ margin-bottom: var(--space-sm);
+ margin-top: var(--space-sm);
align-self: flex-start;
}
@@ -88,27 +92,31 @@
width: 100%;
display: flex;
flex-direction: column;
- gap: 12px;
+ gap: var(--space-sm);
}
.profile-liked-song {
display: flex;
align-items: center;
- gap: 16px;
- background: #2c1d1d;
- border-radius: 10px;
- padding: 12px 18px;
- transition: background 0.2s;
+ gap: var(--space-md);
+ background: var(--color-surface);
+ border-radius: var(--radius-md);
+ padding: var(--space-sm) var(--space-lg);
+ transition: all var(--transition-normal);
+ border: 1px solid var(--color-border);
+ box-shadow: var(--shadow-sm);
}
.profile-liked-song:hover {
- background: #3b2323;
+ background: var(--color-surface-hover);
+ transform: translateY(-2px);
+ box-shadow: var(--shadow-md);
}
.profile-liked-cover {
width: 56px;
height: 56px;
- border-radius: 8px;
+ border-radius: var(--radius-md);
background-size: cover;
background-position: center;
background-repeat: no-repeat;
@@ -120,21 +128,21 @@
}
.profile-liked-title-text {
- color: #fff;
- font-size: 1rem;
- font-weight: 600;
+ color: var(--color-text-primary);
+ font-size: var(--font-size-base);
+ font-weight: var(--font-weight-semibold);
}
.profile-liked-artist {
- color: #c89295;
- font-size: 0.95rem;
+ color: var(--color-text-secondary);
+ font-size: var(--font-size-sm);
}
@media (max-width: 600px) {
.profile-container {
- padding: 16px 0 0 0;
+ padding: var(--space-md) 0 0 0;
}
.profile-header {
- margin-bottom: 18px;
+ margin-bottom: var(--space-lg);
}
}
diff --git a/frontend/src/utils/api.js b/frontend/src/utils/api.js
index 599aabcb..ca3f4cd0 100644
--- a/frontend/src/utils/api.js
+++ b/frontend/src/utils/api.js
@@ -1,6 +1,6 @@
import { auth } from './firebaseConfig';
-const API_BASE = import.meta.env.VITE_BACKEND_API_URL || '';
+const API_BASE = import.meta.env.VITE_BACKEND_API_URL || 'http://localhost:8000';
async function getToken() {
const user = auth.currentUser;
diff --git a/frontend/src/utils/firebaseConfig.js b/frontend/src/utils/firebaseConfig.js
index 9f209c75..1d1813de 100644
--- a/frontend/src/utils/firebaseConfig.js
+++ b/frontend/src/utils/firebaseConfig.js
@@ -2,12 +2,12 @@ import { initializeApp } from 'firebase/app';
import { getAuth, GoogleAuthProvider } from 'firebase/auth';
const firebaseConfig = {
- apiKey: import.meta.env.VITE_FIREBASE_API_KEY,
- authDomain: import.meta.env.VITE_FIREBASE_AUTH_DOMAIN,
- projectId: import.meta.env.VITE_FIREBASE_PROJECT_ID,
- storageBucket: import.meta.env.VITE_FIREBASE_STORAGE_BUCKET,
- messagingSenderId: import.meta.env.VITE_FIREBASE_MESSAGING_SENDER_ID,
- appId: import.meta.env.VITE_FIREBASE_APP_ID,
+ apiKey: import.meta.env.VITE_FIREBASE_API_KEY || "demo-api-key",
+ authDomain: import.meta.env.VITE_FIREBASE_AUTH_DOMAIN || "demo-project.firebaseapp.com",
+ projectId: import.meta.env.VITE_FIREBASE_PROJECT_ID || "demo-project",
+ storageBucket: import.meta.env.VITE_FIREBASE_STORAGE_BUCKET || "demo-project.appspot.com",
+ messagingSenderId: import.meta.env.VITE_FIREBASE_MESSAGING_SENDER_ID || "123456789",
+ appId: import.meta.env.VITE_FIREBASE_APP_ID || "1:123456789:web:abcdef",
};
const app = initializeApp(firebaseConfig);
diff --git a/package-lock.json b/package-lock.json
new file mode 100644
index 00000000..a0a80ddc
--- /dev/null
+++ b/package-lock.json
@@ -0,0 +1,6 @@
+{
+ "name": "Streamify",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {}
+}