Skip to content

Added frontend admin toolbar#28058

Merged
ErisDS merged 14 commits into
mainfrom
codex/frontend-admin-toolbar
May 28, 2026
Merged

Added frontend admin toolbar#28058
ErisDS merged 14 commits into
mainfrom
codex/frontend-admin-toolbar

Conversation

@JohnONolan
Copy link
Copy Markdown
Member

@JohnONolan JohnONolan commented May 22, 2026

Summary

  • Added a staff-only frontend admin toolbar for public Ghost pages.
  • Added a new @tryghost/admin-toolbar package that owns the toolbar source, tests, Vite build, and UMD artifact.
  • Added staff frontend tools wiring in Ghost core so ghost_head injects staff-only scripts only after the frontend marker is present.
  • Added frontend activation from Admin view-site links and hidden iframe handling.
toolbar.mp4

Architecture

The toolbar is not rendered into public HTML by default. Admin links to the frontend add ?admin=1, which is handled by the new frontend middleware. That middleware creates a short-lived, signed ghost-admin-toolbar marker cookie on the frontend domain and redirects back to the clean URL. The marker is intentionally not a staff session and contains no personalized data; it only says that this browser should be offered staff frontend tooling.

On subsequent frontend requests, the middleware validates the marker and sets res.locals.staffFrontendToolsEnabled. ghost_head delegates staff-only script selection to staff-frontend-tools/head-scripts, which emits the non-personal admin-toolbar.min.js script and page metadata needed to build the correct toolbar actions.

The browser bundle still verifies the real staff session through the existing hidden /ghost/auth-frame/ bridge before rendering. It calls getUser, requires an Owner, Administrator, or Editor role, then mounts the toolbar in a Shadow DOM so theme CSS cannot affect it. This keeps normal visitor pages cacheable and prevents staff-specific data from being embedded in server-rendered HTML.

The Admin "view site" iframe also passes admin=1&admin_toolbar=0. That seeds the frontend marker cookie, but the middleware suppresses staff tool injection inside iframe responses using the explicit query parameter and Sec-Fetch-Dest: iframe. This lets Admin enable the toolbar for normal frontend visits without rendering the toolbar inside the Admin preview iframe.

Package boundary

The toolbar source now lives in apps/admin-toolbar. The package owns its source modules, Vite build, tests, README/LICENSE, and umd/admin-toolbar.min.js. Ghost core no longer builds from apps/admin-toolbar/src; ghost/core builds the package first and then copies the package UMD artifact into core/frontend/public/admin-toolbar.min.js. This keeps core responsible for activation, caching, serving, and head injection, while the package owns the toolbar runtime.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 22, 2026

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds a new frontend admin-toolbar package (Preact) with build config, UMD bundle, components, styles, action/link helpers, auth iframe + admin API, storage helpers, and a bootstrap entrypoint that renders into shadow DOM. Integrates server-side: middleware to set/validate a signed toolbar cookie, head-scripts service to inject the toolbar script with data attributes, a public route to serve the bundle, build-step copying of the prebuilt UMD into the core public assets, and unit/integration tests for client and server behavior.

Possibly related PRs

  • TryGhost/Ghost#27742: Related frontend caching and unit test updates covering admin-toolbar caching scenarios.

Suggested labels

preview

Suggested reviewers

  • EvanHahn
  • mike182uk
  • 9larsons
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 7.58% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main feature added: a frontend admin toolbar. It is concise, clear, and directly reflects the primary change in the changeset.
Description check ✅ Passed The description is comprehensive and directly related to the changeset. It explains the summary, architecture, package boundary, and objectives in detail, all of which align with the changes made.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/frontend-admin-toolbar

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
apps/admin/src/layout/app-sidebar/user-menu.tsx (1)

16-28: ⚡ Quick win

Consider extracting the helper to a shared module.

Both nav-main.tsx and user-menu.tsx define similar getAdminToolbarUrl helpers with slightly different signatures:

  • nav-main.tsx: (url?: string) => string | undefined
  • user-menu.tsx: (url: string) => string

This duplication could lead to maintenance drift. Consider extracting a single shared helper (e.g., to a utils or helpers module) to maintain consistency.

