Files
PaperClipAI/ui
DottaandClaude Opus 5.5 19239c11d1 fix(onboarding): move Use a custom gateway under Advanced on the API key step (#19510)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - New users connect a model in the onboarding wizard's "Connect a
model" step.
> - On the Claude API and Codex API paths, the step shows an API key
card.
> - The "Use a custom gateway" button sat directly under the key field,
inside that card, with no gap.
> - A tester reported that it hugs the field and that it belongs under
Advanced.
> - A custom gateway is an alternative route, not the next step after
the key.
> - This pull request moves the button into the step's existing Advanced
disclosure.
> - The benefit is a cleaner key card, and the gateway route stays one
click away.

## Linked Issues or Issue Description

No public issue exists. A manual new-user onboarding test on a staging
cloud workspace found this bug. Related: #17253 added the custom gateway
route.

**What happened?**
On the onboarding "Connect a model" step, API key path (Claude API and
Codex/OpenAI API), the "Use a custom gateway" button is shown at the top
level, directly against the API key text field.

**Steps to reproduce**
1. Start onboarding and reach "Connect a model".
2. Choose "Use API key instead", then pick Claude (or OpenAI).
3. See "Use a custom gateway" directly under the "Enter API key here"
field.

**Expected behavior**
The custom gateway control is in the Advanced section of the step. It is
hidden until Advanced is opened.

Source: manual new-user onboarding test on Paperclip Cloud staging (item
N-16, P3, Claude API path).

## What Changed

- `ui/src/components/OnboardingWizard.tsx`: render
`OnboardingGatewaySetup` inside the connect step's existing `Advanced`
`<details>` (above the runner select), not inside the API key card. It
keeps the same gates as the card it left: the card is live and mounted,
no connect progress, API credential mode, a created company, and a
Claude or Codex adapter.
- `ui/src/components/onboarding/OnboardingGatewaySetup.tsx`: accept an
optional `className`. The wizard passes `-ml-3` so the ghost button's
label lines up with the Advanced summary.
- The gateway dialog and its save/select-model/connect flow are
unchanged.
- `ui/src/components/OnboardingWizard.test.tsx`: new test for the Claude
API and Codex API paths. It asserts the button is in a closed `Advanced`
disclosure, outside the key field's card, and that the gateway dialog
opens after Advanced is expanded.

## Verification

Red on unchanged source (`npx vitest run
src/components/OnboardingWizard.test.tsx -t "custom gateway"`):

```
 ❯ src/components/OnboardingWizard.test.tsx (212 tests | 2 failed | 208 skipped)
       × keeps Use a custom gateway in the closed Advanced disclosure on the Claude API key step
       × keeps Use a custom gateway in the closed Advanced disclosure on the Codex API key step
AssertionError: Use a custom gateway should live inside the Advanced disclosure: expected null to be truthy
 Test Files  1 failed (1)
      Tests  2 failed | 2 passed | 208 skipped (212)
```

Green after the fix (same command):

```
 Test Files  1 passed (1)
      Tests  4 passed | 208 skipped (212)
```

Neighbouring suites (`OnboardingWizard.test.tsx`,
`ai-connections/AiProviderSetup.test.tsx`, `components/onboarding/*`),
including the existing end-to-end custom gateway save/test/hire test:

```
 Test Files  8 passed (8)
      Tests  270 passed (270)
```

- `pnpm check:token-gates`: all gates clean.
- `tsc --noEmit` for `ui`: no new errors. The only errors are the
existing unbuilt `@paperclipai/plugin-sdk/ui` import in
`PluginOrganizationSwitcher`.

Screenshots (Storybook `Onboarding/Agent arc › Connect · Claude API
key`):

| Before (master) | After (Advanced closed) | After (Advanced open) |
| --- | --- | --- |
|
![before](https://raw.githubusercontent.com/paperclipai/paperclip/1dae9c09f9a4070c66cd313dbb64baf1636c54d0/n16-before.jpg)
| ![after
collapsed](https://raw.githubusercontent.com/paperclipai/paperclip/1dae9c09f9a4070c66cd313dbb64baf1636c54d0/n16-after-collapsed.jpg)
| ![after
expanded](https://raw.githubusercontent.com/paperclipai/paperclip/1dae9c09f9a4070c66cd313dbb64baf1636c54d0/n16-after-expanded.jpg)
|

The red "This item doesn't exist or was moved." line in the screenshots
comes from the story's runner fixture. It is present on master too and
is not related.

## Risks

- Low risk. This is a layout move of one control. The gateway flow and
its gates are unchanged.
- The control is now one click deeper. This is the intended outcome of
the report.
- After a gateway is saved, "Use a different API key" stays in the card,
so a user can still leave the gateway route without opening Advanced.

## Model Used

- Claude Opus 5.5 (`claude-opus-5-5`), Anthropic, via Claude Code with
tool use (shell, file edits, browser for Storybook screenshots).

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` / `Closes
#` / `Refs #` OR (b) described the issue in-PR following the relevant
issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 11:42:21 -06:00
..
…

@paperclipai/ui

Published static assets for the Paperclip board UI.

What gets published

The npm package contains the production build under dist/. It does not ship the UI source tree or workspace-only dependencies.

Storybook

Storybook config, stories, and fixtures live under ui/storybook/.

pnpm --filter @paperclipai/ui storybook
pnpm --filter @paperclipai/ui build-storybook

Typical use

Install the package, then serve or copy the built files from node_modules/@paperclipai/ui/dist.

Editor dependency identity

Keep the root and workspace overrides for @codemirror/state, @codemirror/view, and @lezer/common aligned. CodeMirror requires shared extension identity, while Lezer parsers and syntax highlighters require shared NodeProp IDs. Multiple Lezer copies can crash code-block highlighting with tags is not iterable. src/lib/codemirror-single-instance.test.ts checks the installed dependency graph and highlights sample code through the editor's real language dependencies. GitHub Actions owns regeneration of pnpm-lock.yaml.