Restructure Web App into server/ + web/ (GsmNode parity)

Reorganize the Web App to match the GsmNode project layout: a Go
backend-for-frontend in server/ that embeds the built SPA and reverse-proxies
/api/* to the API Server, with the Vue 3 + Vite frontend moved into web/.

- Move all frontend files into web/ (history preserved via renames)
- Point vite build output at ../server/dist for Go embedding
- Add server/ Go BFF (main.go, go.mod, .env.example, Run-WebApp.ps1)
- Drop Docker/nginx deploy (Dockerfile, docker-compose.yml, nginx.conf.template,
  .dockerignore) in favor of the BFF, matching GsmNode
- Update .claude/launch.json to run the dev server from web/
- Rewrite README.md for the new layout

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
tajniak81andClaude Opus 4.8 committed 2026-07-13 11:34:02 +02:00
1 parent ba3f227361
commit 75a2ccc226
47 files changed
+230 -161

No files matched your search

+60 -34
View File
@@ -1,27 +1,78 @@
# DriverVault — Web App
Vue 3 + Vite + Tailwind CSS v4 maintenance tracker. Talks **only** to the API
Server (never to PocketBase directly). Built from `Car Service.xlsx`. Plain JS
(not TS). Vue calls the central API Server directly — there is no separate web
backend.
Maintenance tracker for your cars: a **Vue 3 + Vite + Tailwind CSS v4** SPA served
by a small **Go backend-for-frontend (BFF)**. The BFF serves the built SPA and
reverse-proxies `/api/*` to the API Server, so the browser is always same-origin
and all data access still flows through the API Server (never PocketBase directly).
## Run
```
Browser ─► Web App BFF (:8090) ──/api/*──► API Server (:8080) ─► PocketBase
└── serves embedded Vue SPA
```
## Layout
```
server/ Go BFF: embeds web/dist, proxies /api -> API_BASE
main.go
.env.example
dist/ built SPA (generated; embedded at compile time)
web/ Vue 3 + Vite + Tailwind v4 source
src/
main.js app bootstrap
router.js /login, / (dashboard), /cars/:id, /settings, /admin
api.js the only place that calls the API Server (base URL resolution)
auth.js session/profile state, isAdmin
prefs.js theme/locale/date/font preferences -> <html>
lib/format.js date/km formatting + next-service status badges
style.css Tailwind v4 entry (+ dark custom-variant)
App.vue layout shell + nav (Admin link when admin)
components/ Modal, CarFormModal, ServiceFormModal, PartFormModal, ShareModal, Logo
views/ Login, Dashboard, CarDetail, Settings, AdminUsers
```
## Requirements
- Node 18+ and Go 1.26+
- A running **API Server** (see `../API Server`)
## Develop
Two terminals:
```powershell
npm install
npm run dev # http://localhost:5173
# terminal 1 — API Server (see ../API Server/README.md)
cd "../API Server"; ./api-server.exe
# terminal 2 — Vite dev server with hot reload (proxies /api -> :8080)
cd web; npm install; npm run dev # http://localhost:5173
```
The dev server proxies `/api/*` to the API Server (default `http://localhost:8080`,
override with `VITE_API_TARGET`), so the client uses same-origin relative URLs and
avoids CORS. The **API Server must be running** — see `../API Server/README.md`.
The dev server also listens on all interfaces (`host: true`) so it's reachable on
avoids CORS. It also listens on all interfaces (`host: true`) so it's reachable on
the LAN (e.g. `http://10.2.1.101:5173`).
At runtime, users can override the API base URL from the login screen's **Server
settings** (persisted in `localStorage` as `cc_server_url`); resolution order is
that override → `VITE_API_BASE` → `/api`.
## Build & run (production-style)
```powershell
./server/Run-WebApp.ps1 # builds frontend, then serves on :8090
# or manually:
cd web; npm run build # outputs to ../server/dist
cd ../server; go run . # http://localhost:8090
```
Config (`server/.env`, copy from `.env.example`):
| Variable | Purpose | Default |
|---|---|---|
| `WEB_ADDR` | Listen address | `:8090` |
| `API_BASE` | API Server base URL | `http://localhost:8080` |
## Features
- **Dashboard** — one card per car: last service, odometer, next-due date/km, and
@@ -48,28 +99,3 @@ Login gets a JWT from the API Server (stored client-side) and creates a server
session. `auth.js` exposes `isAdmin` and the current profile; the router guards
`public` / `admin` routes. Cars are per-user (owned + shared), and the UI mirrors
the server's read / write / owner access levels.
## Structure
```
src/
├── main.js # app bootstrap
├── router.js # /login, / (dashboard), /cars/:id, /settings, /admin
├── api.js # the only place that calls the API Server (base URL resolution)
├── auth.js # session/profile state, isAdmin
├── prefs.js # theme/locale/date/font preferences → <html>
├── lib/format.js # date/km formatting + next-service status badges
├── style.css # Tailwind v4 entry (+ dark custom-variant)
├── App.vue # layout shell + nav (Admin link when admin)
├── components/
│ ├── Modal.vue CarFormModal.vue ServiceFormModal.vue PartFormModal.vue ShareModal.vue
└── views/
├── Login.vue Dashboard.vue CarDetail.vue
└── Settings.vue AdminUsers.vue
```
## Build
```powershell
npm run build # -> dist/
```