osctrl frontend

June 11, 2026 ยท View on GitHub

React + TypeScript + Vite SPA for the osctrl admin UI.

Talks exclusively to osctrl-api (port 8081 by default). Served as static files โ€” no Node.js server in production.

Important

The frontend is the primary operator UI going forward. The legacy server-rendered osctrl-admin HTML interface is being kept for transition purposes and will be deprecated.

๐Ÿค” What is the frontend?

The osctrl frontend is the modern operator UI for managing environments, nodes, queries, carves, tags, users, and settings through osctrl-api.

๐Ÿš€ Why it exists

The frontend is where new operator-facing UX improvements are landing. It replaces the legacy server-rendered osctrl-admin experience with a React SPA that talks directly to the API layer.

๐Ÿ—‚ Directory

frontend/
โ”œโ”€โ”€ src/
โ”‚   โ”œโ”€โ”€ main.tsx          React 19 entry point
โ”‚   โ”œโ”€โ”€ router.tsx        TanStack Router instance
โ”‚   โ”œโ”€โ”€ routes/           Page components (TanStack Router)
โ”‚   โ”œโ”€โ”€ components/       Reusable UI components (primitives, atoms, data, chrome, forms, feedback)
โ”‚   โ”œโ”€โ”€ features/         Feature modules (one folder per page: nodes, queries, carves, ...)
โ”‚   โ”œโ”€โ”€ api/              Typed API client + generated types
โ”‚   โ”œโ”€โ”€ lib/              Utilities, custom hooks, time formatting
โ”‚   โ””โ”€โ”€ styles/           Tailwind base + design token CSS
โ””โ”€โ”€ tests/
    โ””โ”€โ”€ e2e/              Playwright end-to-end tests

๐Ÿงฐ npm scripts

ScriptDescription
npm run devStart Vite dev server on port 5173, proxying /api to :8081
npm run buildType-check then produce dist/
npm run previewPreview the production build locally
npm run checkRun tsc --noEmit (type-check only)
npm run lintAlias for check (linting config added in a later track)
npm testRun Vitest once
npm run test:watchRun Vitest in watch mode
npm run test:e2eRun Playwright e2e tests

๐Ÿ›  Development

๐Ÿ’ป Local frontend workflow

# Terminal 1 โ€” osctrl API (Go)
make api-dev   # starts osctrl-api on :8081

# Terminal 2 โ€” React SPA
cd frontend
npm run dev    # starts Vite on :5173, proxies /api/* to :8081

Open http://localhost:5173 in the browser. Vite's dev proxy forwards all /api/* requests to the running Go API, so auth cookies work as same-origin.

๐Ÿณ Docker dev stack

The repository's docker-compose-dev.yml exposes the frontend through osctrl-nginx at:

  • https://localhost:8444 for the frontend SPA
  • https://localhost:8443 for the legacy osctrl-admin HTML interface

In that setup, osctrl-frontend stays internal-only on the Docker network and osctrl-nginx performs TLS termination before proxying requests to it.

๐Ÿ— Production build

make frontend    # runs npm ci + npm run build in frontend/

Output: frontend/dist/. Deploy options:

  1. nginx โ€” serve dist/ as the document root, reverse-proxy /api/* to osctrl-api. See deploy/nginx/frontend.conf.example.
  2. Static hosting + CDN โ€” upload dist/ to S3/Cloudfront/etc. Configure CORS on the API.
  3. Docker โ€” build the multi-stage image at deploy/docker/dockerfiles/Dockerfile-osctrl-frontend (node:22-alpine โ†’ nginx:alpine). Single image, no separate Go binary.

โš™๏ธ Tech stack

  • React 19 + TypeScript 5 (strict)
  • Vite 7
  • TanStack Router (typed routing)
  • TanStack Query 5 (server state)
  • TanStack Table 8 (headless table)
  • Tailwind CSS v4 via @tailwindcss/vite
  • Radix UI primitives (ร  la carte)
  • react-hook-form 7 + zod 3
  • Vitest + @testing-library/react + jsdom
  • Playwright (e2e)