Also applies to: 205-205

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/admin/src/layout/app-sidebar/user-menu.tsx` around lines 16 - 28,
Extract the duplicated getAdminToolbarUrl logic into a single exported helper in
a shared module (e.g., helpers or utils) and update both implementations to
import and use that shared function; unify the signature to accept url?: string
and return string | undefined (or choose the consistent nullable/empty behavior
your app expects), implement the same URL manipulation (new URL(url) with
searchParams.set("admin","1") and safe try/catch fallback), export it (e.g.,
export function getAdminToolbarUrl(url?: string): string | undefined) and
replace the local functions in nav-main.tsx and user-menu.tsx with imports from
the new module, updating call sites to handle the unified return type.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/admin-toolbar/package.json`:
- Around line 20-24: The package.json scripts call binaries directly; update the
"scripts" entries to invoke binaries through pnpm: change "build" to use "pnpm
exec vite build", change "lint" to "pnpm exec eslint src --ext .js --cache", and
change "test" to call the local build via "pnpm run build" then run mocha via
pnpm like "pnpm exec mocha --exit --trace-warnings --timeout=60000
\"test/**/*.test.js\""; modify the "build", "lint", and "test" script values
accordingly.

---

Nitpick comments:
In `@apps/admin/src/layout/app-sidebar/user-menu.tsx`:
- Around line 16-28: Extract the duplicated getAdminToolbarUrl logic into a
single exported helper in a shared module (e.g., helpers or utils) and update
both implementations to import and use that shared function; unify the signature
to accept url?: string and return string | undefined (or choose the consistent
nullable/empty behavior your app expects), implement the same URL manipulation
(new URL(url) with searchParams.set("admin","1") and safe try/catch fallback),
export it (e.g., export function getAdminToolbarUrl(url?: string): string |
undefined) and replace the local functions in nav-main.tsx and user-menu.tsx
with imports from the new module, updating call sites to handle the unified
return type.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 85c27896-68ed-4e8f-9041-d127cb454978

📥 Commits

Reviewing files that changed from the base of the PR and between 148a027 and bcc8983.

⛔ Files ignored due to path filters (3)
  • apps/admin-toolbar/umd/admin-toolbar.min.js is excluded by !**/*.min.js
  • ghost/core/core/frontend/public/admin-toolbar.min.js is excluded by !**/*.min.js
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (33)
  • apps/admin-toolbar/LICENSE
  • apps/admin-toolbar/README.md
  • apps/admin-toolbar/package.json
  • apps/admin-toolbar/src/actions.js
  • apps/admin-toolbar/src/auth.js
  • apps/admin-toolbar/src/body-offset.js
  • apps/admin-toolbar/src/components.js
  • apps/admin-toolbar/src/config.js
  • apps/admin-toolbar/src/constants.js
  • apps/admin-toolbar/src/icons.js
  • apps/admin-toolbar/src/index.js
  • apps/admin-toolbar/src/links.js
  • apps/admin-toolbar/src/storage.js
  • apps/admin-toolbar/src/styles.js
  • apps/admin-toolbar/src/user.js
  • apps/admin-toolbar/test/admin-toolbar.test.js
  • apps/admin-toolbar/vite.config.mjs
  • apps/admin/src/layout/app-sidebar/nav-main.tsx
  • apps/admin/src/layout/app-sidebar/user-menu.tsx
  • ghost/admin/app/components/gh-site-iframe.js
  • ghost/core/bin/minify-assets.js
  • ghost/core/core/frontend/helpers/ghost_head.js
  • ghost/core/core/frontend/services/staff-frontend-tools/head-scripts.js
  • ghost/core/core/frontend/web/middleware/admin-toolbar.js
  • ghost/core/core/frontend/web/middleware/frontend-caching.js
  • ghost/core/core/frontend/web/middleware/index.js
  • ghost/core/core/frontend/web/routers/serve-public-file.js
  • ghost/core/core/frontend/web/site.js
  • ghost/core/package.json
  • ghost/core/test/unit/frontend/helpers/ghost-head.test.js
  • ghost/core/test/unit/frontend/web/middleware/admin-toolbar.test.js
  • ghost/core/test/unit/frontend/web/middleware/frontend-caching.test.js
  • pnpm-workspace.yaml

