Skip to content

feat: Host-injected dashboard nav items, filtered by user permission - #2701

Open
camielvs wants to merge 1 commit into
masterfrom
add-host-injected-nav-items
Open

feat: Host-injected dashboard nav items, filtered by user permission#2701
camielvs wants to merge 1 commit into
masterfrom
add-host-injected-nav-items

Conversation

@camielvs

@camielvs camielvs commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator

Description

Adds a window.__TANGLE_EXTRA_NAV_ITEMS__ config contract so a deployment can add its own links to the dashboard sidebar without forking DashboardLayout. It sits alongside the existing injection points (__TANGLE_AI_MODELS__, __TANGLE_EXTRA_FLAGS__, __TANGLE_ANNOUNCEMENTS__).

Items render in the utility block directly under Settings. An item may declare requiresPermission; it is then shown only to users whose /api/users/me permissions include that string — reusing the same permissions array that already gates the Hugging Face auth button and run actions.

window.__TANGLE_EXTRA_NAV_ITEMS__ = [
  { label: "Admin", href: "/admin/", icon: "ShieldCheck", requiresPermission: "admin" },
];

Injected config is validated before use, following the aiModels.ts reader pattern: items without a usable label or href are dropped, an icon that isn't in the Lucide set is dropped (rather than crashing the sidebar), and hrefs are restricted to same-origin paths or http(s) URLs so a host assembling this config from a less-trusted source can't turn a nav item into a javascript: sink.

Two notes for reviewers:

  • The permission filter is presentation only. Whatever an item links to has to enforce its own access control — nothing here is a security boundary.
  • ExtraNavItems uses useQuery(userQueryOptions) rather than the useUserDetails() wrapper, because that wrapper is useSuspenseQuery and would suspend the whole dashboard shell on first paint. The item appears when /api/users/me resolves; the rest of the sidebar never waits on it.

Related Issue and Pull requests

Consumed by a matching Shopify-side overlay change that surfaces an admin dashboard link.

Type of Change

  • New feature

Checklist

  • I have tested this does not break current pipelines / runs functionality
  • I have tested the changes on staging

Screenshots (if applicable)

Verified locally with the config above injected and /api/users/me returning ["read", "write", "admin"] — "Admin" renders under Settings with the same styling as Docs/Settings, links to /admin/, and gets no target="_blank" since it is same-origin. With ["read", "write"] the item is absent.

Test Instructions

  1. pnpm start, then in the devtools console before load (or via an index.html script block) set window.__TANGLE_EXTRA_NAV_ITEMS__ as above.
  2. With a backend that grants your user admin, the item shows under Settings; without it, the item is hidden.
  3. pnpm vitest run src/config/extraNavItems.test.ts src/routes/Dashboard/ExtraNavItems.test.tsx

Additional Comments

pnpm validate and the full pnpm test suite (215 files, 2260 tests) pass locally.

Adds a `window.__TANGLE_EXTRA_NAV_ITEMS__` config contract, alongside the
existing `__TANGLE_AI_MODELS__` / `__TANGLE_EXTRA_FLAGS__` ones, so a
deployment can add its own links to the dashboard sidebar without forking
the layout. Items render under Settings; an item may declare
`requiresPermission`, in which case it is only shown to users whose
`/api/users/me` permissions include it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@camielvs
camielvs requested a review from a team as a code owner September 3, 2026 17:27
@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown

🎩 Preview

A preview build has been created at: add-host-injected-nav-items/e285a6e

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.

1 participant