main
md 134 lines 3.73 KB
Rendered Raw
1 # Relay Server Frontend
2
3 React + TypeScript frontend for relay server discovery and onboarding.
4
5 ## Tech Stack
6
7 - React 19
8 - TypeScript
9 - Vite 7
10 - Tailwind CSS 4
11 - shadcn/ui (Radix-based)
12 - Lucide React
13 - @ssgoi/react
14 - React Compiler (`babel-plugin-react-compiler`, enabled in `vite.config.ts`)
15
16 ## Core Behavior
17
18 The Go relay is API-only. This frontend is a standalone Vite app that talks to
19 the relay over the JSON API and does not receive server-side injected lease
20 data.
21
22 - Public presentation state is loaded from `/ui/state`.
23 - Operator presentation policy state is loaded from `/ui/policy/state`.
24 - All JSON API responses use the `{ ok, data?, error? }` envelope parsed by `src/lib/apiClient.ts`.
25 - `VITE_PORTAL_API_BASE_URL` points the frontend at the public edge origin or deployment base path, not at `/api`; `/api`, `/ui`, `/sdk`, and `/discovery` are sibling paths. Admin auth uses a bearer token returned by `/api/admin/auth/login`.
26
27 ## Project Structure
28
29 ```text
30 frontend/
31 src/
32 components/
33 hooks/
34 useServerList.ts
35 useAdmin.ts
36 useList.ts
37 useAuth.ts
38 lib/
39 apiClient.ts
40 apiPaths.ts
41 metadata.ts
42 pages/
43 Admin.tsx
44 ServerDetail.tsx
45 ServerList.tsx
46 types/
47 api.ts
48 App.tsx
49 main.tsx
50 index.css
51 api/
52 server.ts
53 index.html
54 package.json
55 tsconfig.json
56 tsconfig.api.json
57 vite.config.ts
58 ```
59
60 ## Install and Build
61
62 ```bash
63 cd frontend
64 npm install
65 npm run build
66 ```
67
68 Build output goes to `frontend/dist/`.
69
70 ## Development
71
72 ```bash
73 cd frontend
74 npm run dev
75 ```
76
77 Default dev URL: `http://localhost:5173`.
78
79 To run against another origin, build or run the frontend with the public edge origin:
80
81 ```bash
82 VITE_PORTAL_API_BASE_URL=https://portal.example.com npm run dev
83 ```
84
85 ## Docker
86
87 The frontend Docker image serves the built Vite app with nginx over HTTP. It
88 does not own API path routing; the public edge nginx routes relay-owned paths to
89 `portal:4017` and `/ui/*` presentation paths to `portal-api:8081`.
90 TLS for public domains should live in the outer reverse proxy. The app uses
91 same-origin relative API paths, so it does not need runtime config file
92 generation.
93
94 ```bash
95 docker compose up -d portal-frontend
96 ```
97
98 ## NPM Scripts
99
100 | Script | Purpose |
101 | --- | --- |
102 | `npm run dev` | Start the Vite development server. |
103 | `npm run build` | Type-check and build production assets. |
104 | `npm run build:api` | Build the TypeScript API service. |
105 | `npm run lint` | Run ESLint. |
106 | `npm run typecheck` | Run TypeScript checking. |
107 | `npm test` | Run Vitest. |
108 | `npm run preview` | Preview the production bundle. |
109
110 ## Relay Integration
111
112 Relay server exposes:
113
114 - `/` - relay API identity response
115 - `/api/state` - public leases
116 - `/api/install.sh` and `/api/install.ps1` - CLI installers
117 - `/api/admin/auth/*` - admin token auth endpoints
118 - `/api/policy/*` - relay policy endpoints
119 - `/sdk/*` - SDK/control endpoints
120 - `/discovery` - relay discovery when enabled
121
122 The TypeScript API service composes frontend-owned presentation
123 state on top of relay data under the `/ui/` prefix:
124
125 - `/ui/state` - relay leases plus `landing_page_enabled`
126 - `/ui/policy/*` - relay policy, with `landing_page_enabled` composed into `/ui/policy` and `/ui/policy/state`
127 - `/ui/service/status` - hostname and service readiness derived from relay `/api/state`
128 - `/ui/thumbnail/{hostname}` - generated screenshots, disabled when `HEADLESS_SHELL_URL` is empty
129
130 ## Notes
131
132 - Relay path constants are owned by Go (`types/paths.go`) and mirrored in `src/lib/apiPaths.ts` for browser calls; presentation paths live under `/ui/` in `api/server.ts`, the edge nginx config, and `src/lib/apiPaths.ts`.
133 - Frontend API wire types live in `src/types/api.ts`.
134 - Radix Select values cannot be empty strings. Use stable values such as `"all"` and `"default"`.