.dub.link changes#3871
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📝 WalkthroughWalkthroughThe PR enhances domain and subdomain onboarding flows: DomainOption cards gain banners and feature lists; the Domain page becomes an async server component that conditionally renders partner vs non-partner copy; ProgramLinkConfiguration adds a trial-only .dub.link subdomain modal with debounced availability checks and claim submission; backend auto-verifies .dub.link claims. ChangesDomain & Subdomain Onboarding Enhancement
Sequence Diagram(s)sequenceDiagram
participant User
participant Modal as Subdomain Modal
participant Form as SubdomainForm
participant ValidAPI as Validation API
participant CreateAPI as Domains API
participant Cache as SWR Cache
participant Toast as Toast Notification
User->>Modal: Click Use dub.link subdomain
Modal->>Form: Render with initial state
User->>Form: Type slug (sanitized, debounced)
Form->>ValidAPI: GET /api/domains/:domain/validate
ValidAPI-->>Form: Available / Taken
Form-->>User: Display status
User->>Form: Click Claim Domain
Form->>CreateAPI: POST /api/domains?workspaceId=...
CreateAPI-->>Form: Auto-verify .dub.link slugs / Respond
Form->>Cache: Revalidate /api/domains
Form->>Cache: Revalidate /api/links
Form->>Toast: Show success
Form->>Modal: Close via callback
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (1)
apps/web/app/app.dub.co/(onboarding)/onboarding/(steps)/domain/page.tsx (1)
41-41: 💤 Low valueVerify the arbitrary variant selector.
[&_>div:first-of-type]:max-w-[640px]includes a leading underscore (_) inside the selector before>. Tailwind converts_to a space in arbitrary variants, so this compiles to& >div:first-of-type(descendant + child combinator), which still matches a direct child but is unusual. The conventional form would be[&>div:first-of-type]:max-w-[640px]. Worth confirming this still resolves to the intended child element under the configured Tailwind version.♻️ Optional cleanup
- className="max-w-none [&_>div:first-of-type]:max-w-[640px]" + className="max-w-none [&>div:first-of-type]:max-w-[640px]"🤖 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/web/app/app.dub.co/`(onboarding)/onboarding/(steps)/domain/page.tsx at line 41, The arbitrary variant selector in the className string uses an underscore (`[&_>div:first-of-type]:max-w-[640px]`) which Tailwind treats as a space; update the selector to the conventional form (`[&>div:first-of-type]:max-w-[640px]`) so it clearly targets the direct child div as intended—locate the className assignment in the onboarding domain page component (the className containing "max-w-none [&_>div:first-of-type]:max-w-[640px]") and replace the underscored selector with the standard one, then run your Tailwind build to verify the rule applies to the first direct child div.
🤖 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/web/ui/partners/program-link-configuration.tsx`:
- Around line 334-358: The availability UI can show results for a different slug
and lose to out-of-order fetches; inside DubLinkSubdomainForm update the
useEffect that validates debouncedDomain to create and use an AbortController
for the fetch, abort it in the effect cleanup to prevent stale responses from
overwriting state, and only set/setAvailable when the response is from the
current request; also change the JSX that renders the "is available" / checking
branches (the parts referencing domain, available, and isChecking) to gate those
branches on slug === debouncedSlug so the UI only displays availability for a
slug that was actually validated.
- Around line 360-369: The claimDomain handler calls fetch with workspace.id
which can be undefined; update claimDomain (and the submit button) to guard
against an unloaded workspace by asserting workspace.id before calling fetch
(return early or show validation) and ensure setIsSubmitting is not set true
unless workspace.id exists; also add disabled={!available || !workspace.id} to
the submit control so the form cannot be submitted until useWorkspace() has a
valid id.
- Around line 371-376: The error handling for the fetch response currently
assumes res.json() returns an object with error.message and only resets
setIsSubmitting(false) on that failure path; update the failure branch in the
submission handler (the block using res, setIsSubmitting, and toast.error in
program-link-configuration.tsx) to parse the JSON defensively, read the message
via optional chaining and type checks (e.g., if error is string or object use
appropriate message), and ensure setIsSubmitting(false) is executed in all exit
paths (move it into a finally block or call it before each return) so the UI is
always reset even with unexpected response shapes.
---
Nitpick comments:
In `@apps/web/app/app.dub.co/`(onboarding)/onboarding/(steps)/domain/page.tsx:
- Line 41: The arbitrary variant selector in the className string uses an
underscore (`[&_>div:first-of-type]:max-w-[640px]`) which Tailwind treats as a
space; update the selector to the conventional form
(`[&>div:first-of-type]:max-w-[640px]`) so it clearly targets the direct child
div as intended—locate the className assignment in the onboarding domain page
component (the className containing "max-w-none
[&_>div:first-of-type]:max-w-[640px]") and replace the underscored selector with
the standard one, then run your Tailwind build to verify the rule applies to the
first direct child div.
🪄 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: defaults
Review profile: CHILL
Plan: Pro
Run ID: 1a67afae-1058-43da-ac0b-841d3655566b
📒 Files selected for processing (4)
apps/web/app/app.dub.co/(onboarding)/onboarding/(steps)/domain/default-domain-selector.tsxapps/web/app/app.dub.co/(onboarding)/onboarding/(steps)/domain/page.tsxapps/web/app/app.dub.co/(onboarding)/onboarding/(steps)/products/product-selector.tsxapps/web/ui/partners/program-link-configuration.tsx
|
@coderabbitai full review |
✅ Actions performedFull review triggered. |
There was a problem hiding this comment.
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 `@apps/web/ui/partners/program-link-configuration.tsx`:
- Around line 380-383: The early-return branches that handle empty debouncedSlug
(where debouncedSlug.trim() is checked and setAvailable(null) is called) do not
reset the checking flag, leaving isChecking true; update both places (the
empty-slug branches around the debouncedSlug checks) to call
setIsChecking(false) before returning so the spinner/loading state is cleared
when the input is emptied or a pending request is aborted.
🪄 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: defaults
Review profile: CHILL
Plan: Pro
Run ID: 7e8adfd6-ef61-40eb-8035-0b0309b92e4f
📒 Files selected for processing (2)
apps/web/app/api/domains/route.tsapps/web/ui/partners/program-link-configuration.tsx
There was a problem hiding this comment.
♻️ Duplicate comments (1)
apps/web/ui/partners/program-link-configuration.tsx (1)
379-383:⚠️ Potential issue | 🟡 Minor | ⚡ Quick win
isCheckingis not reset whendebouncedSlugis empty, leaving the spinner stuck.When the user clears the input while a fetch is in-flight, the effect cleanup aborts the request. The
finallyblock at line 413 correctly skipssetIsChecking(false)for aborted requests. However, when the debounce settles on an empty string, this early-return path runssetAvailable(null)and returns without ever clearingisChecking, so the spinner persists indefinitely.🛡️ Proposed fix
useEffect(() => { if (!debouncedSlug.trim()) { + setIsChecking(false); setAvailable(null); return; }🤖 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/web/ui/partners/program-link-configuration.tsx` around lines 379 - 383, The effect that watches debouncedSlug returns early when debouncedSlug.trim() is empty but doesn't reset the isChecking state, leaving the spinner active; update the useEffect block that checks debouncedSlug (the one using debouncedSlug.trim(), setAvailable, and setIsChecking) so that on the early-return path you also call setIsChecking(false) (and setAvailable(null) as already done) to ensure isChecking is cleared when the input becomes empty or the request is aborted.
🤖 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.
Duplicate comments:
In `@apps/web/ui/partners/program-link-configuration.tsx`:
- Around line 379-383: The effect that watches debouncedSlug returns early when
debouncedSlug.trim() is empty but doesn't reset the isChecking state, leaving
the spinner active; update the useEffect block that checks debouncedSlug (the
one using debouncedSlug.trim(), setAvailable, and setIsChecking) so that on the
early-return path you also call setIsChecking(false) (and setAvailable(null) as
already done) to ensure isChecking is cleared when the input becomes empty or
the request is aborted.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 1771b1ab-fe67-48dc-8df9-a019625cd146
📒 Files selected for processing (4)
apps/web/app/api/domains/route.tsapps/web/app/app.dub.co/(onboarding)/onboarding/(steps)/domain/default-domain-selector.tsxapps/web/app/app.dub.co/(onboarding)/onboarding/(steps)/domain/page.tsxapps/web/ui/partners/program-link-configuration.tsx
Summary by CodeRabbit
New Features
User Experience