From bc4cfe607d972e6ee85acfba9a73e19cb0141a15 Mon Sep 17 00:00:00 2001 From: Decobus Date: Sat, 26 Jul 2025 00:19:16 -0400 Subject: [PATCH] Add API key authentication for external access MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Create API key context for managing authentication state - Add dedicated settings page for API key management - Move performance metrics to dedicated page in navigation - Update middleware to support URL parameter fallback - Enhance UI with proper glass morphism styling - Add Solarized color utilities to CSS - Improve spacing and padding throughout UI components - Remove manual bullet points from list items 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- app/globals.css | 60 ++++++++++- app/layout.tsx | 19 ++-- app/performance/page.tsx | 125 ++++++++++++++++++++++ app/settings/page.tsx | 158 ++++++++++++++++++++++++++++ components/ApiKeyPrompt.tsx | 152 ++++++++++++++++++++++++++ components/Header.tsx | 18 ++++ components/PerformanceDashboard.tsx | 68 ++++++------ contexts/ApiKeyContext.tsx | 57 ++++++++++ lib/apiClient.ts | 7 +- middleware.ts | 4 +- 10 files changed, 620 insertions(+), 48 deletions(-) create mode 100644 app/performance/page.tsx create mode 100644 app/settings/page.tsx create mode 100644 components/ApiKeyPrompt.tsx create mode 100644 contexts/ApiKeyContext.tsx diff --git a/app/globals.css b/app/globals.css index ae33ffe..dac679e 100644 --- a/app/globals.css +++ b/app/globals.css @@ -73,7 +73,8 @@ body { } /* Glass Card Component */ -.glass { +.glass, +.glass-panel { background: rgba(7, 54, 66, 0.4); backdrop-filter: blur(10px); border: 1px solid rgba(88, 110, 117, 0.3); @@ -489,4 +490,59 @@ body { background: rgba(7, 54, 66, 0.2); border: 1px solid rgba(88, 110, 117, 0.2); border-radius: 12px; -} \ No newline at end of file +} + +/* Solarized Color Utilities */ +.text-base03 { color: var(--solarized-base03); } +.text-base02 { color: var(--solarized-base02); } +.text-base01 { color: var(--solarized-base01); } +.text-base00 { color: var(--solarized-base00); } +.text-base0 { color: var(--solarized-base0); } +.text-base1 { color: var(--solarized-base1); } +.text-base2 { color: var(--solarized-base2); } +.text-base3 { color: var(--solarized-base3); } +.text-blue { color: var(--solarized-blue); } +.text-cyan { color: var(--solarized-cyan); } +.text-green { color: var(--solarized-green); } +.text-yellow { color: var(--solarized-yellow); } +.text-orange { color: var(--solarized-orange); } +.text-red { color: var(--solarized-red); } +.text-magenta { color: var(--solarized-magenta); } +.text-violet { color: var(--solarized-violet); } + +.bg-base03 { background-color: var(--solarized-base03); } +.bg-base02 { background-color: var(--solarized-base02); } +.bg-base01 { background-color: var(--solarized-base01); } +.bg-base00 { background-color: var(--solarized-base00); } +.bg-base0 { background-color: var(--solarized-base0); } +.bg-base1 { background-color: var(--solarized-base1); } +.bg-base2 { background-color: var(--solarized-base2); } +.bg-base3 { background-color: var(--solarized-base3); } +.bg-blue { background-color: var(--solarized-blue); } +.bg-cyan { background-color: var(--solarized-cyan); } +.bg-green { background-color: var(--solarized-green); } +.bg-yellow { background-color: var(--solarized-yellow); } +.bg-orange { background-color: var(--solarized-orange); } +.bg-red { background-color: var(--solarized-red); } +.bg-magenta { background-color: var(--solarized-magenta); } +.bg-violet { background-color: var(--solarized-violet); } + +.border-base01 { border-color: var(--solarized-base01); } +.border-base02 { border-color: var(--solarized-base02); } +.border-blue { border-color: var(--solarized-blue); } +.border-cyan { border-color: var(--solarized-cyan); } +.border-green { border-color: var(--solarized-green); } +.border-yellow { border-color: var(--solarized-yellow); } +.border-orange { border-color: var(--solarized-orange); } +.border-red { border-color: var(--solarized-red); } + +/* Border opacity utilities */ +.border-green\/30 { border-color: rgba(133, 153, 0, 0.3); } +.border-yellow\/30 { border-color: rgba(181, 137, 0, 0.3); } +.border-blue\/30 { border-color: rgba(38, 139, 210, 0.3); } +.border-red\/30 { border-color: rgba(220, 50, 47, 0.3); } + +/* Focus utilities */ +.focus\:outline-none:focus { outline: none; } +.focus\:ring-2:focus { box-shadow: 0 0 0 2px var(--solarized-blue); } +.focus\:ring-blue:focus { box-shadow: 0 0 0 2px var(--solarized-blue); } \ No newline at end of file diff --git a/app/layout.tsx b/app/layout.tsx index c3ab1bc..4b3dbbc 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -2,7 +2,7 @@ import './globals.css'; import Header from '@/components/Header'; import Footer from '@/components/Footer'; import { ErrorBoundary } from '@/components/ErrorBoundary'; -import PerformanceDashboard from '@/components/PerformanceDashboard'; +import { ApiKeyProvider } from '@/contexts/ApiKeyContext'; export const metadata = { title: 'Live Stream Manager', @@ -13,14 +13,15 @@ export default function RootLayout({ children }: { children: React.ReactNode }) return ( -
-
- - {children} - -
-