From 3fff72cf777129ef654a6d3710844451e2ea601d Mon Sep 17 00:00:00 2001 From: Zsolt Tasnadi Date: Wed, 18 Mar 2026 00:55:02 +0100 Subject: [PATCH] embedded youtube --- apps/frontend/src/pages/index.astro | 200 +++++++++++++++++++++++++++- docker-compose.yaml | 2 + 2 files changed, 201 insertions(+), 1 deletion(-) diff --git a/apps/frontend/src/pages/index.astro b/apps/frontend/src/pages/index.astro index edea944..9fb3425 100644 --- a/apps/frontend/src/pages/index.astro +++ b/apps/frontend/src/pages/index.astro @@ -77,6 +77,10 @@ try { } catch (e) { console.error('Failed to fetch highlighted software:', e); } + +// YouTube Config from Env +const YOUTUBE_API_KEY = import.meta.env.YOUTUBE_API_KEY; +const YOUTUBE_CHANNEL_ID = import.meta.env.YOUTUBE_CHANNEL_ID; --- @@ -163,6 +167,43 @@ try { )} + +
+
+
+
+ Latest Video +
+
+ +
+
+
+
+
Loading video...
+
+
+ + +
+
+
+
@@ -359,6 +400,80 @@ try { .nav-card-desc { @apply text-gray-600 mb-6 flex-grow leading-relaxed; } + + /* YouTube Widget */ + .youtube-widget-container { + --yt-accent: #ff0000; + --bg-card: #181818; + --bg-meta: #1f1f1f; + --text-primary: #f1f1f1; + --text-secondary: #aaaaaa; + --border: rgba(255,255,255,0.08); + --radius: 12px; + @apply w-full max-w-4xl mx-auto; + } + + .youtube-widget-container .widget-header { + @apply flex items-center gap-2.5 mb-5; + } + .youtube-widget-container .yt-icon { + @apply w-7 h-5 bg-[#ff0000] rounded-[5px] flex items-center justify-center flex-shrink-0; + } + .youtube-widget-container .yt-icon::after { + content: ''; + @apply border-l-[10px] border-l-white border-t-[6px] border-t-transparent border-b-[6px] border-b-transparent ml-0.5; + } + .youtube-widget-container .widget-label { + @apply text-[11px] font-semibold tracking-[0.12em] uppercase text-gray-500; + } + .youtube-widget-container .live-dot { + @apply w-[7px] h-[7px] rounded-full bg-[#ff0000] ml-auto animate-pulse; + } + + .youtube-widget-container .yt-card { + background: var(--bg-card); + border: 1px solid var(--border); + border-radius: var(--radius); + @apply overflow-hidden shadow-xl; + } + + .youtube-widget-container .player-wrap { + @apply relative w-full aspect-video bg-black; + } + .youtube-widget-container .player-wrap :global(iframe) { + @apply w-full h-full border-none block; + } + + .youtube-widget-container .state-overlay { + @apply absolute inset-0 flex flex-col items-center justify-center gap-4 bg-black; + } + .youtube-widget-container .state-overlay :global(.spinner) { + @apply w-9 h-9 border-4 border-white/10 border-t-[#ff0000] rounded-full animate-spin; + } + .youtube-widget-container .state-text { + @apply text-[13px] text-[#aaaaaa] text-center px-6; + } + + .youtube-widget-container .meta { + padding: 1.1rem 1.25rem; + background: var(--bg-meta); + border-top: 1px solid var(--border); + } + .youtube-widget-container .video-title { + @apply text-[15px] font-semibold leading-[1.4] text-[#f1f1f1] mb-1.5 truncate; + } + .youtube-widget-container .meta-row { + @apply flex items-center gap-3 flex-wrap; + } + .youtube-widget-container .meta-chip { + @apply text-[12px] text-[#aaaaaa] flex items-center gap-1; + } + .youtube-widget-container .new-badge { + @apply text-[10px] font-bold tracking-[0.08em] bg-[#ff0000] text-white px-1.5 py-0.5 rounded uppercase; + } + .youtube-widget-container .yt-link { + @apply ml-auto text-[12px] text-[#ff0000] no-underline font-medium opacity-85 transition-opacity hover:opacity-100; + } diff --git a/docker-compose.yaml b/docker-compose.yaml index 8bf79af..556080c 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -122,6 +122,8 @@ services: - WEBAPP_GITEA_TOKEN=${WEBAPP_GITEA_TOKEN} - WEBAPP_WIKIJS_TOKEN=${WEBAPP_WIKIJS_TOKEN} - DISCORD_INVITE_LINK=${DISCORD_INVITE_LINK} + - YOUTUBE_API_KEY=${YOUTUBE_API_KEY} + - YOUTUBE_CHANNEL_ID=${YOUTUBE_CHANNEL_ID} volumes: - ./apps/frontend:/app - /app/node_modules