Skip to content

feat(integrations): URL-anchored filters#947

Merged
vfanelle merged 6 commits intomainfrom
vfanelle/integrations-url-anchored-filters
May 1, 2026
Merged

feat(integrations): URL-anchored filters#947
vfanelle merged 6 commits intomainfrom
vfanelle/integrations-url-anchored-filters

Conversation

@vfanelle
Copy link
Copy Markdown
Contributor

@vfanelle vfanelle commented Apr 24, 2026

Preview: https://docs-git-vfanelle-integrations-url-anchored-filters-arcade-ai.vercel.app/en/resources/glossary#pro-tool-executions

URL query params are now the source of truth for the integrations page filters. A filtered view can be copied from the address bar and shared — paste the URL anywhere and the recipient sees the same filtered list of MCP servers. The glossary's Pro Tool Executions and BYOC sections link directly to these views.

Link structures

What you want to see URL
Pro tools only /en/resources/integrations?label=pro#list
BYOC-eligible tools only /en/resources/integrations?label=byoc#list
Tools that are both Pro and BYOC /en/resources/integrations?label=pro&label=byoc#list
All MCP servers (no filters) /en/resources/integrations

The #list anchor scrolls past the page header straight to the tool list.

Made with Cursor

@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 24, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
docs Ready Ready Preview, Comment May 1, 2026 9:22pm

Request Review

@vfanelle vfanelle force-pushed the vfanelle/integrations-url-anchored-filters branch from 29f96b5 to bc9b4d2 Compare April 24, 2026 23:50
Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

Style Review

Found 4 style suggestion(s).

Powered by Vale + Claude

Comment thread app/en/resources/glossary/page.mdx Outdated
### Standard and Pro Tool Executions

Arcade tools are divided into 2 categories: Standard and Pro. While all tools have some cost for Arcade to run, Pro tools are significantly more costly - either due to infrastructure costs, the complexity of the tool, or a cost imposed by the provider of the tool. Pro tools cost more to execute and have different limits.
Arcade tools are divided into 2 categories: Standard and Pro. While all tools have some cost for Arcade to run, Pro tools are significantly more costly either due to infrastructure costs, the complexity of the tool, or a cost imposed by the provider of the tool. Pro tools cost more to execute and have different limits.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

write-good.Weasel: Remove weasel word 'significantly' and fix em-dash spacing

Suggested change
Arcade tools are divided into 2 categories: Standard and Pro. While all tools have some cost for Arcade to run, Pro tools are significantly more costlyeither due to infrastructure costs, the complexity of the tool, or a cost imposed by the provider of the tool. Pro tools cost more to execute and have different limits.
Arcade tools are divided into 2 categories: Standard and Pro. While all tools have some cost for Arcade to run, Pro tools are more costlyeither due to infrastructure costs, the complexity of the tool, or a cost imposed by the provider of the tool. Pro tools cost more to execute and have different limits.

Comment thread app/en/resources/glossary/page.mdx Outdated

#### Pro Tool Executions

Pro tools incur materially higher operational cost than Standard tools due to underlying infrastructure (e.g., compute-intensive sandboxes), provider-imposed fees (e.g., per-call API charges from data providers), or tool complexity. Each invocation of a Pro tool counts as one Pro Tool Execution against your plan's monthly Pro allowance, with any overage billed per execution at the Pro rate listed on the [pricing page](https://www.arcade.dev/pricing). Arcade may reclassify tools between Standard and Pro from time to time as the underlying cost structure of a tool changes; any such reclassification applies prospectively.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Google.Latin: Replace 'e.g.' with 'for example' in both instances

