Initial commit: StackPilot Phase 1 (Core)
Self-hosted Docker Compose manager. - Backend: FastAPI + docker-py + SQLite (JWT auth, file-first stacks, lifecycle, live status, WebSocket logs, docker-run converter, audit log) - Frontend: React + Vite + Tailwind (login/setup, dashboard, stacks, stack detail, Monaco editor, dark/light theme) - Deployment: docker-compose.yml, Dockerfiles, nginx reverse proxy Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
import { useEffect } from "react";
|
||||
import { BrowserRouter, Navigate, Outlet, Route, Routes } from "react-router-dom";
|
||||
import { Layout } from "@/components/layout/Layout";
|
||||
import { Login } from "@/pages/Login";
|
||||
import { Dashboard } from "@/pages/Dashboard";
|
||||
import { Stacks } from "@/pages/Stacks";
|
||||
import { StackDetail } from "@/pages/StackDetail";
|
||||
import { StackEditor } from "@/pages/StackEditor";
|
||||
import { Networks, Images, Templates, Settings } from "@/pages/Placeholder";
|
||||
import { useAuthStore } from "@/store/auth";
|
||||
import { useThemeStore } from "@/store/theme";
|
||||
|
||||
function RequireAuth() {
|
||||
const token = useAuthStore((s) => s.accessToken);
|
||||
return token ? <Outlet /> : <Navigate to="/login" replace />;
|
||||
}
|
||||
|
||||
export default function App() {
|
||||
const applyTheme = useThemeStore((s) => s.apply);
|
||||
const fetchMe = useAuthStore((s) => s.fetchMe);
|
||||
const token = useAuthStore((s) => s.accessToken);
|
||||
|
||||
useEffect(() => {
|
||||
applyTheme();
|
||||
}, [applyTheme]);
|
||||
|
||||
useEffect(() => {
|
||||
if (token) fetchMe().catch(() => {});
|
||||
}, [token, fetchMe]);
|
||||
|
||||
return (
|
||||
<BrowserRouter>
|
||||
<Routes>
|
||||
<Route path="/login" element={<Login />} />
|
||||
<Route element={<RequireAuth />}>
|
||||
<Route element={<Layout />}>
|
||||
<Route path="/" element={<Dashboard />} />
|
||||
<Route path="/stacks" element={<Stacks />} />
|
||||
<Route path="/stacks/new" element={<StackEditor />} />
|
||||
<Route path="/stacks/:id" element={<StackDetail />} />
|
||||
<Route path="/stacks/:id/edit" element={<StackEditor />} />
|
||||
<Route path="/networks" element={<Networks />} />
|
||||
<Route path="/images" element={<Images />} />
|
||||
<Route path="/templates" element={<Templates />} />
|
||||
<Route path="/settings" element={<Settings />} />
|
||||
</Route>
|
||||
</Route>
|
||||
<Route path="*" element={<Navigate to="/" replace />} />
|
||||
</Routes>
|
||||
</BrowserRouter>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user