Skip to content

fix(dashboard): derive per-project setup URL from live origin#1511

Merged
JerrettDavis merged 2 commits into
headroomlabs-ai:mainfrom
rodboev:pr/1508-dashboard-origin-hint
Jun 30, 2026
Merged

fix(dashboard): derive per-project setup URL from live origin#1511
JerrettDavis merged 2 commits into
headroomlabs-ai:mainfrom
rodboev:pr/1508-dashboard-origin-hint

Conversation

@rodboev

@rodboev rodboev commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

Description

The Per-Project Savings empty state currently shows a hardcoded ANTHROPIC_BASE_URL: http://127.0.0.1:8787/p/<project-name>. When the proxy listens on a fallback or custom port, users can copy a broken setup URL from the dashboard. This change derives the hint from the browser's live origin and keeps the existing /p/<project-name> suffix used by per-project savings. Closes #1508.

Related context: #1406 made non-default proxy ports a normal path, which makes the hardcoded dashboard hint user-visible more often.

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update
  • Performance improvement
  • Code refactoring (no functional changes)

Changes Made

  • Replace the static Per-Project Savings setup hint with an Alpine x-text binding that uses window.location.origin.
  • Preserve the /p/<project-name> suffix so the displayed path shape stays aligned with the existing per-project routing contract.
  • Add a Playwright regression that loads the dashboard from non-default origins and asserts the empty state follows the active page origin instead of 8787.

Testing

  • Unit tests pass (uv run pytest tests/test_dashboard_cache_ttl_playwright.py -k "per_project_setup_url_uses_current_origin" -v)
  • Unit tests pass (uv run pytest tests/test_owned_asset_encoding.py::test_get_dashboard_html_reads_as_utf8 tests/test_proxy_dashboard_stats_cache.py::test_dashboard_uses_cached_stats_and_lazy_history_feed_polling -v)
  • Linting passes (uv run ruff check tests/test_dashboard_cache_ttl_playwright.py)
  • Type checking passes (uv run mypy headroom)
  • New tests added for new functionality when applicable
  • Manual testing performed

Test Output

uv run pytest tests/test_dashboard_cache_ttl_playwright.py -k "per_project_setup_url_uses_current_origin" -v
tests/test_dashboard_cache_ttl_playwright.py::test_dashboard_per_project_setup_url_uses_current_origin PASSED [100%]
================= 1 passed, 1 deselected, 1 warning in 0.82s ==================

uv run pytest tests/test_owned_asset_encoding.py::test_get_dashboard_html_reads_as_utf8 tests/test_proxy_dashboard_stats_cache.py::test_dashboard_uses_cached_stats_and_lazy_history_feed_polling -v
tests/test_owned_asset_encoding.py::test_get_dashboard_html_reads_as_utf8 PASSED [ 50%]
tests/test_proxy_dashboard_stats_cache.py::test_dashboard_uses_cached_stats_and_lazy_history_feed_polling PASSED [100%]
======================== 2 passed, 1 warning in 0.16s =========================

uv run ruff check tests/test_dashboard_cache_ttl_playwright.py
All checks passed!

Real Behavior Proof

  • Environment: Playwright Chromium dashboard harness, dashboard template served through the existing route interception used by the dashboard tests, no live provider required.
  • Exact command / steps: uv run pytest tests/test_dashboard_cache_ttl_playwright.py -k "per_project_setup_url_uses_current_origin" -v
  • Observed result: http://127.0.0.1:8788/dashboard passed with the new current-origin assertion, and origin/main failed the same assertion because the page still rendered ANTHROPIC_BASE_URL: http://127.0.0.1:8787/p/<project-name>. A separate browser check against http://headroom.local:9393/dashboard also passed on the patched branch.
  • Not tested: full live headroom proxy --port 8788 browser validation, unless it is run during implementation.

Review Readiness

  • I have performed a self-review
  • This PR is ready for human review

Checklist

  • My code follows the project's style guidelines
  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • I have updated the CHANGELOG.md if applicable

Additional Notes

CHANGELOG.md is intentionally unchanged because this repo generates changelog entries from conventional commits. The documentation checkbox is satisfied by correcting the in-dashboard setup instruction.

@github-actions

Copy link
Copy Markdown
Contributor

PR governance

This PR follows the template and is marked ready for human review.

@github-actions github-actions Bot added the status: ready for review Pull request body is complete and the author marked it ready for human review label Jun 27, 2026

@JerrettDavis JerrettDavis left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks ready. Deriving the empty-state setup hint from window.location.origin fixes alternate-port/dashboard-host deployments without changing the API surface, and the Playwright coverage proves both the non-default port and host cases. CI is green.

@JerrettDavis JerrettDavis merged commit e035aef into headroomlabs-ai:main Jun 30, 2026
21 checks passed
@github-actions github-actions Bot mentioned this pull request Jun 30, 2026
chopratejas pushed a commit that referenced this pull request Jul 3, 2026
🤖 I have created a release *beep* *boop*
---


<details><summary>0.29.0</summary>

##
[0.29.0](v0.28.0...v0.29.0)
(2026-07-03)


### Features

