Skip to content

fix: move apex recoupable.com → recoupable.dev (chat Website + legal redirects)#1825

Merged
sweetmantech merged 1 commit into
testfrom
fix/apex-dot-dev
Jun 30, 2026
Merged

fix: move apex recoupable.com → recoupable.dev (chat Website + legal redirects)#1825
sweetmantech merged 1 commit into
testfrom
fix/apex-dot-dev

Conversation

@sweetmantech

@sweetmantech sweetmantech commented Jun 30, 2026

Copy link
Copy Markdown
Collaborator

Part of the recoupable.com → recoupable.dev apex migration. Tracking issue: #1819.

recoupable.dev is live (200). This PR is mergeable on its own — all targets are verified live.

Changes

  • components/Sidebar/UserProfileDropdown/ExternalLinksGroup.tsx — Website link href and visible label recoupable.comrecoupable.dev.
  • app/privacy/page.tsx — redirect https://www.recoupable.com/privacy-policyhttps://recoupable.dev/privacy-policy (verified 200).
  • app/terms/page.tsx — redirect https://www.recoupable.com/terms-of-servicehttps://recoupable.dev/terms-of-use. Note the path changed from terms-of-service to terms-of-use (recoupable.dev/terms-of-service is 404; /terms-of-use is 200).

Gate

pnpm exec tsc --noEmit — clean except the pre-existing lib/emails/__tests__/extractSendEmailResults.test.ts UIMessage content errors (unrelated to this change). No new errors in the touched files.

Refs #1819

🤖 Generated with Claude Code


Summary by cubic

Switch the app to the new apex domain recoupable.dev. Updates the user menu link and legal redirects to point to live pages.

Written for commit 40ced00. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • Bug Fixes
    • Updated site links to point to the new recoupable.dev domain.
    • Redirects for the Privacy and Terms pages now go to the correct policy pages on the updated domain.
    • The user profile dropdown’s external link now opens the updated site address.

…redirects)

Update the Website link in the user profile dropdown and the privacy/terms
redirects from recoupable.com to the live recoupable.dev apex.

- ExternalLinksGroup: Website href + label → recoupable.dev
- /privacy → https://recoupable.dev/privacy-policy
- /terms → https://recoupable.dev/terms-of-use (path renamed from terms-of-service)

Refs #1819

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

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

Project Deployment Actions Updated (UTC)
chat Ready Ready Preview Jun 30, 2026 12:23am

Request Review

@coderabbitai

coderabbitai Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: d0954115-9e4c-42a3-8435-f3664654f133

📥 Commits

Reviewing files that changed from the base of the PR and between b0d4798 and 40ced00.

📒 Files selected for processing (3)
  • app/privacy/page.tsx
  • app/terms/page.tsx
  • components/Sidebar/UserProfileDropdown/ExternalLinksGroup.tsx

📝 Walkthrough

Walkthrough

Three hardcoded URLs are updated from recoupable.com to recoupable.dev: the privacy page redirect target changes to /privacy-policy, the terms page redirect changes to /terms-of-use, and the sidebar external link href and label are updated accordingly.

Changes

Domain URL Migration

Layer / File(s) Summary
Redirect and external link URL updates
app/privacy/page.tsx, app/terms/page.tsx, components/Sidebar/UserProfileDropdown/ExternalLinksGroup.tsx
Privacy redirect now targets https://recoupable.dev/privacy-policy, terms redirect targets https://recoupable.dev/terms-of-use, and the sidebar external anchor href and label updated to https://recoupable.dev.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~2 minutes

Poem

🌐 From .com to .dev we go,
Three little URLs in a row,
Privacy, Terms, and a sidebar link,
Swapped in a blink — no need to think.
Clean domains, clean code, clean show! ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
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.
Solid & Clean Code ✅ Passed Touched functions are tiny, single-purpose redirects/links; no new abstraction, nesting, or duplication beyond the migration URLs.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/apex-dot-dev

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

No issues found across 3 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Auto-approved: Updates the apex domain from recoupable.com to recoupable.dev across a UI link and two legal redirects. All changes are simple string replacements; no logic or behavior change.

Re-trigger cubic

