|
1 | 1 | # Frosting |
2 | 2 |
|
3 | | -Frontend for [cupcake](https://github.com/javaBin/cupcake) |
| 3 | +Vue 3 / Nuxt frontend for [cupcake](https://github.com/javaBin/cupcake). Lets javaBin program committee members (`pkom` role) browse JavaZone conferences and sessions to find potential speakers for local events. |
4 | 4 |
|
5 | | -## TODO |
| 5 | +## Tech stack |
6 | 6 |
|
7 | | -Always lots to do - but - before we can release this: |
| 7 | +- **Framework**: Nuxt (SPA mode) |
| 8 | +- **UI**: Nuxt UI + Tailwind CSS |
| 9 | +- **Auth**: OIDC Authorization Code flow via `oidc-client-ts` |
| 10 | +- **Icons**: Nuxt Icon (Carbon, Lucide, Logos, OpenMoji) |
| 11 | +- **Metrics**: Prometheus via `@artmizu/nuxt-prometheus` |
| 12 | +- **Package manager**: pnpm |
8 | 13 |
|
9 | | -- Some tests would be nice :) |
| 14 | +## Pages |
10 | 15 |
|
11 | | -## Build |
| 16 | +| Route | Description | |
| 17 | +|---|---| |
| 18 | +| `/` | Home — shows authenticated user and role check | |
| 19 | +| `/conference/[conferenceId]` | Session browser with filtering for a conference | |
| 20 | +| `/conference/[conferenceId]/session/[sessionId]` | Session detail with full speaker info (bio, email, location) | |
12 | 21 |
|
13 | | -Nuxt application using pnpm |
| 22 | +## Authentication |
14 | 23 |
|
15 | | - pnpm install |
| 24 | +The app uses the OIDC Authorization Code flow. Tokens are stored in browser `sessionStorage`. All API requests are automatically sent with a Bearer token, and a 401 response triggers a silent refresh before retrying. |
16 | 25 |
|
17 | | -## Local running |
| 26 | +Access requires the `pkom` role in the configured OIDC provider. The home page displays a warning if the authenticated user does not have this role. |
18 | 27 |
|
19 | | - pnpm dev |
| 28 | +## Local development |
20 | 29 |
|
21 | | -## Preview build |
| 30 | +Install dependencies: |
22 | 31 |
|
23 | | - pnpm build |
24 | | - pnpm preview |
| 32 | +```bash |
| 33 | +pnpm install |
| 34 | +``` |
25 | 35 |
|
26 | | -### Configuration |
| 36 | +Start the dev server (proxies `/api/*` to `http://127.0.0.1:8080` by default): |
27 | 37 |
|
28 | | -| Environment Variable | Description | Default | |
29 | | -|------------------------------|------------------------------------------------------|--------------------------------------------------------------------------| |
30 | | -| `CUPCAKE_BACKEND` | Backend base URL for the server-side proxy | `http://127.0.0.1:8080` (dev) / `https://cupcake-backend.java.no` (prod) | |
31 | | -| `CUPCAKE_FRONTEND` | Hostname the dev server allows (Vite `allowedHosts`) | `localhost` | |
32 | | -| `NUXT_PUBLIC_OIDC_AUTHORITY` | OIDC authority URL (e.g. Keycloak realm URL) | `https://auth.home.chrissearle.org/realms/HA12` | |
33 | | -| `NUXT_PUBLIC_OIDC_CLIENT_ID` | OIDC client ID | `cupcake-client` | |
| 38 | +```bash |
| 39 | +pnpm dev |
| 40 | +``` |
| 41 | + |
| 42 | +The cupcake backend must be running locally unless you override `CUPCAKE_BACKEND`. With `JWT_ENABLED=false` on the backend, no auth configuration is needed. |
| 43 | + |
| 44 | +The frontend OIDC defaults point to the development Keycloak realm, so no `NUXT_PUBLIC_OIDC_*` overrides are needed for local dev against that environment. |
| 45 | + |
| 46 | +## Preview a production build |
| 47 | + |
| 48 | +```bash |
| 49 | +pnpm build |
| 50 | +pnpm preview |
| 51 | +``` |
| 52 | + |
| 53 | +## Linting |
| 54 | + |
| 55 | +```bash |
| 56 | +pnpm lint # check |
| 57 | +pnpm lint:fix # auto-fix |
| 58 | +``` |
| 59 | + |
| 60 | +ESLint and Prettier are also enforced via pre-commit hooks (lint-staged). |
| 61 | + |
| 62 | +## Configuration |
| 63 | + |
| 64 | +| Environment Variable | Description | Default | |
| 65 | +|---|---|---| |
| 66 | +| `CUPCAKE_BACKEND` | Backend base URL for the server-side proxy | `http://127.0.0.1:8080` (dev) / `https://cupcake-backend.java.no` (prod) | |
| 67 | +| `CUPCAKE_FRONTEND` | Hostname the dev server allows (Vite `allowedHosts`) | `localhost` | |
| 68 | +| `NUXT_PUBLIC_OIDC_AUTHORITY` | OIDC authority URL (e.g. Keycloak realm URL) | `https://auth.home.chrissearle.org/realms/HA12` | |
| 69 | +| `NUXT_PUBLIC_OIDC_CLIENT_ID` | OIDC client ID | `cupcake-client` | |
| 70 | + |
| 71 | +`NUXT_PUBLIC_OIDC_AUTHORITY` and `NUXT_PUBLIC_OIDC_CLIENT_ID` must match the `OIDC_WELL_KNOWN_URL` and `OIDC_EXPECTED_AZP` values configured on the backend. |
| 72 | + |
| 73 | +## Proxy middleware |
| 74 | + |
| 75 | +The Nuxt server middleware transparently proxies the following paths to the cupcake backend: |
| 76 | + |
| 77 | +- `/api/*` — conference and session data |
| 78 | +- `/login` — OIDC login initiation |
| 79 | +- `/refresh` — token refresh |
| 80 | + |
| 81 | +This keeps the frontend and backend on the same origin from the browser's perspective, avoiding CORS issues. |
| 82 | + |
| 83 | +## Docker |
| 84 | + |
| 85 | +Multi-platform images (`linux/amd64`, `linux/arm64`) are published to `ghcr.io/javabin/frosting`. |
| 86 | + |
| 87 | +To build locally: |
| 88 | + |
| 89 | +```bash |
| 90 | +docker build -t frosting . |
| 91 | +``` |
| 92 | + |
| 93 | +The image uses a multi-stage build (Node build stage, slim runtime stage) and serves via the Nitro server on port 3000. |
| 94 | + |
| 95 | +## CI/CD |
| 96 | + |
| 97 | +| Trigger | Workflow | What it does | |
| 98 | +|---|---|---| |
| 99 | +| Push to `main` | `build.yaml` | Builds and pushes multi-platform Docker image, tags as `staging` | |
| 100 | +| Pull request | `pr.yaml` | Runs `pnpm lint` and `pnpm build` | |
| 101 | +| Tag `v*` | `release.yaml` | Promotes `staging` image to `release` and version tag | |
0 commit comments