* **proxy:** add --lossless no-CCR mode with format-native compaction
([#1721](#1721))
([c75ebde](c75ebde))
* **stats:** surface Codex WS compression counters in /stats summary
([#1680](#1680))
([2fe19c3](2fe19c3))
* **transforms:** adaptive Otsu KEEP/DROP threshold (+ land relevance
split on main)
([#1726](#1726))
([eea667a](eea667a))


### Bug Fixes

* **bedrock:** fail fast when session-token auth lacks botocore
([#1553](#1553))
([54cfa36](54cfa36))
* **bedrock:** route ARNs via converse, named AWS profiles, and au. re…
([#1456](#1456))
([7d87aa2](7d87aa2))
* **ccr:** honor workspace dir for sqlite store
([#1564](#1564))
([96e1dfe](96e1dfe))
* **claude:** surface Remote Control proxy incompatibility
([#1610](#1610))
([4bf7f92](4bf7f92))
* **cli:** stop advertising unwired compression tuning env vars in
banner
([#1634](#1634))
([d5bf98d](d5bf98d))
* **codex:** avoid duplicate headroom provider config
([#1431](#1431))
([ddd4adf](ddd4adf))
* **compression:** reject lossy unmarked tool output in unit router path
([#1479](#1479))
([de24cd5](de24cd5))
* **cortex-code:** migrate to current Cortex REST API endpoints + add
e2e benchmarks
([#1474](#1474))
([f00ace6](f00ace6))
* **dashboard:** align token savings headline denominator
([#1653](#1653))
([646e705](646e705))
* **dashboard:** derive per-project setup URL from live origin
([#1511](#1511))
([e035aef](e035aef))
* **detection:** contain unidiff panic on orphaned +++ target line
([#1548](#1548))
([e386c09](e386c09))
* **evals:** CJK-aware F1 tokenization + token estimation
([#1527](#1527))
([99a8540](99a8540))
* **install:** close parent log fd in start_detached_agent
([#1576](#1576))
([816cb85](816cb85))
* **install:** use Windows-safe PID liveness probe in runtime_status
([#1544](#1544))
([#1560](#1560))
([6b227b9](6b227b9))
* **learn:** aggregate verbosity baselines across projects instead of
overwriting
([#1288](#1288))
([27a5468](27a5468))
* **mcp:** show lifetime totals and label rolling session scope in
headroom_stats
([#1428](#1428))
([1c0e152](1c0e152))
* **memory:** cap local embedder CPU thread oversubscription
([#198](#198))
([#1559](#1559))
([b84afbf](b84afbf))
* **memory:** singleflight LocalBackend init to stop cold-start races
([#1691](#1691))
([bec47a1](bec47a1))
* **openclaw:** detect uv-installed headroom binary in ~/.local/bin
([#1459](#1459))
([adaeb88](adaeb88))
* **opencode:** preserve custom OpenAI gateway paths
([#1596](#1596))
([c19347c](c19347c))
* **opencode:** route native providers + load transport plugin, fix
Serena context
([#1573](#1573))
([ad0034f](ad0034f))
* preserve anthropic passthrough tool order
([#1427](#1427))
([a932247](a932247))
* **proxy/auth:** match real Anthropic OAuth token prefix (sk-ant-oat)
([#1672](#1672))
([8cddf9b](8cddf9b))
* **proxy:** expose persistent savings metrics
([#1647](#1647))
([5fe4e7b](5fe4e7b))
* **proxy:** fail open when kompress saturation would exhaust
pre-upstream budget
([#1430](#1430))
([15ac650](15ac650))
* **proxy:** handle streaming CCR retrieval
([#1451](#1451))
([d337e3b](d337e3b))
* **proxy:** include system/tools/sampling in cache key
([#1473](#1473))
([312129a](312129a))
* **proxy:** preserve Responses passthrough bytes
([#1598](#1598))
([2a34a82](2a34a82))
* **proxy:** strip Codex lite header on the HTTP /responses path
([#1663](#1663))
([9fbd47b](9fbd47b))
* **proxy:** wire --compression-max-workers /
HEADROOM_COMPRESSION_MAX_WORKERS
([#1632](#1632))
([814ffa3](814ffa3))
* **savings:** count cache-read tokens in input cost estimate
([#1429](#1429))
([72ade37](72ade37))
* skip Magika backend on x86 CPUs without AVX2
([#1162](#1162))
([64783d8](64783d8))
* **transforms/content-router:** route grep/log output away from HTML
extractor
([#1719](#1719))
([0d18ef2](0d18ef2))
* **transforms:** bound native content detection with a Windows watchdog
([#575](#575))
([#1563](#1563))
([95abca3](95abca3))
* Vertex AI support for Claude Code with ANTHROPIC_VERTEX_BASE_URL
([#1393](#1393))
([cff7247](cff7247))
* **wrap:** detach the shared proxy on Windows so it survives an
ungraceful agent close
([#1464](#1464))
([6cba441](6cba441))
* **wrap:** preserve custom Vertex base URL
([#1477](#1477))
([75427bb](75427bb))
* **wrap:** remove rtk instructions from Codex AGENTS.md on unwrap
([#1604](#1604))
([c9d717c](c9d717c))
</details>

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

status: ready for review Pull request body is complete and the author marked it ready for human review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Dashboard per-project setup URL hardcodes port 8787

2 participants