Comment thread apps/admin-toolbar/package.json
@JohnONolan JohnONolan force-pushed the codex/frontend-admin-toolbar branch 2 times, most recently from 6b49587 to 137cb00 Compare May 22, 2026 03:38
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@ghost/core/package.json`:
- Line 49: Update the package.json scripts to invoke executables through pnpm
instead of calling node or vitest directly: change the "build:assets:js" script
so it uses pnpm to run the minifier (replace the direct "node
bin/minify-assets.js" invocation with a pnpm-based invocation), and likewise
update the scripts that call vitest (referenced in the same file around the
other script entries) to use "pnpm vitest" instead of calling vitest directly;
ensure you modify the script strings that reference build:assets:js and the
vitest-related script names so all executables are run via pnpm per repo policy.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 0c6fe516-52a1-4905-8e87-00ed841738f0

📥 Commits

Reviewing files that changed from the base of the PR and between bcc8983 and 6b49587.

⛔ Files ignored due to path filters (2)
  • apps/admin-toolbar/umd/admin-toolbar.min.js is excluded by !**/*.min.js
  • ghost/core/core/frontend/public/admin-toolbar.min.js is excluded by !**/*.min.js
📒 Files selected for processing (32)
  • apps/admin-toolbar/LICENSE
  • apps/admin-toolbar/README.md
  • apps/admin-toolbar/package.json
  • apps/admin-toolbar/src/actions.js
  • apps/admin-toolbar/src/auth.js
  • apps/admin-toolbar/src/body-offset.js
  • apps/admin-toolbar/src/components.js
  • apps/admin-toolbar/src/config.js
  • apps/admin-toolbar/src/constants.js
  • apps/admin-toolbar/src/icons.js
  • apps/admin-toolbar/src/index.js
  • apps/admin-toolbar/src/links.js
  • apps/admin-toolbar/src/storage.js
  • apps/admin-toolbar/src/styles.js
  • apps/admin-toolbar/src/user.js
  • apps/admin-toolbar/test/admin-toolbar.test.js
  • apps/admin-toolbar/vite.config.mjs
  • apps/admin/src/layout/app-sidebar/nav-main.tsx
  • apps/admin/src/layout/app-sidebar/user-menu.tsx
  • ghost/admin/app/components/gh-site-iframe.js
  • ghost/core/bin/minify-assets.js
  • ghost/core/core/frontend/helpers/ghost_head.js
  • ghost/core/core/frontend/services/staff-frontend-tools/head-scripts.js
  • ghost/core/core/frontend/web/middleware/admin-toolbar.js
  • ghost/core/core/frontend/web/middleware/frontend-caching.js
  • ghost/core/core/frontend/web/middleware/index.js
  • ghost/core/core/frontend/web/routers/serve-public-file.js
  • ghost/core/core/frontend/web/site.js
  • ghost/core/package.json
  • ghost/core/test/unit/frontend/helpers/ghost-head.test.js
  • ghost/core/test/unit/frontend/web/middleware/admin-toolbar.test.js
  • ghost/core/test/unit/frontend/web/middleware/frontend-caching.test.js
✅ Files skipped from review due to trivial changes (1)
  • apps/admin-toolbar/LICENSE

Comment thread ghost/core/package.json Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
apps/admin/src/layout/app-sidebar/user-menu.tsx (1)

16-28: ⚡ Quick win

Extract getAdminToolbarUrl into a shared sidebar utility.

This helper is duplicated in nav-main.tsx and user-menu.tsx; centralizing it avoids divergence in toolbar URL behavior.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/admin/src/layout/app-sidebar/user-menu.tsx` around lines 16 - 28,
Extract the duplicated getAdminToolbarUrl function (currently in user-menu.tsx
and nav-main.tsx) into a single shared utility module (e.g., export function
getAdminToolbarUrl(...) from a new sidebar utility file), update both
user-menu.tsx and nav-main.tsx to import and use that shared function, and
remove the local copies; ensure the new utility preserves the exact try/catch
behavior (returns "" for falsy input, attempts new URL(), sets search param
"admin" to "1", returns href, and falls back to returning the original url on
parse error) and run any relevant linter/tests to confirm no regressions.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/admin-toolbar/src/index.js`:
- Around line 51-53: The await on the iframe load currently can hang forever
because it waits on a Promise created with frame.addEventListener('load',
resolve, {once: true});; modify this to race the load event against a timeout:
create a Promise that either resolves on frame.addEventListener('load', ...) or
rejects/ resolves with an error after a configurable timeout (e.g., 5–10s),
ensure you clean up the event listener and clear the timeout in both paths, and
surface the timeout error so the caller can run fallback/cleanup logic
(referencing the existing frame and the load event listener).

In `@pnpm-workspace.yaml`:
- Line 60: The catalog package currently lists preact as a caret-range
dependency ("preact: ^10.29.2") which violates catalogMode: strict; update the
catalog dependency entry for preact to an exact version (remove the caret) so it
reads the exact release (10.29.2) instead of ^10.29.2; locate the preact entry
under the catalog package in pnpm-workspace.yaml (symbol: catalog.preact) and
replace the version specifier with the exact version.

---

Nitpick comments:
In `@apps/admin/src/layout/app-sidebar/user-menu.tsx`:
- Around line 16-28: Extract the duplicated getAdminToolbarUrl function
(currently in user-menu.tsx and nav-main.tsx) into a single shared utility
module (e.g., export function getAdminToolbarUrl(...) from a new sidebar utility
file), update both user-menu.tsx and nav-main.tsx to import and use that shared
function, and remove the local copies; ensure the new utility preserves the
exact try/catch behavior (returns "" for falsy input, attempts new URL(), sets
search param "admin" to "1", returns href, and falls back to returning the
original url on parse error) and run any relevant linter/tests to confirm no
regressions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 1b5e7c74-4c15-410b-93b1-680614504706

📥 Commits

Reviewing files that changed from the base of the PR and between 6b49587 and 9307271.

⛔ Files ignored due to path filters (3)
  • apps/admin-toolbar/umd/admin-toolbar.min.js is excluded by !**/*.min.js
  • ghost/core/core/frontend/public/admin-toolbar.min.js is excluded by !**/*.min.js
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (33)
  • apps/admin-toolbar/LICENSE
  • apps/admin-toolbar/README.md
  • apps/admin-toolbar/package.json
  • apps/admin-toolbar/src/actions.js
  • apps/admin-toolbar/src/auth.js
  • apps/admin-toolbar/src/body-offset.js
  • apps/admin-toolbar/src/components.js
  • apps/admin-toolbar/src/config.js
  • apps/admin-toolbar/src/constants.js
  • apps/admin-toolbar/src/icons.js
  • apps/admin-toolbar/src/index.js
  • apps/admin-toolbar/src/links.js
  • apps/admin-toolbar/src/storage.js
  • apps/admin-toolbar/src/styles.js
  • apps/admin-toolbar/src/user.js
  • apps/admin-toolbar/test/admin-toolbar.test.js
  • apps/admin-toolbar/vite.config.mjs
  • apps/admin/src/layout/app-sidebar/nav-main.tsx
  • apps/admin/src/layout/app-sidebar/user-menu.tsx
  • ghost/admin/app/components/gh-site-iframe.js
  • ghost/core/bin/minify-assets.js
  • ghost/core/core/frontend/helpers/ghost_head.js
  • ghost/core/core/frontend/services/staff-frontend-tools/head-scripts.js
  • ghost/core/core/frontend/web/middleware/admin-toolbar.js
  • ghost/core/core/frontend/web/middleware/frontend-caching.js
  • ghost/core/core/frontend/web/middleware/index.js
  • ghost/core/core/frontend/web/routers/serve-public-file.js
  • ghost/core/core/frontend/web/site.js
  • ghost/core/package.json
  • ghost/core/test/unit/frontend/helpers/ghost-head.test.js
  • ghost/core/test/unit/frontend/web/middleware/admin-toolbar.test.js
  • ghost/core/test/unit/frontend/web/middleware/frontend-caching.test.js
  • pnpm-workspace.yaml
✅ Files skipped from review due to trivial changes (2)
  • apps/admin-toolbar/LICENSE
  • apps/admin-toolbar/README.md

Comment thread apps/admin-toolbar/src/index.js Outdated
Comment thread pnpm-workspace.yaml
@JohnONolan JohnONolan force-pushed the codex/frontend-admin-toolbar branch from 9307271 to bc3c09d Compare May 22, 2026 03:56
@codecov

This comment was marked as outdated.

@JohnONolan JohnONolan force-pushed the codex/frontend-admin-toolbar branch 2 times, most recently from b660fb5 to cc21788 Compare May 22, 2026 04:37
@ErisDS
Copy link
Copy Markdown
Member

ErisDS commented May 27, 2026

  • Use standard CDN serving pattern for admin toolbar. The admin toolbar uses a copy step in minify-assets.js and a local static file route in serve-public-file.js, unlike every other public app (portal, comments-ui, sodo-search, announcement-bar, signup-form) which use getFrontendAppConfig with a jsDelivr CDN URL from defaults.json. This means two copies of the build artifact exist (one committed, one built) and the serving path diverges from the established pattern. Switched to getFrontendAppConfig('adminToolbar') with a CDN entry in defaults.json, removed the copy step and static route. (689552ecef)

  • Suppress admin toolbar in theme customisation preview. theme-preview.tsx fetches the site URL with credentials: 'include' and mode: 'cors'. Because sec-fetch-dest is empty (not iframe), the toolbar middleware's iframe suppression doesn't apply. Added ?admin_toolbar=0 to all preview URLs (theme, announcement bar, portal, offers) and added a matching client-side check in the toolbar init. (63ddba2cea, c9e1913f22)

  • Extract duplicated getAdminToolbarUrl helper. Resolved by the CDN pattern switch — the URL is now constructed in one place via getFrontendAppConfig('adminToolbar') in head-scripts.js. (689552ecef)

  • Wire up clearBodyOffset for client-side toolbar hide. Investigated: the hide flow uses ?admin=0 which triggers a full page navigation (middleware clears cookie + redirects), making client-side cleanup unnecessary. clearBodyOffset is an intentional API counterpart to applyBodyOffset, not dead code.

  • Document Preact dependency choice. Updated README with rationale (3KB vs 40KB for a lightweight public widget) and corrected the serving documentation to reflect the CDN pattern. (0bbf4b52f1)

  • Add test for implicit commentsEnabled default. Added 12 tests covering getAdminToolbarAttributes: resource type detection, context-dependent home-only attributes, and the implicit comments-enabled default. (002515536d)

Suggestions

  • Consider parallelising the auth frame load and auth token request. Currently AUTH_FRAME_LOAD_TIMEOUT (5s) and AUTH_TIMEOUT (2s) are sequential, giving a 7s worst case before the toolbar shows unauthenticated state. For v1 this is probably fine, but if toolbar load time becomes a concern, the iframe could start loading earlier.
  • The cookie-based activation (?admin=1 sets an HMAC-signed marker cookie) means the toolbar persists across sessions until the cookie expires. Consider whether there should be a way to deactivate it from the toolbar UI without requiring a manual cookie clear or ?admin=0 URL parameter.

@ErisDS ErisDS force-pushed the codex/frontend-admin-toolbar branch 2 times, most recently from 7d8c89e to f47d9b4 Compare May 27, 2026 16:58
JohnONolan and others added 11 commits May 28, 2026 07:08
Adds a staff-only frontend toolbar that can be enabled from Admin view-site links while keeping public HTML cacheable for normal visitors.

The toolbar is built as its own frontend package so Ghost core consumes a built UMD artifact rather than package internals, and staff frontend script injection is isolated behind a small core boundary.
Updates the new admin toolbar package scripts to invoke workspace binaries through pnpm, matching repository conventions.
Regenerates the new admin toolbar package lockfile entry against current main so frozen CI installs resolve the Vite peer set correctly.
Uses pnpm to invoke the core asset minifier so the new admin toolbar build path follows workspace script conventions.
Use getFrontendAppConfig with a jsDelivr URL like all other public apps
(portal, comments-ui, sodo-search) instead of a custom copy-into-core
pipeline. Removes the local serve route, minify-assets copy step, and
committed build artifact from ghost/core.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The theme customisation, announcement bar, portal, and offer preview
panels all fetch site content that could include the admin toolbar
script. Added admin_toolbar=0 to suppress the toolbar in all previews.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Covers resource type detection, context-dependent attributes, and the
implicit comments-enabled default.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The middleware already suppresses the toolbar server-side when
?admin_toolbar=0 is in the URL. This adds the same check client-side
so the toolbar does not render even if the script was injected from cache.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The admin_toolbar=0 suppression param added to preview URLs caused
Playwright route matching to fail because page.route used an exact
URL match. Changed to a glob pattern so extra query params are
allowed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@ErisDS ErisDS force-pushed the codex/frontend-admin-toolbar branch from f47d9b4 to 54e15dc Compare May 28, 2026 06:11
ErisDS and others added 3 commits May 28, 2026 07:23
Deduplicated the getAdminToolbarUrl function from nav-main.tsx and
user-menu.tsx into a shared utility module.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Removed the separate staff-frontend-tools service directory and inlined
the admin toolbar script assembly into ghost_head.js, matching the
pattern used by portal, search, and announcement-bar. Also added the
missing crossorigin="anonymous" attribute for CDN consistency.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@ErisDS ErisDS merged commit 8bdc9fe into main May 28, 2026
54 checks passed
@ErisDS ErisDS deleted the codex/frontend-admin-toolbar branch May 28, 2026 08:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants