pubsub-dashboard
v1.0.0
Published
Local-first developer dashboard for Google Cloud Pub/Sub — runs entirely on 127.0.0.1, authenticates via gcloud ADC, zero telemetry.
Downloads
1,169
Maintainers
Readme
pubsub-dashboard
A local-first dashboard for Google Cloud Pub/Sub. It runs entirely on
127.0.0.1, authenticates with your existing gcloud Application Default
Credentials, and never talks to anything except Google Cloud APIs.
- Loopback only — binds
127.0.0.1, refuses non-localHostheaders. - No credentials of its own — reuses
gcloud auth application-default login. - No project inference — the active project comes only from
gcloud config get-value project(neverGOOGLE_CLOUD_PROJECT). - One command —
npx pubsub-dashboardboots and opens your browser.
Prerequisites
- OS: macOS or Linux. Windows is not supported in v1.
- Node.js: ≥ 20 LTS — check with
node --version. - Google Cloud SDK (
gcloud) installed and onPATH. - ADC configured: run
gcloud auth application-default loginonce. - Active project: run
gcloud config set project <PROJECT_ID>once.
Quickstart
gcloud auth application-default login # once
gcloud config set project <PROJECT_ID> # once
npx pubsub-dashboard # boots + opens http://127.0.0.1:4321The block below is the verifiable quickstart — CI runs it on every PR
(FR-019). It launches the server, waits for /api/health to report ok, then
shuts it down. Set PUBSUB_BIN to point at a local build; it defaults to the
published CLI. In CI, PUBSUB_DEMO_PROJECT lets the server boot without gcloud.
set -euo pipefail
PUBSUB_BIN="${PUBSUB_BIN:-npx pubsub-dashboard}"
PORT="${PORT:-4321}"
# Launch the loopback-only dashboard in the background.
$PUBSUB_BIN --port "$PORT" &
SERVER_PID=$!
trap 'kill "$SERVER_PID" 2>/dev/null || true' EXIT
# Poll the health endpoint until the server is ready.
ready=""
for _ in $(seq 1 40); do
if curl -fsS "http://127.0.0.1:${PORT}/api/health" >/tmp/pubsub-health.json 2>/dev/null; then
ready="yes"
break
fi
sleep 0.25
done
test -n "$ready"
grep -q '"status":"ok"' /tmp/pubsub-health.json
echo "pubsub-dashboard health: ok"A browser tab opens on http://127.0.0.1:4321 showing the active project ID,
your identity, and a Diagnostics panel with the most recent backend operation.
GCP Resource Browser
The dashboard lets you browse all GCP projects accessible via your ADC credentials, and then inspect the Pub/Sub topics and subscriptions within each project.
Screenshot
Required IAM roles
Two roles must be granted on each project you want to browse:
| Role | Purpose |
| ------------------------------------------------------------------------------------- | -------------------------------------------------------- |
| roles/resourcemanager.projects.list (or resourcemanager.projects.list permission) | List all GCP projects via the Cloud Resource Manager API |
| roles/pubsub.viewer | List topics and subscriptions within a project |
Grant pubsub.viewer to your account with:
gcloud projects add-iam-policy-binding <PROJECT_ID> \
--member="user:<YOUR_EMAIL>" \
--role="roles/pubsub.viewer"To list all your accessible projects the ADC account also needs
resourcemanager.projects.list. On most GCP organisations this is already
included in roles/viewer or roles/browser. If you only see a
PERMISSION_DENIED error on the project list, grant it explicitly:
gcloud projects add-iam-policy-binding <PROJECT_ID> \
--member="user:<YOUR_EMAIL>" \
--role="roles/browser"API endpoints
| Endpoint | Description |
| -------------------------------------------- | ------------------------------------------------------------- |
| GET /api/projects | Lists all GCP projects accessible to the current ADC identity |
| GET /api/projects/:projectId/topics | Lists Pub/Sub topics in the given project |
| GET /api/projects/:projectId/subscriptions | Lists Pub/Sub subscriptions in the given project |
All three endpoints propagate a traceId (UUID) in both the response body and
the X-Trace-Id header so that individual requests can be correlated in logs.
Interface
The dashboard ships a "Kanagawa × Blade Runner" interface — a Japanese-ink
palette with neon accents and HUD framing. It is presentation only: every
capability of the resource browser, publisher, and receiver is unchanged. All
preferences persist in localStorage and are applied before first paint (no
flash of the wrong appearance); nothing leaves your machine.
- Themes — Sumi-Ink dark (default) and Lotus light, toggled from the header.
- Workspace layouts — switch between Rail, Triptych, and Console from the appearance settings (gear icon). Your active selection and the in-progress compose draft survive every layout change.
- Command palette — press ⌘K / Ctrl+K (or the header ⌘K button) to jump to any project, topic, or subscription. Navigation only; type to filter, arrows to move, Enter to select, Esc to close.
- Appearance settings — the gear icon opens theme, density
(compact/regular/cozy), accent (cyan/magenta/amber/violet), and layout
controls. (Neon intensity and scanlines are fixed defaults, minimized under
prefers-reduced-motion.) - Keyboard-navigable lists — each resource list filters as you type, with ↑/↓, Home/End, Enter, and Esc, and a bounded scroll so the editors stay visible.
- Live JSON highlighting — the publisher colorizes JSON as you type (display-only; the published bytes are exactly what you see).
- Receiver auto-poll — opt-in Auto mode pulls every 2.5 s with a visible indicator; the running list is capped at the 60 newest messages. Manual Pull is always available.
Supported OS
macOS and Linux only. Windows is not supported in v1.
What's in scope (and what's not)
In scope for v1 (this release): one-command boot, gcloud ADC auth, active project + identity display, loopback-only operation with strict CSP and log redaction, and an in-app Diagnostics panel.
Out of scope for v1 (planned for feature 002+): publishing messages, subscribing/pulling messages, and JSON message composition. See docs/extension-points.md for how those features plug in without changing the boot or auth paths.
Flags
| Flag | Default | Effect |
| ------------ | ------- | ------------------------------------------------------------------------------------- |
| --port <n> | 4321 | Override the local port. Exits non-zero with a clear error if the port is in use. |
| --verbose | off | Raise log level to debug. Payloads are revealed in logs; credentials stay redacted. |
| --help | — | Print the flag list and exit 0. |
| --version | — | Print the version and exit 0. |
Troubleshooting
| Symptom | Cause | Fix |
| ------------------------------- | ----------------------- | -------------------------------------------------------- |
| ADC not found exit | ADC login not run | gcloud auth application-default login |
| gcloud not on PATH exit | Cloud SDK not installed | Install from https://cloud.google.com/sdk/docs/install |
| No active gcloud project exit | No active project | gcloud config set project <PROJECT_ID> |
| Port 4321 in use exit | Port busy | npx pubsub-dashboard --port 5173 |
| Requires Node >= 20 LTS exit | Node too old | Install / switch to Node 20 LTS+ |
| Browser does not open | No default browser | Open the printed URL manually |
Stop
Press Ctrl+C. The server stops within 1 second, releases the port, and leaves no orphan processes.
Contributing
See docs/contributing.md for the local verification workflow and CI / branch-protection setup.