@sweetmantech sweetmantech merged commit b305bc3 into test Jun 30, 2026
4 checks passed
sweetmantech added a commit that referenced this pull request Jun 30, 2026
* refactor(chat): update chat components to use chatId instead of roomId (#1765)

* refactor(chat): update chat components to use chatId instead of roomId

This commit removes the InstantChatRoom component and updates various hooks and components to replace references of roomId with chatId. The changes ensure that chat functionality is aligned with the new session-scoped architecture, improving consistency across the chat system. Additionally, the sessionId is now required in several components to streamline the chat transport process.

* refactor(chat): integrate sessionId and update chat path utilities

This commit enhances the chat components by introducing the `sessionId` in various hooks and updating the URL handling to utilize new utility functions for generating chat paths. The changes improve the consistency and maintainability of chat navigation, ensuring that the application correctly reflects the session-scoped architecture.

* fix(chat): ensure newRoomId is treated as a string in URL handling

This commit updates the `useCreateArtistTool` hook to explicitly cast `result.newRoomId` to a string when generating the chat path. This change prevents potential type-related issues and ensures consistent URL formatting. Additionally, it adds an import statement for testing utilities in the chat paths test file, enhancing test coverage and maintainability.

* refactor(Header, OrganizationProvider): remove usePathname and replace with window.location.pathname

This commit removes the usePathname hook from both Artist.tsx and OrganizationProvider.tsx, replacing it with direct access to window.location.pathname. This change simplifies the code and maintains the intended navigation behavior without relying on Next.js's router for pathname management.

* refactor(chat): split chatPaths per SRP, drop dead legacy branch, simplify useParams

- Remove dead `/chat/` branch from isActiveChatRoomPath — this PR makes
  /chat/{id} 404, so treating it as an active chat room contradicted the
  PR's own intent and could never fire in production.
- Split lib/chat/chatPaths.ts into one-function-per-file (getChatPath,
  getChatUrl, isActiveChatRoomPath) per repo SRP convention; mirror tests.
- Simplify useVercelChat to `const { chatId } = useParams<{ chatId?: string }>()`
  (KISS), consistent with chat.tsx.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Sweets Sweetman <sweetmantech@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(chat): defer new-chat bootstrap wait from spinner to send button (#1767) (#1774)

* feat(chat): defer new-chat bootstrap wait from spinner to send button (#1767)

New chats landing on `/` or `/chat` blocked the whole view on a
full-screen spinner while `POST /api/sessions` + `POST /api/sandbox`
resolved (~12s cold, dominated by sandbox provisioning). Render `<Chat>`
immediately with a typeable input instead and provision in parallel; the
Send button stays disabled with a "Preparing your workspace…" cue until
the api-minted `sessionId` + `chatId` land, so the workflow transport
never fires without the ids its validator requires.

- NewChatBootstrap: render <Chat> eagerly with a stable placeholder chat
  id (survives the preparing → ready transition); drop the spinner.
- Thread `sessionId?`, `workflowChatId`, `isBootstrapPreparing` through
  Chat → VercelChatProvider → useVercelChat (provider kept inline).
- useVercelChat: `transportChatId = workflowChatId ?? id` drives the
  transport, optimistic conversation, and URL; only load persisted
  history on a canonical route so no spinner flashes over the input
  during the ready transition.
- ChatInput: gate Send on `isBootstrapPreparing`; input stays typeable.
- useChatTransport / useMessageLoader: sessionId optional + guard.
- useCreateArtistTool: guard the one context sessionId consumer.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(chat): send live sessionId/chatId from workflow transport (#1767)

The new-chat flow mounts <Chat> (and useChat) during provisioning with
sessionId undefined + a placeholder chatId. useChat captures the transport
from that mount render and does not swap to the rebuilt instance when the
ids later resolve — so the first send POSTed `sessionId: undefined` to
/api/chat/workflow and got a 400 (the URL rewrote correctly because it
reads the live prop, not the transport).

Read the ids from refs inside transport.body() so a single stable
transport instance always sends the values current as of the request,
regardless of useChat's stale capture. Removed chatId/sessionId from the
memo deps since rebuilding the instance never helped.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(chat): replace preparing-text cue with a workspace status dot (#1767)

Swap the flashing "Preparing your workspace…" toolbar text for a
stoplight status dot in the top-right of the chat input: red = off
(provisioning failed / unavailable), yellow = provisioning, green =
ready. Hover shows context via the shadcn tooltip.

- New `WorkspaceStatusIndicator` component in its own file (SRP) — a pure
  display component driven by a `status` prop, built on the existing
  shadcn-based `common/Tooltip`, so it's open for reuse without change.
- Thread `workspaceStatus: "off" | "provisioning" | "ready"` through
  Chat → VercelChatProvider → context (replacing the `isBootstrapPreparing`
  boolean); Send is gated while it's not `ready`.
- NewChatBootstrap now derives the status and renders `<Chat>` even on a
  provisioning error (red dot + disabled Send, input still visible)
  instead of swapping in a full-screen error view.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* chore(chat): simplify provisioning tooltip copy (#1767)

Shorten the yellow/provisioning workspace-status tooltip to
"Preparing your workspace".

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(chat): drop legacy GET /api/chats/{id}/artist caller (#1767) (#1768)

* fix(chat): drop legacy GET /api/chats/{id}/artist caller (#1767)

* fix(chat): reactive conversations cache + user-scoped session query

* refactor(chat): drop dead /chat/:id artist cache fallback (post-#1765)

The conversations-cache fallback in useArtistFromChat only existed for the
legacy /chat/:id deep link (chatId but no sessionId). That route was
removed in #1765 — every chat is now reached via the canonical
/sessions/{sessionId}/chats/{chatId} URL, so sessionId is always present.

Reduce to the session path: GET /api/sessions/{sessionId} -> session.artistId
-> select. Removes useSyncExternalStore reactive-cache machinery,
findArtistIdInConversationsCache (+ its test), and the unused chatId param.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* refactor(chat): validate getSessionById response with zod (PR #1768 review)

Replace type-casting with boundary zod validation, matching the
getConversations convention. Drops the `as GetSessionByIdResponse`/
`as GetSessionByIdErrorResponse` casts in favor of safeParse/parse.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* refactor(chat): extract shared safeJsonParse into lib/api (PR #1768 review)

Replace the locally-defined safeJsonParse in getSessionById with a
shared helper in lib/api/, alongside the other HTTP helpers. DRY/SRP.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Sweets Sweetman <sweetmantech@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* refactor(chat): replace chatId with transportChatId in message editor and hooks

This commit updates the MessageEditor component and the useVercelChat hook to utilize transportChatId instead of the previous chatId. This change enhances the consistency of chat-related API calls and aligns with the new session-scoped architecture, ensuring that the correct chat identifier is used for operations like deleting trailing messages.

* fix(chat): persist selected model before send so the workflow bills it (#1781)

* fix(chat): persist selected model before send so the workflow bills it

The chat-workflow path bills the model it reads from chats.model_id at
request time. The picker selection was never written there, so every new
chat (and any model change) billed the chats.model_id default instead of
the chosen model.

Before sending, await a PATCH of the selected model to
chats.model_id when it changed for the active chat (shouldPersistChatModel
guards redundant writes). The chat row already exists from new-chat
bootstrap, so this covers the first turn race-free without an api change.

Reuses buildPatchChatBody + updateChat(modelId) (originally from #1779).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* refactor(chat): extract model-persist-before-send into usePersistSelectedModel

Addresses OCP/SRP review feedback on #1781: instead of inlining the
persist-before-send block in useVercelChat, encapsulate it in a dedicated
usePersistSelectedModel hook (owns the lastPersisted ref + guard + PATCH).
useVercelChat now just calls `await persistSelectedModel()` before send.

Behavior unchanged; pure decision logic still covered by
shouldPersistChatModel tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(chat): persist selected model on retry/edit + append paths

Addresses review feedback on #1781:
- Retry/Edit call reload() → regenerate (and append() calls sendMessage)
  bypassing handleSubmit, so the selected model was not persisted before
  those sends — the regenerated turn could bill the previous/default model.
  Now await persistSelectedModel() in handleReload and append too.
- Clarify updateChat JSDoc: it patches title and/or modelId (not just rename).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat(chat): repoint chat transport to canonical POST /api/chat (#1783)

Step 3 of the /api/chat/workflow → /api/chat rename (chat#1767), against
the merged docs contract (docs#235) and the api endpoint (api#645, on test).

useChatTransport now POSTs to ${baseUrl}/api/chat instead of
/api/chat/workflow. Comment-only refs in VercelChatProvider updated too.

⚠️ Deploy coordination: requires api#645 (which removes /api/chat/workflow)
to be live in the same environment. Must deploy together with the api
promotion and the open-agents repoint (step 4), or chat 404s.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Revert "refactor(chat): replace chatId with transportChatId in message editor and hooks"

This reverts commit 9f34b11.

* chore: upgrade @privy-io/react-auth v1.88.4 → v3.31.0 (#1802)

* chore: upgrade @privy-io/react-auth v1.88.4 -> v3.31.0

Prerequisite for cross-subdomain (cookie) auth in #1801:
matches marketing's ^3.31.0 so both surfaces run a cookie-capable SDK.

Migration surface is minimal — every @privy-io import in chat is usePrivy
or the PrivyProvider component (audited all 48 sites); none of the
v3-renamed/removed hooks (useLoginToFrame, useSignAuthorization,
useSolanaWallets, useWallets, useLogin/useLogout callbacks) are used, and
usePrivy()'s return shape (login/logout/authenticated/user/getAccessToken/
ready) plus user.email.address / user.wallet.address are unchanged in v3.

Only code change: embeddedWallets.createOnLogin moved under a per-chain key
(v3 breaking change) -> embeddedWallets.ethereum.createOnLogin.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Update providers/PrivyProvider.tsx

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat: show X (Twitter) + LinkedIn in artist Connectors tab (chat#1793) (#1805)

* feat: show X (Twitter) in artist Connectors tab; keep LinkedIn label-only (chat#1793)

Mirror the api ALLOWED_ARTIST_CONNECTORS change on the frontend: add
`twitter` to the artist-settings connector allow-list. `linkedin` stays
excluded (label/owner-only).

TDD: new allowedArtistConnectors.test.ts asserts twitter included +
linkedin excluded, RED before GREEN.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat: show LinkedIn in artist Connectors tab too (chat#1793)

Reversal of the earlier label-only call: per owner decision 2026-06-18,
LinkedIn is now an artist-facing connector. Add `linkedin` to the chat
ALLOWED_ARTIST_CONNECTORS, mirroring api#680.

TDD: flipped the linkedin assertion (now included), RED before GREEN.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs: update artist allow-list comment — chat is the source of truth (chat#1793)

The api's ALLOWED_ARTIST_CONNECTORS is being deleted (no runtime consumer;
api#680). Reword the comment to drop the stale "separate from the API's
ALLOWED_ARTIST_CONNECTORS" reference and state that this list is the source
of truth, applied by filtering the unopinionated GET /api/connectors response.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* feat: branded icons + display metadata for X, LinkedIn, YouTube connectors (chat#1793)

The artist Connectors tab showed X/LinkedIn (and YouTube) with the generic
Link2 fallback icon, a default description, and a mangled fallback name.
Add proper display entries:
- getConnectorIcon: SiX (X), SiYoutube (YouTube), lucide Linkedin (LinkedIn,
  since Simple Icons dropped the LinkedIn logo on brand request)
- connectorMetadata: descriptions for twitter + linkedin
- formatConnectorName: "X (Twitter)" + "LinkedIn"

TDD: connectorDisplay.test.ts asserts branded (non-fallback) icons + clean
names + real descriptions for the three slugs, RED before GREEN.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix: point prod API base to api.recoupable.dev (domain cutover) (#1820)

NEW_API_BASE_URL resolved to https://api.recoupable.com in production, which no
longer resolves after the .com apex was retired — every client API call from
chat.recoupable.dev failed with ERR_NAME_NOT_RESOLVED (e.g. /api/ai/models, so
the model selector never populated). Point prod at the live api.recoupable.dev
domain. Non-prod base (test-recoup-api.vercel.app) is unchanged.

Refs #1819.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix: repoint dead .com hosts to live .dev (#1819 §A+§B) (#1823)

Repoint dead recoupable.com hosts to their live .dev equivalents and DRY
the URLs through shared constants in lib/consts.ts.

- Add APP_BASE_URL, DOCS_BASE_URL, API_PUBLIC_BASE_URL constants
- getChatUrl: chat.recoupable.com -> APP_BASE_URL (chat.recoupable.dev)
- ApiKeyManager / ExternalLinksGroup docs links -> DOCS_BASE_URL
  (docs.recoupable.dev); apex recoupable.com link left intact (still live)
- In-app API doc examples (account/fans/posts): api.recoupable.com ->
  api.recoupable.dev, via API_PUBLIC_BASE_URL where interpolatable
- JSDoc @see hosts -> docs.recoupable.dev
- Update getChatUrl test assertion to match new origin

Emails (agent@recoupable.com) and apex links left untouched.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* HOLD MERGE: move brand email to @recoupable.dev (#1826)

RECOUP_FROM_EMAIL agent@recoupable.com → @recoupable.dev (the agent's outbound
from-address); global-error page "Get help" support mailto → @recoupable.dev.

DO NOT MERGE until recoupable.dev is a verified sending domain in Resend —
the agent sends from this address, so an unverified domain bounces every email.
Per #1819 decision 2026-06-29.

Refs #1819.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix: move apex recoupable.com → recoupable.dev (chat Website + legal redirects) (#1825)

Update the Website link in the user profile dropdown and the privacy/terms
redirects from recoupable.com to the live recoupable.dev apex.

- ExternalLinksGroup: Website href + label → recoupable.dev
- /privacy → https://recoupable.dev/privacy-policy
- /terms → https://recoupable.dev/terms-of-use (path renamed from terms-of-service)

Refs #1819

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: ahmednahima0-beep <ahmednahima0@gmail.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: pradipthaadhi <yulius.upwork@gmail.com>
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