Suggested change
Pro tools incur materially higher operational cost than Standard tools due to underlying infrastructure (e.g., compute-intensive sandboxes), provider-imposed fees (e.g., per-call API charges from data providers), or tool complexity. Each invocation of a Pro tool counts as one Pro Tool Execution against your plan's monthly Pro allowance, with any overage billed per execution at the Pro rate listed on the [pricing page](https://www.arcade.dev/pricing). Arcade may reclassify tools between Standard and Pro from time to time as the underlying cost structure of a tool changes; any such reclassification applies prospectively.
Pro tools incur materially higher operational cost than Standard tools due to underlying infrastructure (for example, compute-intensive sandboxes), provider-imposed fees (for example, per-call API charges from data providers), or tool complexity. Each invocation of a Pro tool counts as one Pro Tool Execution against your plan's monthly Pro allowance, with any overage billed per execution at the Pro rate listed on the [pricing page](https://www.arcade.dev/pricing). Arcade may reclassify tools between Standard and Pro from time to time as the underlying cost structure of a tool changes; any such reclassification applies prospectively.

Comment thread app/en/resources/glossary/page.mdx Outdated
### Bring Your Own Credentials (BYOC)

Bring Your Own Credentials (BYOC) is a feature that allows you to use your own credentials to certain pro tools. This changes the cost of the tool execution, as you will be charged directly by the provider of the tool, rather than relying on Arcade to pay the bill for you.
Bring Your Own Credentials (BYOC) is a feature that allows you to use your own credentials to access Pro tools. This changes the cost of the tool execution, as you will be charged directly by the provider of the tool, rather than relying on Arcade to pay the bill for you. In exchange, the tool execution will be billed at the Standard rate. As of 04/26/2026, most credentials required for Pro tools are API Keys specific to the service being accessed.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Google.DateFormat: Change '04/26/2026' to proper date format 'April 26, 2026'

Suggested change
Bring Your Own Credentials (BYOC) is a feature that allows you to use your own credentials to access Pro tools. This changes the cost of the tool execution, as you will be charged directly by the provider of the tool, rather than relying on Arcade to pay the bill for you. In exchange, the tool execution will be billed at the Standard rate. As of 04/26/2026, most credentials required for Pro tools are API Keys specific to the service being accessed.
Bring Your Own Credentials (BYOC) is a feature that allows you to use your own credentials to access Pro tools. This changes the cost of the tool execution, as you will be charged directly by the provider of the tool, rather than relying on Arcade to pay the bill for you. In exchange, the tool execution will be billed at the Standard rate. As of April 26, 2026, most credentials required for Pro tools are API Keys specific to the service being accessed.

Comment thread app/en/resources/glossary/page.mdx Outdated
Bring Your Own Credentials (BYOC) is a feature that allows you to use your own credentials to access Pro tools. This changes the cost of the tool execution, as you will be charged directly by the provider of the tool, rather than relying on Arcade to pay the bill for you. In exchange, the tool execution will be billed at the Standard rate. As of 04/26/2026, most credentials required for Pro tools are API Keys specific to the service being accessed.

To set your own credentials, set the requisite secret within the Arcade Dashboard, overwriting the default 'static' credentials.
To set your own credentials, set the requisite secret(s) within the Arcade Dashboard Secrets page, overwriting the default 'static' credentials. You can also set the secrets using the Arcade CLI.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Google.OptionalPlurals: Remove (s) from secret(s)

Suggested change
To set your own credentials, set the requisite secret(s) within the Arcade Dashboard Secrets page, overwriting the default 'static' credentials. You can also set the secrets using the Arcade CLI.
To set your own credentials, set the requisite secret within the Arcade Dashboard Secrets page, overwriting the default 'static' credentials. You can also set the secrets using the Arcade CLI.

Valerie Fanelle added 4 commits April 24, 2026 17:24
Sync the integrations page filter state to URL query params so filtered
views can be linked, bookmarked, and shared.

- Add use-url-filter-sync hook: two-way sync between Zustand store and
  URL via replaceState (no full navigation or scroll jump)
- On mount: read params and apply filters before first paint
- On popstate (back/forward): re-sync filters from URL
- On filter change: update URL in same render cycle
- Unknown/malformed params ignored gracefully
- Clearing all filters strips the query string entirely
- Add 21 Vitest tests for param parsing, serialization, and round-trips

Supported params: category, type, pro, byoc, q
Example: /integrations?pro=1&byoc=1

Made-with: Cursor
Swap the hardcoded "As of 04/24" Pro tools list for a link to the
integrations page filtered by Pro (/integrations?pro=1).

