package ui import ( "net/http" "path/filepath" ) // Handler serves the workspace launcher UI. type Handler struct { appDir string } // NewHandler creates a UI handler that serves the launcher and static assets. func NewHandler(appDir string) *Handler { return &Handler{ appDir: appDir, } } // RegisterRoutes mounts the public UI routes on the given mux. func (h *Handler) RegisterRoutes(mux *http.ServeMux, authGate func(http.Handler) http.Handler) { // Static assets (manifest.json, sw.js, icons) staticDir := filepath.Join(h.appDir, "static") staticHandler := http.FileServer(http.Dir(staticDir)) mux.Handle("GET /static/", http.StripPrefix("/static", staticHandler)) // Launcher page — protected by OIDC auth gate mux.Handle("GET /", authGate(http.HandlerFunc(h.launcherPage))) } // launcherPage renders the main workspace landing page. func (h *Handler) launcherPage(w http.ResponseWriter, r *http.Request) { // Only handle root path, not all paths if r.URL.Path != "/" { http.NotFound(w, r) return } // Get user info from session (set by auth middleware) // For now, render without user name (OIDC provides this later) userName := "" apps := DefaultApps() component := LauncherPage(userName, apps) component.Render(r.Context(), w) }