From d429b2d2528ba82d01308169628a1f116d7570fc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Br=C3=BCckner?=
Date: Mon, 8 Jun 2026 14:08:57 +0200
Subject: [PATCH] refactor(caddy): flatten routes to a plain array like
bookings
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
GET /api/caddy/routes now returns the route array directly instead of
{ system, custom }. Frontend state is CaddyRoute[] initialised to [],
rendered with a simple .map() and an empty-state message — mirroring how
bookings are loaded and displayed.
---
server.ts | 2 +-
src/components/Settings.tsx | 22 +++++++++++++---------
2 files changed, 14 insertions(+), 10 deletions(-)
diff --git a/server.ts b/server.ts
index 1e9a9ea..fffbf9b 100644
--- a/server.ts
+++ b/server.ts
@@ -1180,7 +1180,7 @@ async function startServer() {
app.get('/api/caddy/routes', requireAuth, (_req, res) => {
try {
- res.json({ system: [], custom: getCaddyRoutes() });
+ res.json(getCaddyRoutes());
} catch (err: any) {
res.status(500).json({ error: err.message });
}
diff --git a/src/components/Settings.tsx b/src/components/Settings.tsx
index 4aa9b5c..d26ee85 100644
--- a/src/components/Settings.tsx
+++ b/src/components/Settings.tsx
@@ -193,7 +193,7 @@ export default function Settings({ currentUser: _currentUser }: SettingsProps) {
const [caddyEnabled, setCaddyEnabled] = useState(false);
const [caddyAdminUrl, setCaddyAdminUrl] = useState('http://localhost:2019');
const [caddyStatus, setCaddyStatus] = useState<'unknown' | 'available' | 'unavailable'>('unknown');
- const [caddyRoutes, setCaddyRoutes] = useState<{ system: { hostname: string; upstream: string }[]; custom: CaddyRoute[] } | null>(null);
+ const [caddyRoutes, setCaddyRoutes] = useState([]);
const [addingRoute, setAddingRoute] = useState(false);
const [newHostname, setNewHostname] = useState('');
const [newUpstream, setNewUpstream] = useState('');
@@ -360,17 +360,15 @@ export default function Settings({ currentUser: _currentUser }: SettingsProps) {
}
async function loadCaddyRoutes() {
- // Status check is background — never blocks route display
- authFetch('/api/caddy/status')
- .then(res => res.ok ? res.json() : null)
- .then(s => setCaddyStatus(s?.available ? 'available' : 'unavailable'))
- .catch(() => setCaddyStatus('unavailable'));
-
- // Routes load immediately from DB
try {
const res = await authFetch('/api/caddy/routes');
if (res.ok) setCaddyRoutes(await res.json());
} catch {}
+ // Status check runs separately — purely informational, never blocks the list
+ authFetch('/api/caddy/status')
+ .then(res => res.ok ? res.json() : null)
+ .then(s => setCaddyStatus(s?.available ? 'available' : 'unavailable'))
+ .catch(() => setCaddyStatus('unavailable'));
}
async function handleAddRoute() {
@@ -939,8 +937,14 @@ export default function Settings({ currentUser: _currentUser }: SettingsProps) {
)}
+ {caddyRoutes.length === 0 && (
+
+ No proxy routes configured yet.
+
+ )}
+
{/* Custom routes */}
- {caddyRoutes?.custom.map(r => (
+ {caddyRoutes.map((r: CaddyRoute) => (
{editingRouteId === r.id ? (