diff --git a/backend/app/main.py b/backend/app/main.py index e64ac93..4bbb0c2 100644 --- a/backend/app/main.py +++ b/backend/app/main.py @@ -62,11 +62,16 @@ app = FastAPI( lifespan=lifespan ) -# Configure CORS +# Configure CORS. The frontend normally talks to the backend through the +# nginx (prod) or vite (dev) proxy, so requests are same-origin and never +# trip CORS. The wildcard here is a fallback for the rare case where a +# user / script hits the backend directly from a browser at some other +# origin (LAN IP, reverse proxy under a different host, etc.). This is a +# single-user homelab tool, so a permissive CORS policy is fine. app.add_middleware( CORSMiddleware, - allow_origins=["http://localhost:3000", "http://localhost:5173"], # Frontend URLs - allow_credentials=True, + allow_origins=["*"], + allow_credentials=False, allow_methods=["*"], allow_headers=["*"], ) diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 5c9b54a..29900fb 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -53,9 +53,6 @@ function App() { return (
- - -
{/* Left Sidebar */} @@ -67,9 +64,15 @@ function App() {
- {/* Main Content - Timeline */} -
- + {/* Main column — filter bar, discard bar, timeline. Lives to the + * right of the left sidebar so the filter row doesn't bleed + * across the sidebar. */} +
+ + +
+ +
{/* Right Sidebar */} @@ -82,6 +85,10 @@ function App() {
+ {/* Floating keyboard hints — pinned bottom-center, glassy. Sits + * above the timeline and below the toast layer. */} + + {/* Scan Progress Indicator */} diff --git a/frontend/src/components/KeyboardHints.tsx b/frontend/src/components/KeyboardHints.tsx index 2dbe667..e011ca0 100644 --- a/frontend/src/components/KeyboardHints.tsx +++ b/frontend/src/components/KeyboardHints.tsx @@ -25,22 +25,22 @@ export function KeyboardHints() { ] return ( -
-
+
+
{hints.map((hint, i) => (
- + {hint.key} {hint.action} {i < hints.length - 1 && ( - + )}
))} {selectedCount > 0 && ( <> - + {selectedCount} selected diff --git a/frontend/src/components/filter/FilterBar.tsx b/frontend/src/components/filter/FilterBar.tsx index ce6c4c1..d719892 100644 --- a/frontend/src/components/filter/FilterBar.tsx +++ b/frontend/src/components/filter/FilterBar.tsx @@ -93,7 +93,7 @@ export function FilterBar() { const anyActive = hasActiveFilters(filterState) return ( -
+
{/* Date */} Clear all diff --git a/frontend/src/services/api.ts b/frontend/src/services/api.ts index d9d8464..75d6afa 100644 --- a/frontend/src/services/api.ts +++ b/frontend/src/services/api.ts @@ -1,6 +1,11 @@ import axios from 'axios' -const API_BASE_URL = 'http://localhost:8001/api/v1' +// Relative API base. In production the nginx in front of the SPA proxies +// /api/ to the backend container; in dev the vite server has the same +// proxy in vite.config.ts. Using a relative URL means requests are +// always same-origin, so the app works whether you hit it from +// localhost, a LAN IP, or a reverse proxy without any CORS dance. +const API_BASE_URL = '/api/v1' const api = axios.create({ baseURL: API_BASE_URL,