CI / Test (linux/amd64) (push) Waiting to run
CI / Lint (push) Waiting to run
CI / Cross-build (darwin/amd64) (push) Waiting to run
CI / Cross-build (linux/amd64) (push) Waiting to run
CI / Cross-build (darwin/arm64) (push) Waiting to run
CI / Cross-build (linux/arm64) (push) Waiting to run
135 lines
4.3 KiB
Markdown
135 lines
4.3 KiB
Markdown
# urapt-web
|
|
|
|
The web UI for [urapt](https://github.com/owenqwenstarsky/urapt), a self-hostable
|
|
APT repository server. A React single-page app that talks to a urapt-server's
|
|
REST API (`/api/v1`) to manage repositories, members, distributions, packages,
|
|
tokens, and users — full management parity with the `urapt` CLI.
|
|
|
|
## Stack
|
|
|
|
- **Vite** + **React 18** + **TypeScript**
|
|
- **Tailwind CSS** + **shadcn/ui** (New York, neutral)
|
|
- **React Router v7**, **TanStack Query v5**, **Zustand**, **Vitest**
|
|
|
|
## Requirements
|
|
|
|
- Node.js 20+ (see `.nvmrc`) and pnpm 10+
|
|
|
|
## Development
|
|
|
|
Start a local urapt-server (from the repo root):
|
|
|
|
```bash
|
|
make run-server # listens on 0.0.0.0:8080
|
|
```
|
|
|
|
Then in `urapt-web/`:
|
|
|
|
```bash
|
|
pnpm install
|
|
pnpm dev # http://localhost:5173
|
|
```
|
|
|
|
Vite proxies `/api` and `/apt` to `http://localhost:8080` (override with the
|
|
`URAPT_SERVER` env var), so the UI is same-origin with the API in dev — no CORS
|
|
needed. If `needs_setup` is true (no users yet), you'll be sent to the first-run
|
|
setup screen to create the admin account.
|
|
|
|
## Scripts
|
|
|
|
| Script | Description |
|
|
| ---------------- | ------------------------------------ |
|
|
| `pnpm dev` | Start the Vite dev server |
|
|
| `pnpm build` | Type-check and build to `dist/` |
|
|
| `pnpm preview` | Preview the production build locally |
|
|
| `pnpm typecheck` | Run `tsc` with no emit |
|
|
| `pnpm lint` | Run ESLint |
|
|
| `pnpm format` | Run Prettier (write) |
|
|
| `pnpm test` | Run Vitest once |
|
|
|
|
## Configuration
|
|
|
|
| Env var | Default | Notes |
|
|
| ------------------- | ----------------------- | -------------------------------------------------------------------------------- |
|
|
| `VITE_API_BASE_URL` | `/api/v1` | REST API base. Override only for cross-origin dev (requires CORS on the server). |
|
|
| `URAPT_SERVER` | `http://localhost:8080` | Dev proxy target only. |
|
|
|
|
## Deployment (same-origin)
|
|
|
|
The UI is designed to be served from the **same origin** as a urapt-server,
|
|
behind a reverse proxy that serves the SPA from `dist/` and forwards `/api/v1`
|
|
and `/apt` to `urapt-server`. No CORS, no server changes — the API base is just
|
|
`/api/v1`.
|
|
|
|
```bash
|
|
pnpm build # outputs dist/
|
|
```
|
|
|
|
### Railway
|
|
|
|
`urapt-web/` includes a Dockerfile for deploying the UI as a separate Railway
|
|
service. The container builds the Vite app and serves it with Caddy, proxying
|
|
`/api/*` and `/apt/*` to an existing `urapt-server` service.
|
|
|
|
In Railway, create a new service from this repo with:
|
|
|
|
- Root Directory: `urapt-web`
|
|
- Environment variable: `URAPT_SERVER_URL=https://your-urapt-server.up.railway.app`
|
|
|
|
A trailing slash is okay; the container normalizes it before starting Caddy.
|
|
|
|
Do not set `VITE_API_BASE_URL` for this deployment; the UI should keep using the
|
|
default same-origin `/api/v1` path.
|
|
|
|
|
|
### Caddy
|
|
|
|
```caddy
|
|
apt.example.com {
|
|
# SPA
|
|
root * /srv/urapt-web/dist
|
|
try_files {path} /index.html
|
|
file_server
|
|
|
|
# REST API + APT endpoint
|
|
reverse_proxy /api/* 127.0.0.1:8080
|
|
reverse_proxy /apt/* 127.0.0.1:8080
|
|
}
|
|
```
|
|
|
|
### nginx
|
|
|
|
```nginx
|
|
server {
|
|
listen 80;
|
|
server_name apt.example.com;
|
|
root /srv/urapt-web/dist;
|
|
|
|
location / { try_files $uri /index.html; }
|
|
|
|
location /api/ { proxy_pass http://127.0.0.1:8080; }
|
|
location /apt/ { proxy_pass http://127.0.0.1:8080; }
|
|
}
|
|
```
|
|
|
|
## Architecture
|
|
|
|
```
|
|
src/
|
|
lib/api/ typed client mirroring urapt's shared/api + shared/models
|
|
(client, errors, endpoints, types)
|
|
stores/ Zustand auth store (persisted token)
|
|
hooks/ shared server/user queries, logout
|
|
components/ app shell, common UI (copy button, confirm, states), shadcn ui
|
|
features/ auth, setup, repos (tabs), tokens, users, settings
|
|
routes.tsx route tree with lazy-loaded pages + protected/admin guards
|
|
```
|
|
|
|
The API client (`src/lib/api/`) is hand-written and typed against urapt's Go
|
|
DTOs in `shared/api/api.go` and `shared/models/models.go`. A `401` anywhere
|
|
clears the local session and redirects to `/login`.
|
|
|
|
## License
|
|
|
|
GPL-3.0-or-later, matching the urapt project.
|