Made-with: Cursor
- Add link to BYOC-eligible tools (/integrations?byoc=1) in the BYOC
  glossary definition
- Set isPro: true for Granola and Bright Data toolkits

Made-with: Cursor
These toolkits are BYOC-only (user supplies their own API key), so they
should not be marked Pro.

Made-with: Cursor
Copy link
Copy Markdown
Contributor

@teallarson teallarson left a comment

Choose a reason for hiding this comment

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

I love the move to search params! This can be simpler, though.

The main thing I’d avoid is having two sources of truth: Zustand filter state and URL params, then syncing them through a global store subscription, mount hydration, replaceState, and a manual popstate listener. Could we make the URL/search params the source of truth instead, and have filter handlers write params directly? That should remove most of useUrlFilterSync. For read, use useSearchParams()! For writing, since the filtering is entirely client-side and doesn’t need a server navigation/refetch, the native History API seems reasonable. Next documents that pushState / replaceState integrate with useSearchParams and usePathname.

A few specific edge cases in the current version:

  • The PR says URL params are applied before first paint, but this uses useEffect, so they apply after paint/hydration.
  • Filter changes use replaceState, so back/forward will not step through filter changes. If that behavior matters, this should use pushState; if it doesn’t, the PR description/test plan should not claim it.
  • Landing on /integrations with no query params does not reset a previously populated global Zustand store.
    category is not validated, so ?category=bogus can create invalid filter state.
  • Boolean parsing is loose: ?pro=bogus currently counts as truthy, even though malformed params are meant to be ignored.

There are also some typing issues that point in the same direction. VALID_TYPES is a Set, then the parser recovers with as ToolkitType; and SerializableFilterState.selectedType is just string, so invalid values can be serialized without TypeScript noticing. I’d rather share the actual filter value shape, e.g. selectedType: ToolkitType | "all", use a real type guard for toolkit types, and validate categories if category is URL-addressable.

Minor test-structure nit: the tests import pure parse/serialize helpers from a "use client" hook module. It may be cleaner to split those helpers into a non-client module and keep the hook/component layer separate.

Address review feedback by making URL query params the single source of
truth for the integrations page filters and simplifying the URL shape.

- Remove the Zustand filter store and the use-url-filter-sync hook;
  replace them with a useFilters() hook that reads via
  useSearchParams() and writes via window.history.pushState
  (replaceState for the search input). Back/forward now steps through
  filter changes.

- Switch the URL shape from `?pro=1&byoc=1` to a multi-value
  `?label=pro&label=byoc`. Add an isLabel type guard; unknown labels
  are silently ignored.

- Move parse/serialize/type-guard helpers into a new pure
  filter-params module (no "use client"). Validate categories and
  toolkit types via real type guards instead of `as` casts. Tests
  now import from the pure module.

- Anchor the filters bar + tool grid at `#list` and point the
  glossary's Pro Tools / BYOC links there so users land pre-filtered
  and scrolled to the list.

- Wrap ToolkitsClient in Suspense, required by useSearchParams() on
  a statically prerendered route.

- Apply Vale style fixes to the Pro / BYOC glossary copy: drop weasel
  "significantly", replace `e.g.,` with `for example,`, drop `(s)`
  from `secret(s)`.

Made-with: Cursor
…-url-anchored-filters

Co-authored-by: Cursor <cursoragent@cursor.com>

# Conflicts:
#	app/en/resources/integrations/components/toolkits.tsx
#	app/en/resources/integrations/components/use-toolkit-filters.ts
Copy link
Copy Markdown
Contributor

@teallarson teallarson left a comment

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

There's a risk here that if the design system removes a category this will break, or if the design system adds a category, it won't get added here.

We could use: const TOOLKIT_TYPES = Object.keys(TYPE_CONFIG) as ToolkitType[]; and const TOOLKIT_CATEGORIES = CATEGORIES.map((c) => c.id) as ToolkitCategory[];

I don't know that it's worth blocking on as I don't think these change often.

@vfanelle vfanelle merged commit 2db1069 into main May 1, 2026
8 checks passed
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