Skip to content

[Dashboard] Add chain infrastructure deployment and management #7456

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 4, 2025

Conversation

jnsdls
Copy link
Member

@jnsdls jnsdls commented Jun 27, 2025

Add Infrastructure Section to Team Dashboard

This PR adds a new "Infrastructure" section to the team dashboard, allowing users to deploy and manage blockchain infrastructure services. Key changes include:

  • Added a new "Infrastructure" tab in the team navigation with a "New" badge
  • Created infrastructure deployment UI with a multi-step checkout flow:
    • Chain selection with filter for deprecated chains
    • Service selection for RPC, Insight, and Account Abstraction services
    • Payment frequency options with annual discount
    • Order summary with pricing calculations
  • Enhanced UpsellBannerCard component to support onClick handlers
  • Added disableDeprecated option to SingleNetworkSelector component
  • Updated Biome schema URLs from 2.0.0 to 2.0.4 across all packages

The infrastructure deployment UI includes detailed pricing information, bundle discounts, and a complete checkout experience for teams to easily deploy blockchain infrastructure services.

Summary by CodeRabbit

  • New Features

    • Introduced infrastructure deployment pages with a multi-step flow for selecting blockchain networks and services, featuring dynamic pricing, discounts, and checkout integration.
    • Added infrastructure service cards displaying status indicators and metric placeholders.
    • Sidebar now includes chain infrastructure links for teams with relevant subscriptions.
    • Added checkout functionality for chain infrastructure subscriptions with error handling.
  • Enhancements

    • Network selector optionally hides deprecated chains.
    • Upsell banner CTA supports both link and callback actions.
    • UI improvements across infrastructure and ecosystem management.
    • Ecosystem API calls and type imports standardized for improved consistency.
  • Bug Fixes

    • Fixed skeleton loading element in chain icon display.
  • Refactor

    • Streamlined ecosystem API integrations and type imports for consistency.
    • Removed redundant helper files and updated import paths in ecosystem features.
    • Improved sidebar and layout components to support chain infrastructure subscriptions.
  • Chores

    • Updated type definitions and component props for enhanced extensibility and clarity.
    • Added new types for chain infrastructure SKUs and team subscriptions.

PR-Codex overview

This PR focuses on refactoring and updating the ecosystem management codebase, enhancing type definitions, consolidating utility functions, and improving component imports for better organization and maintainability.

Detailed summary

  • Deleted unused utility files: fetchEcosystem.ts and fetchEcosystemList.ts.
  • Introduced ChainInfraSKU type for billing.
  • Updated imports for Ecosystem and Partner across multiple files.
  • Enhanced fetchEcosystem and fetchEcosystemList functions to streamline API calls.
  • Improved UI components for better structure and readability.
  • Added new infrastructure deployment components and logic.
  • Refactored subscription handling in the billing system to include new types and functionalities.

The following files were skipped due to too many changes: apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/deploy-infrastructure-form.client.tsx

✨ Ask PR-Codex anything about this PR by commenting with /codex {your question}

Copy link

vercel bot commented Jun 27, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
docs-v2 ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jul 4, 2025 0:24am
nebula ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jul 4, 2025 0:24am
thirdweb_playground ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jul 4, 2025 0:24am
thirdweb-www ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jul 4, 2025 0:24am
wallet-ui ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jul 4, 2025 0:24am

Copy link

changeset-bot bot commented Jun 27, 2025

⚠️ No Changeset found

Latest commit: aec866a

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

Copy link
Contributor

coderabbitai bot commented Jun 27, 2025

Walkthrough

This update introduces a new blockchain infrastructure deployment feature, including multi-step UI flows for selecting chains and services, dynamic pricing, and checkout integration. It adds new API utilities for ecosystem and chain subscription management, restructures type imports for consistency, and removes obsolete local data-fetching helpers. Sidebar navigation is enhanced to surface chain infrastructure subscriptions per team.

Changes

File(s) Change Summary
.../NetworkSelectors.tsx Added disableDeprecated prop to SingleNetworkSelector to filter deprecated chains.
.../UpsellBannerCard.tsx Made cta prop optional and a union type; updated rendering logic for CTA button.
.../ChainIcon.tsx Changed skeleton placeholder from <div> to <span>.
.../billing.ts Added getChainInfraCheckoutURL async function for checkout URL generation; updated reSubscribePlan URL construction.
.../full-width-sidebar-layout.tsx Added key prop to RenderSidebarSubmenu for submenu rendering.
.../types/billing.ts Added ChainInfraSKU type alias for supported SKUs.
.../infrastructure/[chain_id]/page.tsx New page: displays chain infrastructure subscription, status, and metrics.
.../infrastructure/deploy/[chain_id]/page.tsx New page: step 2 of deployment, renders deploy form for selected chain.
.../infrastructure/deploy/_components/deploy-infrastructure-form.client.tsx New client component: service selection, pricing, billing frequency, checkout.
.../infrastructure/deploy/page.tsx New page: step 1, chain selection for infrastructure deployment.
.../infrastructure/deploy/search-params.ts New module: defines search param parsing for add-ons and billing frequency.
.../infrastructure/layout.tsx New layout: fetches team, wraps children, redirects if team not found.
.../api/ecosystems.ts Added fetchEcosystemList, fetchEcosystem, and AuthOption type; imports refactored.
.../api/team-subscription.ts Added "CHAIN" type, skus field, ChainTeamSubscription type, and chain subscription fetchers.
.../storybook/stubs.ts Updated stub: added skus field, reformatted descriptions.
.../TeamSidebarLayout.tsx Added chainSubscriptions prop; renders dynamic "Chain Infrastructure" submenu.
.../layout.tsx (team layout) Refactored: fetches ecosystems and chain subscriptions via new APIs; passes to sidebar.
.../ecosystem/[slug]/(active)/analytics/page.tsx, .../components/EcosystemSlugLayout.tsx, .../analytics/components/EcosystemAnalyticsPage.tsx, .../analytics/components/EcosystemWalletUsersChartCard.tsx, .../configuration/components/client/AddPartnerDialogButton.tsx, .../configuration/components/client/add-partner-form.client.tsx, .../configuration/components/client/auth-options-form.client.tsx, .../configuration/components/client/integration-permissions-toggle.client.tsx, .../configuration/components/client/partner-form.client.tsx, .../configuration/components/client/update-partner-form.client.tsx, .../configuration/components/server/auth-options-section.tsx, .../configuration/components/server/ecosystem-partners-section.tsx, .../configuration/components/server/integration-permissions-section.tsx, .../configuration/components/server/partners-table.tsx, .../configuration/hooks/fetchPartnerDetails.ts, .../configuration/hooks/fetchPartners.ts, .../configuration/hooks/use-add-partner.ts, .../configuration/hooks/use-delete-partner.ts, .../configuration/hooks/use-update-ecosystem.ts, .../configuration/hooks/use-update-partner.ts, .../hooks/use-ecosystem.ts, .../hooks/use-partners.ts Refactored type imports from relative to absolute path (@/api/ecosystems).
.../ecosystem/[slug]/(active)/configuration/add-partner/page.tsx, .../partners/[partner_id]/edit/page.tsx Refactored ecosystem fetching: use new API, added explicit not-found error.
.../ecosystem/page.tsx Refactored: uses new fetchEcosystemList API without authToken param.
.../ecosystem/utils/fetchEcosystem.ts, .../ecosystem/utils/fetchEcosystemList.ts, .../configuration/hooks/fetchEcosystem.ts Deleted obsolete local ecosystem fetcher utilities.
.../infrastructure/[chain_id]/_components/service-card.tsx New component: displays service status and metric placeholders.
.../app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/analytics/page.tsx Updated imports to absolute paths; simplified fetchEcosystem call.
.../app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/components/* Changed all Ecosystem and Partner type imports to absolute alias imports.
.../app/(app)/team/[team_slug]/(team)/~/ecosystem/utils/fetchEcosystem.ts Deleted local ecosystem fetcher utility.
.../app/(app)/team/[team_slug]/(team)/~/ecosystem/utils/fetchEcosystemList.ts Deleted local ecosystem list fetcher utility.
.../app/(app)/team/[team_slug]/(team)/~/ecosystem/page.tsx Updated to use new fetchEcosystemList API without authToken param.
.../app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/add-partner/page.tsx Added explicit error throw if ecosystem not found after fetch.
.../app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/partners/[partner_id]/edit/page.tsx Added explicit error throw if ecosystem not found after fetch.
.../app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/analytics/components/EcosystemAnalyticsPage.tsx Updated import of Partner type to absolute alias path.
.../app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/analytics/components/EcosystemWalletUsersChartCard.tsx Updated import of Partner type to absolute alias path.
.../app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/components/client/partner-form.client.tsx Updated import of Partner type to absolute alias path.
.../app/(app)/team/[team_slug]/(team)/~/ecosystem/create/actions/create-ecosystem.ts Changed import of getAuthToken to absolute alias path.
.../app/(app)/(dashboard)/explore/components/contract-row/index.tsx Changed imports of ContractCard and ContractCardSkeleton to absolute alias path.
.../app/(app)/team/[team_slug]/(team)/~/billing/layout.tsx Changed import of TabPathLinks to absolute alias path.
.../app/(app)/team/[team_slug]/(team)/~/usage/layout.tsx Changed import of TabPathLinks to absolute alias path.
.../app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/nft/sales/sales-settings.tsx Changed import of SolidityInput to absolute alias path.
.../app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/analytics/ftux.client.tsx Changed import of Button to absolute alias path.
.../app/(app)/team/[team_slug]/[project_slug]/(sidebar)/wallets/settings/components/index.tsx Removed duplicate import of FileInput, consolidated import from absolute alias path.
.../packages/thirdweb/src/react/web/ui/components/Modal.tsx Reordered props and styles for code clarity; no functional changes.

Sequence Diagram(s)

Infrastructure Deployment Flow

sequenceDiagram
    participant User
    participant DeployInfrastructurePage (Step 1)
    participant SingleNetworkSelector
    participant DeployInfrastructureOnChainPage (Step 2)
    participant DeployInfrastructureForm
    participant BillingAPI

    User->>DeployInfrastructurePage: Visit /team/[team_slug]/~/infrastructure/deploy
    DeployInfrastructurePage->>SingleNetworkSelector: Render chain selector
    User->>SingleNetworkSelector: Select chain
    DeployInfrastructurePage->>User: Enable "Continue" button
    User->>DeployInfrastructurePage: Click "Continue"
    DeployInfrastructurePage->>DeployInfrastructureOnChainPage: Navigate to /deploy/[chain_id]
    DeployInfrastructureOnChainPage->>DeployInfrastructureForm: Render service selection form
    User->>DeployInfrastructureForm: Select services, billing frequency
    User->>DeployInfrastructureForm: Click "Checkout"
    DeployInfrastructureForm->>BillingAPI: Call getChainInfraCheckoutURL
    BillingAPI-->>DeployInfrastructureForm: Return checkout URL or error
    DeployInfrastructureForm->>User: Open checkout or show error
Loading

Sidebar Chain Infrastructure Links

sequenceDiagram
    participant TeamLayout
    participant API
    participant TeamSidebarLayout
    participant User

    TeamLayout->>API: fetchEcosystemList, getChainSubscriptions
    API-->>TeamLayout: Ecosystem list, chain subscriptions
    TeamLayout->>TeamSidebarLayout: Pass chainSubscriptions prop
    TeamSidebarLayout->>User: Render sidebar with dynamic "Chain Infrastructure" submenu
Loading

Ecosystem Fetch Refactor

sequenceDiagram
    participant EcosystemPage
    participant fetchEcosystem (API)
    participant API Server

    EcosystemPage->>fetchEcosystem: Call with slug, team_slug
    fetchEcosystem->>API Server: GET /api/teams/{team_slug}/ecosystems/{slug}
    API Server-->>fetchEcosystem: Ecosystem data or error
    fetchEcosystem-->>EcosystemPage: Ecosystem data or null
Loading

Suggested reviewers

  • joaquim-verges
✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@github-actions github-actions bot added Dashboard Involves changes to the Dashboard. Playground Changes involving the Playground codebase. Portal Involves changes to the Portal (docs) codebase. packages Ecosystem Portal Involves changes to the Ecosystem Portal SDK Involves changes to the thirdweb SDK labels Jun 27, 2025
@jnsdls jnsdls changed the title self-serve infra deployment self-serve infra deployment: part 1 Jun 27, 2025
Copy link
Member Author

jnsdls commented Jun 27, 2025


How to use the Graphite Merge Queue

Add either label to this PR to merge it via the merge queue:

  • merge-queue - adds this PR to the back of the merge queue
  • hotfix - for urgent hot fixes, skip the queue and merge this PR next

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has enabled the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

This stack of pull requests is managed by Graphite. Learn more about stacking.

Copy link
Contributor

github-actions bot commented Jun 27, 2025

size-limit report 📦

Path Size Loading time (3g) Running time (snapdragon) Total time
thirdweb (esm) 63.11 KB (0%) 1.3 s (0%) 269 ms (+112.59% 🔺) 1.6 s
thirdweb (cjs) 352.76 KB (0%) 7.1 s (0%) 942 ms (+7.84% 🔺) 8 s
thirdweb (minimal + tree-shaking) 5.72 KB (0%) 115 ms (0%) 116 ms (+1864.86% 🔺) 231 ms
thirdweb/chains (tree-shaking) 530 B (0%) 11 ms (0%) 42 ms (+1061.87% 🔺) 52 ms
thirdweb/react (minimal + tree-shaking) 19.59 KB (0%) 392 ms (0%) 66 ms (+274.48% 🔺) 458 ms

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (6)
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/page.tsx (1)

1-3: Consider enhancing the infrastructure overview page.

While this minimal implementation works as a placeholder, consider adding more meaningful content such as:

  • Infrastructure service status overview
  • Quick access links to deploy new services
  • Summary of existing infrastructure

This would provide better user experience compared to the current basic text display.

apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/order-summary.tsx (2)

8-12: Consider exposing className prop for better composability.

Following the coding guidelines, components should expose a className prop when useful for styling flexibility.

export function OrderSummary(props: {
  selectedChainId: number;
  selectedServices: ServiceConfig[];
  paymentFrequency: PaymentFrequency;
+ className?: string;
}) {

And apply it to the root div:

-    <div className="space-y-4">
+    <div className={cn("space-y-4", props.className)}>

93-93: Consider making discount percentages configurable.

The discount percentages (15% annual, 10-15% bundle) are hardcoded, which reduces flexibility for business logic changes.

Consider extracting these into configuration constants or props:

+const DISCOUNT_CONFIG = {
+  annual: 0.15,
+  bundle: {
+    twoServices: 0.1,
+    threeServices: 0.15,
+  },
+} as const;

// Then use in calculations:
-  const annualDiscount = paymentFrequency === "annual" ? 0.15 : 0;
+  const annualDiscount = paymentFrequency === "annual" ? DISCOUNT_CONFIG.annual : 0;

Also applies to: 162-166, 169-169

apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/service-selector.tsx (3)

22-26: Consider exposing className prop for better composability.

Following the coding guidelines, components should expose a className prop for styling flexibility.

export function ServiceSelector(props: {
  services: ServiceConfig[];
  selectedServices: ServiceConfig[];
  setSelectedServices: (services: ServiceConfig[]) => void;
+ className?: string;
}) {

113-116: Break down complex className for better readability.

The className string is very long and hard to read. Consider breaking it into multiple lines or extracting parts into variables.

      <Label
        className={cn(
-          "hover:bg-accent/50 flex gap-6 rounded-lg border px-6 py-4 has-[[aria-checked=true]]:border-primary has-[[aria-checked=true]]:bg-primary/10 cursor-pointer items-center",
+          "flex items-center gap-6 rounded-lg border px-6 py-4 cursor-pointer",
+          "hover:bg-accent/50",
+          "has-[[aria-checked=true]]:border-primary has-[[aria-checked=true]]:bg-primary/10",
           props.service.required && "cursor-not-allowed",
         )}
      >

146-153: Consider responsive design for feature list.

The features are completely hidden on mobile (hidden lg:grid). Consider showing a subset or using a different layout for better mobile experience.

-        <div className="grid-cols-2 gap-2 hidden lg:grid">
+        <div className="grid grid-cols-1 lg:grid-cols-2 gap-2">
           {props.service.features.map((feature) => (
             <div className="flex items-center space-x-1 text-sm" key={feature}>
               <CheckIcon className="w-3 h-3 shrink-0 text-success-text" />
               <span>{feature}</span>
             </div>
           ))}
         </div>

Or limit features shown on mobile:

+        <div className="grid grid-cols-1 lg:grid-cols-2 gap-2">
+          {props.service.features.slice(0, 2).map((feature) => (
+            <div className="flex items-center space-x-1 text-sm" key={feature}>
+              <CheckIcon className="w-3 h-3 shrink-0 text-success-text" />
+              <span>{feature}</span>
+            </div>
+          ))}
+          {props.service.features.length > 2 && (
+            <div className="text-sm text-muted-foreground lg:hidden">
+              +{props.service.features.length - 2} more features
+            </div>
+          )}
+        </div>
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 277c2e2 and 71255ca.

📒 Files selected for processing (26)
  • apps/dashboard/biome.json (1 hunks)
  • apps/dashboard/src/@/components/blocks/NetworkSelectors.tsx (2 hunks)
  • apps/dashboard/src/@/components/blocks/UpsellBannerCard.tsx (2 hunks)
  • apps/dashboard/src/@/icons/ChainIcon.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/layout.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/[chain_id]/page.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/checkout.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/order-summary.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/payment-frequency-selector.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/service-selector.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/page.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/layout.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/page.tsx (1 hunks)
  • apps/nebula/biome.json (1 hunks)
  • apps/playground-web/biome.json (1 hunks)
  • apps/portal/biome.json (1 hunks)
  • apps/wallet-ui/biome.json (1 hunks)
  • biome.json (1 hunks)
  • packages/engine/biome.json (1 hunks)
  • packages/insight/biome.json (1 hunks)
  • packages/nebula/biome.json (1 hunks)
  • packages/react-native-adapter/biome.json (1 hunks)
  • packages/service-utils/biome.json (1 hunks)
  • packages/thirdweb/biome.json (1 hunks)
  • packages/vault-sdk/biome.json (1 hunks)
  • packages/wagmi-adapter/biome.json (1 hunks)
🧰 Additional context used
📓 Path-based instructions (11)
`apps/dashboard/*`: The dashboard app is a web-based developer console built wit...

apps/dashboard/*: The dashboard app is a web-based developer console built with Next.js and Chakra UI.
Use Tailwind CSS only for styling; no inline styles or CSS modules.
Use cn() from @/lib/utils for conditional class merging.
Use design system tokens for backgrounds (bg-card), borders (border-border), and muted text (text-muted-foreground).
Expose className prop on the root element of components for overrides.
Use NavLink for internal navigation with automatic active states.
Server components should start files with import "server-only"; client components should begin files with 'use client';.
Never import posthog-js in server components; analytics events are client-side only.

📄 Source: CodeRabbit Inference Engine (CLAUDE.md)

List of files the instruction was applied to:

  • apps/dashboard/biome.json
`packages/thirdweb/*`: Every public symbol in the SDK must have comprehensive TS...

packages/thirdweb/*: Every public symbol in the SDK must have comprehensive TSDoc with at least one @example block that compiles and custom annotation tags (@beta, @internal, @experimental).
Export everything via the exports/ directory, grouped by feature.
Place tests alongside code: foo.ts ↔ foo.test.ts.
Use real function invocations with stub data in tests; avoid brittle mocks.
Use Mock Service Worker (MSW) for fetch/HTTP call interception in tests.
Keep tests deterministic and side-effect free.

📄 Source: CodeRabbit Inference Engine (CLAUDE.md)

List of files the instruction was applied to:

  • packages/thirdweb/biome.json
`apps/wallet-ui/*`: The wallet-ui app is for wallet interface and testing.

apps/wallet-ui/*: The wallet-ui app is for wallet interface and testing.

📄 Source: CodeRabbit Inference Engine (CLAUDE.md)

List of files the instruction was applied to:

  • apps/wallet-ui/biome.json
`biome.json`: Biome is the primary linter/formatter; rules are defined in biome.json.

biome.json: Biome is the primary linter/formatter; rules are defined in biome.json.

📄 Source: CodeRabbit Inference Engine (CLAUDE.md)

List of files the instruction was applied to:

  • biome.json
`packages/wagmi-adapter/*`: Wagmi ecosystem integration is located in packages/wagmi-adapter/.

packages/wagmi-adapter/*: Wagmi ecosystem integration is located in packages/wagmi-adapter/.

📄 Source: CodeRabbit Inference Engine (CLAUDE.md)

List of files the instruction was applied to:

  • packages/wagmi-adapter/biome.json
`apps/portal/*`: The portal app is a documentation site with MDX.

apps/portal/*: The portal app is a documentation site with MDX.

📄 Source: CodeRabbit Inference Engine (CLAUDE.md)

List of files the instruction was applied to:

  • apps/portal/biome.json
`packages/react-native-adapter/*`: Mobile platform shims are located in packages/react-native-adapter/.

packages/react-native-adapter/*: Mobile platform shims are located in packages/react-native-adapter/.

📄 Source: CodeRabbit Inference Engine (CLAUDE.md)

List of files the instruction was applied to:

  • packages/react-native-adapter/biome.json
`**/icons/*`: Icons come from 'lucide-react' or the project-specific '../icons' exports – never embed raw SVG.

**/icons/*: Icons come from 'lucide-react' or the project-specific '../icons' exports – never embed raw SVG.

📄 Source: CodeRabbit Inference Engine (.cursor/rules/dashboard.mdc)

List of files the instruction was applied to:

  • apps/dashboard/src/@/icons/ChainIcon.tsx
`**/*.@(ts|tsx)`: Accept a typed 'props' object and export a named function (e.g...

**/*.@(ts|tsx): Accept a typed 'props' object and export a named function (e.g., export function MyComponent()).
Combine class names via 'cn', expose 'className' prop if useful.
Reuse core UI primitives; avoid re-implementing buttons, cards, modals.
Local state or effects live inside; data fetching happens in hooks.
Merge class names with 'cn' from '@/lib/utils' to keep conditional logic readable.
Stick to design-tokens: background ('bg-card'), borders ('border-border'), muted text ('text-muted-foreground') etc.
Use the 'container' class with a 'max-w-7xl' cap for page width consistency.
Spacing utilities ('px-', 'py-', 'gap-*') are preferred over custom margins.
Responsive helpers follow mobile-first ('max-sm', 'md', 'lg', 'xl').
Never hard-code colors – always go through Tailwind variables.
Tailwind CSS is the styling system – avoid inline styles or CSS modules.
Prefix files with 'import "server-only";' so they never end up in the client bundle (for server-only code).

📄 Source: CodeRabbit Inference Engine (.cursor/rules/dashboard.mdc)

List of files the instruction was applied to:

  • apps/dashboard/src/@/icons/ChainIcon.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/layout.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/page.tsx
  • apps/dashboard/src/@/components/blocks/NetworkSelectors.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/[chain_id]/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/payment-frequency-selector.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/checkout.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/layout.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/order-summary.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/service-selector.tsx
  • apps/dashboard/src/@/components/blocks/UpsellBannerCard.tsx
`apps/nebula/*`: The nebula app is for account abstraction and smart wallet management.

apps/nebula/*: The nebula app is for account abstraction and smart wallet management.

📄 Source: CodeRabbit Inference Engine (CLAUDE.md)

List of files the instruction was applied to:

  • apps/nebula/biome.json
`apps/playground-web/*`: The playground-web app is an interactive SDK testing environment.

apps/playground-web/*: The playground-web app is an interactive SDK testing environment.

📄 Source: CodeRabbit Inference Engine (CLAUDE.md)

List of files the instruction was applied to:

  • apps/playground-web/biome.json
🧠 Learnings (13)
📓 Common learnings
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:155-160
Timestamp: 2025-06-10T00:46:58.580Z
Learning: In the dashboard application, the route structure for team and project navigation is `/team/[team_slug]/[project_slug]/...` without a `/project/` segment. Contract links should be formatted as `/team/${teamSlug}/${projectSlug}/contract/${chainId}/${contractAddress}`.
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:153-226
Timestamp: 2025-06-10T00:50:20.795Z
Learning: In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx, the updateStatus function correctly expects a complete MultiStepState["status"] object. For pending states, { type: "pending" } is the entire status object. For error states, { type: "error", message: React.ReactNode } is the entire status object. The current code incorrectly spreads the entire step object instead of passing just the status object.
apps/dashboard/src/@/icons/ChainIcon.tsx (2)
Learnt from: jnsdls
PR: thirdweb-dev/js#7188
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/components/accounts-count.tsx:15-15
Timestamp: 2025-05-29T00:46:09.063Z
Learning: In the accounts component at apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/components/accounts-count.tsx, the 3-column grid layout (md:grid-cols-3) is intentionally maintained even when rendering only one StatCard, as part of the design structure for this component.
Learnt from: MananTank
PR: thirdweb-dev/js#7177
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/public-pages/erc20/_components/ContractHeader.tsx:26-43
Timestamp: 2025-05-29T10:49:52.981Z
Learning: In React image components, conditional rendering of the entire image container (e.g., `{props.image && <Img />}`) serves a different purpose than fallback handling. The conditional prevents rendering any image UI when no image metadata exists, while the fallback prop handles cases where image metadata exists but the image fails to load. This pattern is intentional to distinguish between "no image intended" vs "image intended but failed to load".
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/layout.tsx (13)
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:155-160
Timestamp: 2025-06-10T00:46:58.580Z
Learning: In the dashboard application, the route structure for team and project navigation is `/team/[team_slug]/[project_slug]/...` without a `/project/` segment. Contract links should be formatted as `/team/${teamSlug}/${projectSlug}/contract/${chainId}/${contractAddress}`.
Learnt from: jnsdls
PR: thirdweb-dev/js#6929
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx:14-19
Timestamp: 2025-05-21T05:17:31.283Z
Learning: In Next.js server components, the `params` object can sometimes be a Promise that needs to be awaited, despite type annotations suggesting otherwise. In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx, it's necessary to await the params object before accessing its properties.
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-25T02:13:08.257Z
Learning: UI primitives should be imported from @/components/ui/*.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Always import reusable UI components from a central library (e.g., '@/components/ui/*') to ensure consistency and avoid duplication.
Learnt from: MananTank
PR: thirdweb-dev/js#7227
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/OpenEditionMetadata.tsx:26-26
Timestamp: 2025-05-30T17:14:25.332Z
Learning: The ModuleCardUIProps interface already includes a client prop of type ThirdwebClient, so when components use `Omit<ModuleCardUIProps, "children" | "updateButton">`, they inherit the client prop without needing to add it explicitly.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Client components must begin with 'use client'; before imports to ensure correct rendering behavior in Next.js.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Prefer composable UI primitives (Button, Input, Select, Tabs, Card, Sidebar, Separator, Badge) over custom markup for maintainability and design consistency.
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-25T02:13:08.257Z
Learning: Client components should begin files with 'use client' and use React hooks for interactivity.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Use client components for interactive UI, components that rely on hooks, browser APIs, or require fast transitions.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Files for components should be named in PascalCase and use the '.client.tsx' suffix if interactive.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Reuse core UI primitives and avoid re-implementing common elements like buttons, cards, or modals.
Learnt from: MananTank
PR: thirdweb-dev/js#7356
File: apps/nebula/src/app/not-found.tsx:1-1
Timestamp: 2025-06-17T18:30:52.976Z
Learning: In the thirdweb/js project, the React namespace is available for type annotations (like React.FC) without needing to explicitly import React. This is project-specific configuration that differs from typical TypeScript/React setups.
Learnt from: MananTank
PR: thirdweb-dev/js#7152
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/nfts/page.tsx:20-20
Timestamp: 2025-05-26T16:26:58.068Z
Learning: In team/project contract pages under routes like `/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/*`, users are always logged in by design. The hardcoded `isLoggedIn={true}` prop in these pages is intentional and correct, not a bug to be fixed.
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/page.tsx (5)
Learnt from: jnsdls
PR: thirdweb-dev/js#6929
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx:14-19
Timestamp: 2025-05-21T05:17:31.283Z
Learning: In Next.js server components, the `params` object can sometimes be a Promise that needs to be awaited, despite type annotations suggesting otherwise. In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx, it's necessary to await the params object before accessing its properties.
Learnt from: jnsdls
PR: thirdweb-dev/js#7363
File: apps/dashboard/src/app/(app)/layout.tsx:63-74
Timestamp: 2025-06-18T02:01:06.006Z
Learning: In Next.js applications, instrumentation files (instrumentation.ts or instrumentation-client.ts) placed in the src/ directory are automatically handled by the framework and included in the client/server bundles without requiring manual imports. The framework injects these files as part of the build process.
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:153-226
Timestamp: 2025-06-10T00:50:20.795Z
Learning: In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx, the updateStatus function correctly expects a complete MultiStepState["status"] object. For pending states, { type: "pending" } is the entire status object. For error states, { type: "error", message: React.ReactNode } is the entire status object. The current code incorrectly spreads the entire step object instead of passing just the status object.
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-25T02:13:08.257Z
Learning: For new UI components, add Storybook stories (*.stories.tsx) alongside the code.
Learnt from: jnsdls
PR: thirdweb-dev/js#7188
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/components/accounts-count.tsx:15-15
Timestamp: 2025-05-29T00:46:09.063Z
Learning: In the accounts component at apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/components/accounts-count.tsx, the 3-column grid layout (md:grid-cols-3) is intentionally maintained even when rendering only one StatCard, as part of the design structure for this component.
apps/dashboard/src/@/components/blocks/NetworkSelectors.tsx (2)
Learnt from: MananTank
PR: thirdweb-dev/js#7227
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/OpenEditionMetadata.tsx:26-26
Timestamp: 2025-05-30T17:14:25.332Z
Learning: The ModuleCardUIProps interface already includes a client prop of type ThirdwebClient, so when components use `Omit<ModuleCardUIProps, "children" | "updateButton">`, they inherit the client prop without needing to add it explicitly.
Learnt from: MananTank
PR: thirdweb-dev/js#7298
File: apps/dashboard/src/app/nebula-app/move-funds/move-funds.tsx:424-424
Timestamp: 2025-06-06T23:46:08.795Z
Learning: The thirdweb project has an ESLint rule that restricts direct usage of `defineChain`. When it's necessary to use `defineChain` directly, it's acceptable to disable the rule with `// eslint-disable-next-line no-restricted-syntax`.
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/[chain_id]/page.tsx (7)
Learnt from: jnsdls
PR: thirdweb-dev/js#6929
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx:14-19
Timestamp: 2025-05-21T05:17:31.283Z
Learning: In Next.js server components, the `params` object can sometimes be a Promise that needs to be awaited, despite type annotations suggesting otherwise. In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx, it's necessary to await the params object before accessing its properties.
Learnt from: MananTank
PR: thirdweb-dev/js#7152
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/page.tsx:2-10
Timestamp: 2025-05-26T16:28:10.079Z
Learning: In Next.js 14+, the `params` object in page components is always a Promise that needs to be awaited, so the correct typing is `params: Promise<ParamsType>` rather than `params: ParamsType`.
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:155-160
Timestamp: 2025-06-10T00:46:58.580Z
Learning: In the dashboard application, the route structure for team and project navigation is `/team/[team_slug]/[project_slug]/...` without a `/project/` segment. Contract links should be formatted as `/team/${teamSlug}/${projectSlug}/contract/${chainId}/${contractAddress}`.
Learnt from: jnsdls
PR: thirdweb-dev/js#7188
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/components/accounts-count.tsx:15-15
Timestamp: 2025-05-29T00:46:09.063Z
Learning: In the accounts component at apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/components/accounts-count.tsx, the 3-column grid layout (md:grid-cols-3) is intentionally maintained even when rendering only one StatCard, as part of the design structure for this component.
Learnt from: MananTank
PR: thirdweb-dev/js#7152
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/nfts/page.tsx:20-20
Timestamp: 2025-05-26T16:26:58.068Z
Learning: In team/project contract pages under routes like `/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/*`, users are always logged in by design. The hardcoded `isLoggedIn={true}` prop in these pages is intentional and correct, not a bug to be fixed.
Learnt from: MananTank
PR: thirdweb-dev/js#7434
File: apps/dashboard/src/app/(app)/team/~/~/contract/[chain]/[contractAddress]/components/project-selector.tsx:62-76
Timestamp: 2025-06-24T21:38:03.155Z
Learning: In the project-selector.tsx component for contract imports, the addToProject.mutate() call is intentionally not awaited (fire-and-forget pattern) to allow immediate navigation to the contract page while the import happens in the background. This is a deliberate design choice to prioritize user experience.
Learnt from: MananTank
PR: thirdweb-dev/js#7152
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/tokens/shared-page.tsx:41-48
Timestamp: 2025-05-26T16:28:50.772Z
Learning: The `projectMeta` prop is not required for the server-rendered `ContractTokensPage` component in the tokens shared page, unlike some other shared pages where it's needed for consistency.
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/payment-frequency-selector.tsx (3)
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Files for components should be named in PascalCase and use the '.client.tsx' suffix if interactive.
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-25T02:13:08.257Z
Learning: For new UI components, add Storybook stories (*.stories.tsx) alongside the code.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Prefer composable UI primitives (Button, Input, Select, Tabs, Card, Sidebar, Separator, Badge) over custom markup for maintainability and design consistency.
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/checkout.tsx (9)
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:153-226
Timestamp: 2025-06-10T00:50:20.795Z
Learning: In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx, the updateStatus function correctly expects a complete MultiStepState["status"] object. For pending states, { type: "pending" } is the entire status object. For error states, { type: "error", message: React.ReactNode } is the entire status object. The current code incorrectly spreads the entire step object instead of passing just the status object.
Learnt from: jnsdls
PR: thirdweb-dev/js#6929
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx:14-19
Timestamp: 2025-05-21T05:17:31.283Z
Learning: In Next.js server components, the `params` object can sometimes be a Promise that needs to be awaited, despite type annotations suggesting otherwise. In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx, it's necessary to await the params object before accessing its properties.
Learnt from: jnsdls
PR: thirdweb-dev/js#7188
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/components/accounts-count.tsx:15-15
Timestamp: 2025-05-29T00:46:09.063Z
Learning: In the accounts component at apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/components/accounts-count.tsx, the 3-column grid layout (md:grid-cols-3) is intentionally maintained even when rendering only one StatCard, as part of the design structure for this component.
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-25T02:13:08.257Z
Learning: Client components should begin files with 'use client' and use React hooks for interactivity.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Files for components should be named in PascalCase and use the '.client.tsx' suffix if interactive.
Learnt from: MananTank
PR: thirdweb-dev/js#7434
File: apps/dashboard/src/app/(app)/team/~/~/contract/[chain]/[contractAddress]/components/project-selector.tsx:62-76
Timestamp: 2025-06-24T21:38:03.155Z
Learning: In the project-selector.tsx component for contract imports, the addToProject.mutate() call is intentionally not awaited (fire-and-forget pattern) to allow immediate navigation to the contract page while the import happens in the background. This is a deliberate design choice to prioritize user experience.
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-25T02:13:08.257Z
Learning: For new UI components, add Storybook stories (*.stories.tsx) alongside the code.
Learnt from: jnsdls
PR: thirdweb-dev/js#7364
File: apps/dashboard/src/app/(app)/account/components/AccountHeader.tsx:36-41
Timestamp: 2025-06-18T02:13:34.500Z
Learning: In the logout flow in apps/dashboard/src/app/(app)/account/components/AccountHeader.tsx, when `doLogout()` fails, the cleanup steps (resetAnalytics(), wallet disconnect, router refresh) should NOT execute. This is intentional to maintain consistency - if server-side logout fails, client-side cleanup should not occur.
Learnt from: MananTank
PR: thirdweb-dev/js#7227
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/OpenEditionMetadata.tsx:26-26
Timestamp: 2025-05-30T17:14:25.332Z
Learning: The ModuleCardUIProps interface already includes a client prop of type ThirdwebClient, so when components use `Omit<ModuleCardUIProps, "children" | "updateButton">`, they inherit the client prop without needing to add it explicitly.
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/page.tsx (12)
Learnt from: jnsdls
PR: thirdweb-dev/js#6929
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx:14-19
Timestamp: 2025-05-21T05:17:31.283Z
Learning: In Next.js server components, the `params` object can sometimes be a Promise that needs to be awaited, despite type annotations suggesting otherwise. In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx, it's necessary to await the params object before accessing its properties.
Learnt from: jnsdls
PR: thirdweb-dev/js#7363
File: apps/dashboard/src/app/(app)/layout.tsx:63-74
Timestamp: 2025-06-18T02:01:06.006Z
Learning: In Next.js applications, instrumentation files (instrumentation.ts or instrumentation-client.ts) placed in the src/ directory are automatically handled by the framework and included in the client/server bundles without requiring manual imports. The framework injects these files as part of the build process.
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:153-226
Timestamp: 2025-06-10T00:50:20.795Z
Learning: In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx, the updateStatus function correctly expects a complete MultiStepState["status"] object. For pending states, { type: "pending" } is the entire status object. For error states, { type: "error", message: React.ReactNode } is the entire status object. The current code incorrectly spreads the entire step object instead of passing just the status object.
Learnt from: MananTank
PR: thirdweb-dev/js#7152
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/(marketplace)/direct-listings/shared-direct-listings-page.tsx:47-52
Timestamp: 2025-05-26T16:29:54.317Z
Learning: The `projectMeta` prop is not required for the server-rendered `ContractDirectListingsPage` component in the direct listings shared page, following the same pattern as other server components in the codebase where `projectMeta` is only needed for client components.
Learnt from: MananTank
PR: thirdweb-dev/js#7434
File: apps/dashboard/src/app/(app)/team/~/~/contract/[chain]/[contractAddress]/components/project-selector.tsx:62-76
Timestamp: 2025-06-24T21:38:03.155Z
Learning: In the project-selector.tsx component for contract imports, the addToProject.mutate() call is intentionally not awaited (fire-and-forget pattern) to allow immediate navigation to the contract page while the import happens in the background. This is a deliberate design choice to prioritize user experience.
Learnt from: MananTank
PR: thirdweb-dev/js#7152
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/tokens/shared-page.tsx:41-48
Timestamp: 2025-05-26T16:28:50.772Z
Learning: The `projectMeta` prop is not required for the server-rendered `ContractTokensPage` component in the tokens shared page, unlike some other shared pages where it's needed for consistency.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Files for components should be named in PascalCase and use the '.client.tsx' suffix if interactive.
Learnt from: MananTank
PR: thirdweb-dev/js#7227
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/OpenEditionMetadata.tsx:26-26
Timestamp: 2025-05-30T17:14:25.332Z
Learning: The ModuleCardUIProps interface already includes a client prop of type ThirdwebClient, so when components use `Omit<ModuleCardUIProps, "children" | "updateButton">`, they inherit the client prop without needing to add it explicitly.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Client components must begin with 'use client'; before imports to ensure correct rendering behavior in Next.js.
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-25T02:13:08.257Z
Learning: Client components should begin files with 'use client' and use React hooks for interactivity.
Learnt from: MananTank
PR: thirdweb-dev/js#7152
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/analytics/shared-analytics-page.tsx:33-39
Timestamp: 2025-05-26T16:30:24.965Z
Learning: In the thirdweb dashboard codebase, redirectToContractLandingPage function already handles execution termination internally (likely using Next.js redirect() which throws an exception), so no explicit return statement is needed after calling it.
Learnt from: MananTank
PR: thirdweb-dev/js#7152
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/claim-conditions/shared-claim-conditions-page.tsx:43-49
Timestamp: 2025-05-26T16:31:02.480Z
Learning: In the thirdweb dashboard codebase, when `redirectToContractLandingPage()` is called, an explicit return statement is not required afterward because the function internally calls Next.js's `redirect()` which throws an error to halt execution.
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/layout.tsx (8)
Learnt from: jnsdls
PR: thirdweb-dev/js#6929
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx:14-19
Timestamp: 2025-05-21T05:17:31.283Z
Learning: In Next.js server components, the `params` object can sometimes be a Promise that needs to be awaited, despite type annotations suggesting otherwise. In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx, it's necessary to await the params object before accessing its properties.
Learnt from: jnsdls
PR: thirdweb-dev/js#7188
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/components/accounts-count.tsx:15-15
Timestamp: 2025-05-29T00:46:09.063Z
Learning: In the accounts component at apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/components/accounts-count.tsx, the 3-column grid layout (md:grid-cols-3) is intentionally maintained even when rendering only one StatCard, as part of the design structure for this component.
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:155-160
Timestamp: 2025-06-10T00:46:58.580Z
Learning: In the dashboard application, the route structure for team and project navigation is `/team/[team_slug]/[project_slug]/...` without a `/project/` segment. Contract links should be formatted as `/team/${teamSlug}/${projectSlug}/contract/${chainId}/${contractAddress}`.
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:153-226
Timestamp: 2025-06-10T00:50:20.795Z
Learning: In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx, the updateStatus function correctly expects a complete MultiStepState["status"] object. For pending states, { type: "pending" } is the entire status object. For error states, { type: "error", message: React.ReactNode } is the entire status object. The current code incorrectly spreads the entire step object instead of passing just the status object.
Learnt from: MananTank
PR: thirdweb-dev/js#7152
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/page.tsx:2-10
Timestamp: 2025-05-26T16:28:10.079Z
Learning: In Next.js 14+, the `params` object in page components is always a Promise that needs to be awaited, so the correct typing is `params: Promise<ParamsType>` rather than `params: ParamsType`.
Learnt from: MananTank
PR: thirdweb-dev/js#7152
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/nfts/page.tsx:20-20
Timestamp: 2025-05-26T16:26:58.068Z
Learning: In team/project contract pages under routes like `/team/[team_slug]/[project_slug]/contract/[chainIdOrSlug]/[contractAddress]/*`, users are always logged in by design. The hardcoded `isLoggedIn={true}` prop in these pages is intentional and correct, not a bug to be fixed.
Learnt from: MananTank
PR: thirdweb-dev/js#7434
File: apps/dashboard/src/app/(app)/team/~/~/contract/[chain]/[contractAddress]/components/project-selector.tsx:62-76
Timestamp: 2025-06-24T21:38:03.155Z
Learning: In the project-selector.tsx component for contract imports, the addToProject.mutate() call is intentionally not awaited (fire-and-forget pattern) to allow immediate navigation to the contract page while the import happens in the background. This is a deliberate design choice to prioritize user experience.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Client components must begin with 'use client'; before imports to ensure correct rendering behavior in Next.js.
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/order-summary.tsx (2)
Learnt from: jnsdls
PR: thirdweb-dev/js#7188
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/components/accounts-count.tsx:15-15
Timestamp: 2025-05-29T00:46:09.063Z
Learning: In the accounts component at apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/accounts/components/accounts-count.tsx, the 3-column grid layout (md:grid-cols-3) is intentionally maintained even when rendering only one StatCard, as part of the design structure for this component.
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:153-226
Timestamp: 2025-06-10T00:50:20.795Z
Learning: In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx, the updateStatus function correctly expects a complete MultiStepState["status"] object. For pending states, { type: "pending" } is the entire status object. For error states, { type: "error", message: React.ReactNode } is the entire status object. The current code incorrectly spreads the entire step object instead of passing just the status object.
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/service-selector.tsx (5)
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:153-226
Timestamp: 2025-06-10T00:50:20.795Z
Learning: In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx, the updateStatus function correctly expects a complete MultiStepState["status"] object. For pending states, { type: "pending" } is the entire status object. For error states, { type: "error", message: React.ReactNode } is the entire status object. The current code incorrectly spreads the entire step object instead of passing just the status object.
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-25T02:13:08.257Z
Learning: For new UI components, add Storybook stories (*.stories.tsx) alongside the code.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Files for components should be named in PascalCase and use the '.client.tsx' suffix if interactive.
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-25T02:13:08.257Z
Learning: Group feature-specific components under feature/components/* with a barrel index.ts.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Prefer composable UI primitives (Button, Input, Select, Tabs, Card, Sidebar, Separator, Badge) over custom markup for maintainability and design consistency.
apps/dashboard/src/@/components/blocks/UpsellBannerCard.tsx (5)
Learnt from: MananTank
PR: thirdweb-dev/js#7227
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/modules/components/OpenEditionMetadata.tsx:26-26
Timestamp: 2025-05-30T17:14:25.332Z
Learning: The ModuleCardUIProps interface already includes a client prop of type ThirdwebClient, so when components use `Omit<ModuleCardUIProps, "children" | "updateButton">`, they inherit the client prop without needing to add it explicitly.
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:153-226
Timestamp: 2025-06-10T00:50:20.795Z
Learning: In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx, the updateStatus function correctly expects a complete MultiStepState["status"] object. For pending states, { type: "pending" } is the entire status object. For error states, { type: "error", message: React.ReactNode } is the entire status object. The current code incorrectly spreads the entire step object instead of passing just the status object.
Learnt from: jnsdls
PR: thirdweb-dev/js#7365
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.tsx:16-17
Timestamp: 2025-06-18T04:30:04.326Z
Learning: Next.js Link component fully supports both internal and external URLs and works appropriately with all standard anchor attributes including target="_blank", rel="noopener noreferrer", etc. Using Link for external URLs is completely appropriate and recommended.
Learnt from: jnsdls
PR: thirdweb-dev/js#7365
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/components/ProjectFTUX/ProjectFTUX.tsx:16-17
Timestamp: 2025-06-18T04:27:16.172Z
Learning: Next.js Link component supports external URLs without throwing errors. When used with absolute URLs (like https://...), it behaves like a regular anchor tag without client-side routing, but does not cause runtime crashes or errors as previously believed.
Learnt from: MananTank
PR: thirdweb-dev/js#7177
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/public-pages/erc20/_components/ContractHeader.tsx:26-43
Timestamp: 2025-05-29T10:49:52.981Z
Learning: In React image components, conditional rendering of the entire image container (e.g., `{props.image && <Img />}`) serves a different purpose than fallback handling. The conditional prevents rendering any image UI when no image metadata exists, while the fallback prop handles cases where image metadata exists but the image fails to load. This pattern is intentional to distinguish between "no image intended" vs "image intended but failed to load".
🧬 Code Graph Analysis (3)
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/page.tsx (1)
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/[chain_id]/page.tsx (1)
  • InfrastructurePage (3-12)
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/payment-frequency-selector.tsx (1)
apps/dashboard/src/@/components/ui/radio-group.tsx (1)
  • RadioGroupItemButton (75-75)
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/layout.tsx (2)
apps/dashboard/src/@/api/team.ts (1)
  • getTeamBySlug (13-32)
apps/dashboard/src/@/components/blocks/upsell-wrapper.tsx (1)
  • UpsellWrapper (34-74)
⏰ Context from checks skipped due to timeout of 90000ms (8)
  • GitHub Check: Size
  • GitHub Check: Unit Tests
  • GitHub Check: E2E Tests (pnpm, esbuild)
  • GitHub Check: E2E Tests (pnpm, vite)
  • GitHub Check: E2E Tests (pnpm, webpack)
  • GitHub Check: Build Packages
  • GitHub Check: Lint Packages
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (27)
biome.json (1)

2-2: Ensure the toolchain is upgraded to Biome 2.0.4+

The schema bump is fine, but editors/CI will complain if the locally installed @biomejs/biome CLI is still on 2.0.0.
Please verify the root package.json (or each workspace) pins @biomejs/biome ≥ 2.0.4 before this lands.

packages/insight/biome.json (1)

2-2: Same schema bump as the root file; handled by the earlier comment. No further feedback.

packages/service-utils/biome.json (1)

2-2: Same schema bump as the root file; handled by the earlier comment. No further feedback.

packages/nebula/biome.json (1)

2-2: Same schema bump as the root file; handled by the earlier comment. No further feedback.

packages/engine/biome.json (1)

2-2: Same schema bump as the root file; handled by the earlier comment. No further feedback.

apps/wallet-ui/biome.json (1)

2-2: Verify Biome CLI/tooling is on ≥ 2.0.4 before merging

The schema bump is harmless, but config validation will fail locally/CI if any environment is still pinned to 2.0.0. Double-check the version in package.json / lockfiles or CI images.

apps/portal/biome.json (1)

2-2: Confirm portal build pipeline uses Biome 2.0.4

Same note as other apps: ensure the CLI version matches the new schema to avoid lint/format errors in CI.

packages/thirdweb/biome.json (1)

2-2: SDK package also needs Biome 2.0.4 in dev-deps

Updating the schema without bumping the dev dependency may break pnpm lint for package authors. Verify the root workspace has the correct version.

apps/dashboard/biome.json (1)

2-2: Dashboard app: check Docker/CI image for Biome version drift

If the dashboard is built inside a container, ensure the image was rebuilt with Biome 2.0.4; otherwise schema validation will complain.

apps/playground-web/biome.json (1)

2-2: Playground-web: sync local VSCode extension + CI to Biome 2.0.4

Developers’ editors and CI must understand the new schema; confirm extension/update is applied.

packages/vault-sdk/biome.json (1)

2-2: Schema version bump looks good

The config now references the 2.0.4 schema, matching the rest of the repo. No further action required as long as the CI environment is already running Biome ≥ 2.0.4.

packages/wagmi-adapter/biome.json (1)

2-2: Consistent schema upgrade

Upgrade to 2.0.4 keeps the wagmi-adapter package aligned with the global tooling.

packages/react-native-adapter/biome.json (1)

2-2: LGTM – schema reference updated

Nothing else changed; integration with the React-Native adapter remains unaffected.

apps/nebula/biome.json (1)

2-2: Nebula biome.json updated correctly

The schema URL now points to 2.0.4, in sync with other apps.

apps/dashboard/src/@/icons/ChainIcon.tsx (1)

33-33: LGTM! Semantic improvement for skeleton placeholder.

The change from <div> to <span> is appropriate since spans are inline elements better suited for icon placeholders while maintaining the same styling and animation behavior.

apps/dashboard/src/@/components/blocks/NetworkSelectors.tsx (3)

155-155: LGTM! Proper prop addition.

The optional disableDeprecated prop is well-typed and follows the established pattern of other boolean filter props in this component.


173-175: LGTM! Correct filtering implementation.

The filtering logic properly excludes chains with deprecated status, using the standard filtering pattern consistent with other conditional filters in this component.


178-183: LGTM! Proper dependency array update.

The dependency array correctly includes disableDeprecated to ensure the memoized chainsToShow recalculates when the filter option changes.

apps/dashboard/src/app/(app)/team/[team_slug]/(team)/layout.tsx (2)

9-9: LGTM! Proper UI primitive import.

Badge component correctly imported from the central UI library, following established coding guidelines.


90-97: LGTM! Well-structured tab addition.

The Infrastructure tab implementation follows the established pattern with proper JSX structure for the name prop containing the Badge component. The routing path is consistent with other team navigation tabs.

apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/page.tsx (1)

4-8: LGTM! Proper server component pattern.

The implementation correctly follows the established server component pattern by initializing the client on the server side and passing it to the client component.

Verify team context handling.

Since this page is in the team route structure (/team/[team_slug]/...), ensure that the InfrastructureCheckout component can access the necessary team context. If team information is required, consider extracting the team_slug from params.

#!/bin/bash
# Description: Check if InfrastructureCheckout component needs team context
# Expected: Find usage of team context or team_slug in the checkout component

ast-grep --pattern $'function InfrastructureCheckout($$$) {
  $$$
}'

# Also check for any team-related props or usage
rg -A 10 -B 5 "team" apps/dashboard/src/app/\(app\)/team/\[team_slug\]/\(team\)/~/infrastructure/deploy/_components/checkout.tsx
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/[chain_id]/page.tsx (1)

3-12: LGTM! Clean implementation following Next.js 14+ patterns.

The component correctly awaits the params Promise and uses the existing getChain utility. The implementation is straightforward and follows the established patterns in the codebase.

apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/layout.tsx (1)

8-46: LGTM! Well-structured layout with proper access control.

The component correctly:

  • Awaits params following Next.js 14+ patterns
  • Fetches team data and handles missing teams gracefully
  • Implements proper billing plan access control via UpsellWrapper
  • Uses consistent team route structure for the deploy button link
  • Follows the established UI component patterns
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/payment-frequency-selector.tsx (1)

4-47: LGTM! Clean and well-structured payment frequency selector.

The component effectively uses UI primitives and follows good practices:

  • Clear type definitions with PaymentFrequency export
  • Responsive grid layout for different screen sizes
  • Proper use of RadioGroup with controlled state
  • Good visual hierarchy with discount badge for annual option
  • Consistent styling patterns with data attributes
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/checkout.tsx (1)

1-206: LGTM! Comprehensive and well-structured checkout flow.

This is an excellent implementation of a multi-step infrastructure deployment checkout:

Strengths:

  • Correct use of "use client" directive and React hooks
  • Well-organized service configuration with clear pricing and features
  • Proper state management for chain, services, and payment frequency
  • Good responsive design with logical grid layout
  • Appropriate use of ClientOnly wrapper for client-side components
  • Clear step-by-step UI with badges and descriptions
  • Comprehensive order summary with chain details and fallback states
  • Follows established patterns from the codebase

Architecture:

  • Clean separation of concerns with imported child components
  • Good use of existing UI primitives (Card, Badge, etc.)
  • Proper handling of derived state with useMemo
  • RPC service correctly marked as required and pre-selected
apps/dashboard/src/@/components/blocks/UpsellBannerCard.tsx (1)

41-136: LGTM! Well-implemented discriminated union for CTA variants.

The update effectively supports both link-based and callback-based CTAs:

Good practices:

  • Clean discriminated union type definition using presence of target vs onClick
  • Proper conditional rendering logic to distinguish between variants
  • Correct security attributes (rel="noopener noreferrer") for external links
  • Consistent styling and icon handling across both variants
  • Follows established component patterns in the codebase

The type-safe approach ensures proper usage of each CTA variant while maintaining backward compatibility.

apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/order-summary.tsx (1)

156-158: Add null safety for service access.

The code uses optional chaining for service?.monthlyPrice but doesn't handle the case where service itself might be null/undefined in the filter.

  const baseMonthlyTotal = selectedServices.reduce((total, service) => {
-    return total + (service?.monthlyPrice || 0);
+    return total + (service?.monthlyPrice ?? 0);
-  }, 0);
+  }, 0);

Consider filtering out null services before the reduce operation:

  const baseMonthlyTotal = selectedServices
+    .filter(Boolean)
+    .reduce((total, service) => {
-    return total + (service?.monthlyPrice || 0);
+      return total + service.monthlyPrice;
    }, 0);
⛔ Skipped due to learnings
Learnt from: MananTank
PR: thirdweb-dev/js#7177
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/public-pages/erc20/_hooks/useTokenPriceData.ts:49-49
Timestamp: 2025-05-27T19:55:25.056Z
Learning: In the ERC20 public pages token price data hook (`useTokenPriceData.ts`), direct array access on `json.data[0]` without optional chaining is intentionally correct and should not be changed to use safety checks.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (2)
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/service-selector.tsx (2)

53-53: Use ID-based comparison instead of object reference equality.

The current implementation uses includes() which relies on reference equality. This may fail if service objects are recreated with the same data but different references.

-          const isSelected = props.selectedServices.includes(service);
+          const isSelected = props.selectedServices.some(s => s.id === service.id);

84-90: Remove redundant null check.

The nextServiceToAdd is already checked to be truthy in the ternary condition on line 82, making the inner null check redundant.

                onClick: () => {
-                  if (nextServiceToAdd) {
                    props.setSelectedServices([
                      ...props.selectedServices,
                      nextServiceToAdd,
                    ]);
-                  }
                },
🧹 Nitpick comments (1)
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/service-selector.tsx (1)

138-138: Consider edge case handling for zero pricing.

While unlikely in this context, the pricing display doesn't handle edge cases where monthlyPrice might be 0. Consider if this scenario needs special handling or messaging.

-              ${props.service.monthlyPrice.toLocaleString()}
+              {props.service.monthlyPrice === 0 ? 'Free' : `$${props.service.monthlyPrice.toLocaleString()}`}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 71255ca and f9d44a0.

📒 Files selected for processing (26)
  • apps/dashboard/biome.json (1 hunks)
  • apps/dashboard/src/@/components/blocks/NetworkSelectors.tsx (2 hunks)
  • apps/dashboard/src/@/components/blocks/UpsellBannerCard.tsx (2 hunks)
  • apps/dashboard/src/@/icons/ChainIcon.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/layout.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/[chain_id]/page.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/checkout.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/order-summary.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/payment-frequency-selector.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/service-selector.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/page.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/layout.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/page.tsx (1 hunks)
  • apps/nebula/biome.json (1 hunks)
  • apps/playground-web/biome.json (1 hunks)
  • apps/portal/biome.json (1 hunks)
  • apps/wallet-ui/biome.json (1 hunks)
  • biome.json (1 hunks)
  • packages/engine/biome.json (1 hunks)
  • packages/insight/biome.json (1 hunks)
  • packages/nebula/biome.json (1 hunks)
  • packages/react-native-adapter/biome.json (1 hunks)
  • packages/service-utils/biome.json (1 hunks)
  • packages/thirdweb/biome.json (1 hunks)
  • packages/vault-sdk/biome.json (1 hunks)
  • packages/wagmi-adapter/biome.json (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (25)
  • apps/dashboard/biome.json
  • packages/wagmi-adapter/biome.json
  • biome.json
  • apps/portal/biome.json
  • packages/service-utils/biome.json
  • packages/thirdweb/biome.json
  • packages/engine/biome.json
  • packages/insight/biome.json
  • apps/wallet-ui/biome.json
  • packages/vault-sdk/biome.json
  • packages/nebula/biome.json
  • packages/react-native-adapter/biome.json
  • apps/nebula/biome.json
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/layout.tsx
  • apps/playground-web/biome.json
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/page.tsx
  • apps/dashboard/src/@/components/blocks/NetworkSelectors.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/[chain_id]/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/payment-frequency-selector.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/checkout.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/layout.tsx
  • apps/dashboard/src/@/icons/ChainIcon.tsx
  • apps/dashboard/src/@/components/blocks/UpsellBannerCard.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/order-summary.tsx
🧰 Additional context used
📓 Path-based instructions (1)
`**/*.@(ts|tsx)`: Accept a typed 'props' object and export a named function (e.g...

**/*.@(ts|tsx): Accept a typed 'props' object and export a named function (e.g., export function MyComponent()).
Combine class names via 'cn', expose 'className' prop if useful.
Reuse core UI primitives; avoid re-implementing buttons, cards, modals.
Local state or effects live inside; data fetching happens in hooks.
Merge class names with 'cn' from '@/lib/utils' to keep conditional logic readable.
Stick to design-tokens: background ('bg-card'), borders ('border-border'), muted text ('text-muted-foreground') etc.
Use the 'container' class with a 'max-w-7xl' cap for page width consistency.
Spacing utilities ('px-', 'py-', 'gap-*') are preferred over custom margins.
Responsive helpers follow mobile-first ('max-sm', 'md', 'lg', 'xl').
Never hard-code colors – always go through Tailwind variables.
Tailwind CSS is the styling system – avoid inline styles or CSS modules.
Prefix files with 'import "server-only";' so they never end up in the client bundle (for server-only code).

📄 Source: CodeRabbit Inference Engine (.cursor/rules/dashboard.mdc)

List of files the instruction was applied to:

  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/service-selector.tsx
🧠 Learnings (2)
📓 Common learnings
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:155-160
Timestamp: 2025-06-10T00:46:58.580Z
Learning: In the dashboard application, the route structure for team and project navigation is `/team/[team_slug]/[project_slug]/...` without a `/project/` segment. Contract links should be formatted as `/team/${teamSlug}/${projectSlug}/contract/${chainId}/${contractAddress}`.
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:153-226
Timestamp: 2025-06-10T00:50:20.795Z
Learning: In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx, the updateStatus function correctly expects a complete MultiStepState["status"] object. For pending states, { type: "pending" } is the entire status object. For error states, { type: "error", message: React.ReactNode } is the entire status object. The current code incorrectly spreads the entire step object instead of passing just the status object.
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/service-selector.tsx (5)
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:153-226
Timestamp: 2025-06-10T00:50:20.795Z
Learning: In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx, the updateStatus function correctly expects a complete MultiStepState["status"] object. For pending states, { type: "pending" } is the entire status object. For error states, { type: "error", message: React.ReactNode } is the entire status object. The current code incorrectly spreads the entire step object instead of passing just the status object.
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-25T02:13:08.257Z
Learning: For new UI components, add Storybook stories (*.stories.tsx) alongside the code.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Files for components should be named in PascalCase and use the '.client.tsx' suffix if interactive.
Learnt from: jnsdls
PR: thirdweb-dev/js#6929
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx:14-19
Timestamp: 2025-05-21T05:17:31.283Z
Learning: In Next.js server components, the `params` object can sometimes be a Promise that needs to be awaited, despite type annotations suggesting otherwise. In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx, it's necessary to await the params object before accessing its properties.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-23T13:49:58.951Z
Learning: Prefer composable UI primitives (Button, Input, Select, Tabs, Card, Sidebar, Separator, Badge) over custom markup for maintainability and design consistency.
🧬 Code Graph Analysis (1)
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/service-selector.tsx (1)
apps/dashboard/src/@/components/blocks/UpsellBannerCard.tsx (1)
  • UpsellBannerCard (57-140)
⏰ Context from checks skipped due to timeout of 90000ms (7)
  • GitHub Check: E2E Tests (pnpm, esbuild)
  • GitHub Check: E2E Tests (pnpm, vite)
  • GitHub Check: E2E Tests (pnpm, webpack)
  • GitHub Check: Size
  • GitHub Check: Unit Tests
  • GitHub Check: Build Packages
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (3)
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/service-selector.tsx (3)

9-20: Type definitions look well-structured.

The Service union type and ServiceConfig interface are properly defined and provide good type safety. The interface covers all necessary service metadata including pricing, features, and UI elements.


27-32: Good use of useMemo for performance optimization.

The nextServiceToAdd computation correctly uses ID-based comparison and is properly memoized with appropriate dependencies.


106-157: ServiceCheckboxCard component follows best practices.

The component properly:

  • Uses semantic HTML with Label for accessibility
  • Implements conditional styling with cn() utility
  • Handles required services appropriately by disabling interaction
  • Uses design system components (Checkbox, Badge)
  • Applies responsive design patterns with lg: prefixes

Copy link

codecov bot commented Jun 27, 2025

Codecov Report

Attention: Patch coverage is 96.96970% with 1 line in your changes missing coverage. Please review.

Project coverage is 51.96%. Comparing base (f1a965b) to head (aec866a).
Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
...ges/thirdweb/src/react/web/ui/components/Modal.tsx 96.96% 1 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main    #7456   +/-   ##
=======================================
  Coverage   51.96%   51.96%           
=======================================
  Files         952      952           
  Lines       64224    64224           
  Branches     4237     4239    +2     
=======================================
  Hits        33377    33377           
  Misses      30740    30740           
  Partials      107      107           
Flag Coverage Δ
packages 51.96% <96.96%> (ø)
Files with missing lines Coverage Δ
...ges/thirdweb/src/react/web/ui/components/Modal.tsx 92.99% <96.96%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@jnsdls jnsdls force-pushed the 06-26-self-serve_infra_deployment branch from 4bd0809 to ae2e3de Compare June 27, 2025 06:17
@jnsdls jnsdls force-pushed the 06-26-self-serve_infra_deployment branch from 744b7d3 to 2ba67fb Compare July 3, 2025 06:27
@jnsdls jnsdls force-pushed the 06-26-self-serve_infra_deployment branch from 2ba67fb to 21a2a3f Compare July 3, 2025 23:17
@jnsdls jnsdls force-pushed the 06-26-self-serve_infra_deployment branch from 21a2a3f to e71e41f Compare July 3, 2025 23:53
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/deploy-infrastructure-form.client.tsx (1)

65-69: The service availability validation is still missing.

The component accepts a chain prop of type ChainMetadataWithServices but doesn't validate whether the selected services are actually available for this specific chain before allowing checkout. This was previously flagged but not yet implemented.

🧹 Nitpick comments (1)
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/deploy-infrastructure-form.client.tsx (1)

385-459: Consider extracting ServiceCard to a separate component file.

The ServiceCard component is well-implemented but is quite substantial (75 lines). Consider extracting it to a separate file for better maintainability and reusability across the codebase.

// Create a new file: service-card.tsx
+import { Badge } from "@/components/ui/badge";
+import { cn } from "@/lib/utils";
+import { RPCIcon, InsightIcon, SmartAccountIcon } from "@/icons";
+
+export function ServiceCard(props: ServiceCardProps) {
+  // ... existing ServiceCard implementation
+}

Then import and use it in the main file:

-// --- Service Card Component ---
-type IconKey = "RPCIcon" | "InsightIcon" | "SmartAccountIcon";
-// ... ServiceCard implementation
+import { ServiceCard } from "./service-card";
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e71e41f and aec866a.

📒 Files selected for processing (55)
  • apps/dashboard/src/@/actions/billing.ts (3 hunks)
  • apps/dashboard/src/@/api/ecosystems.ts (2 hunks)
  • apps/dashboard/src/@/api/team-subscription.ts (4 hunks)
  • apps/dashboard/src/@/components/blocks/NetworkSelectors.tsx (2 hunks)
  • apps/dashboard/src/@/components/blocks/UpsellBannerCard.tsx (2 hunks)
  • apps/dashboard/src/@/components/blocks/full-width-sidebar-layout.tsx (1 hunks)
  • apps/dashboard/src/@/icons/ChainIcon.tsx (1 hunks)
  • apps/dashboard/src/@/storybook/stubs.ts (3 hunks)
  • apps/dashboard/src/@/types/billing.ts (1 hunks)
  • apps/dashboard/src/app/(app)/(dashboard)/explore/components/contract-row/index.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/TeamSidebarLayout.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/layout.tsx (3 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/billing/layout.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/analytics/components/EcosystemAnalyticsPage.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/analytics/components/EcosystemWalletUsersChartCard.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/analytics/page.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/components/EcosystemSlugLayout.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/components/ecosystem-header.client.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/add-partner/page.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/components/client/AddPartnerDialogButton.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/components/client/add-partner-form.client.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/components/client/auth-options-form.client.tsx (3 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/components/client/integration-permissions-toggle.client.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/components/client/partner-form.client.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/components/client/update-partner-form.client.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/components/server/auth-options-section.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/components/server/ecosystem-partners-section.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/components/server/integration-permissions-section.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/components/server/partners-table.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/hooks/fetchEcosystem.ts (0 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/hooks/fetchPartnerDetails.ts (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/hooks/fetchPartners.ts (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/hooks/use-add-partner.ts (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/hooks/use-delete-partner.ts (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/hooks/use-update-ecosystem.ts (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/hooks/use-update-partner.ts (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/partners/[partner_id]/edit/page.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/hooks/use-ecosystem.ts (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/hooks/use-partners.ts (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/create/actions/create-ecosystem.ts (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/page.tsx (2 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/utils/fetchEcosystem.ts (0 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/utils/fetchEcosystemList.ts (0 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/[chain_id]/_components/service-card.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/[chain_id]/page.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/[chain_id]/page.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/deploy-infrastructure-form.client.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/page.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/search-params.ts (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/layout.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/usage/layout.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/nft/sales/sales-settings.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/analytics/ftux.client.tsx (1 hunks)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/wallets/settings/components/index.tsx (1 hunks)
  • packages/thirdweb/src/react/web/ui/components/Modal.tsx (7 hunks)
💤 Files with no reviewable changes (3)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/utils/fetchEcosystem.ts
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/utils/fetchEcosystemList.ts
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/hooks/fetchEcosystem.ts
✅ Files skipped from review due to trivial changes (1)
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/hooks/use-update-ecosystem.ts
🚧 Files skipped from review as they are similar to previous changes (50)
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/transactions/analytics/ftux.client.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/analytics/components/EcosystemAnalyticsPage.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/analytics/components/EcosystemWalletUsersChartCard.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/components/server/auth-options-section.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/components/client/update-partner-form.client.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/hooks/use-update-partner.ts
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/hooks/fetchPartners.ts
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/components/server/partners-table.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/hooks/use-ecosystem.ts
  • apps/dashboard/src/app/(app)/(dashboard)/explore/components/contract-row/index.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/components/client/AddPartnerDialogButton.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/components/client/add-partner-form.client.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/hooks/use-partners.ts
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/hooks/use-delete-partner.ts
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/components/server/integration-permissions-section.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/billing/layout.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/create/actions/create-ecosystem.ts
  • apps/dashboard/src/@/icons/ChainIcon.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/usage/layout.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/components/client/integration-permissions-toggle.client.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/components/server/ecosystem-partners-section.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/tokens/create/nft/sales/sales-settings.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/wallets/settings/components/index.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/hooks/fetchPartnerDetails.ts
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/components/client/partner-form.client.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/search-params.ts
  • apps/dashboard/src/@/components/blocks/NetworkSelectors.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/add-partner/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/analytics/page.tsx
  • apps/dashboard/src/@/types/billing.ts
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/components/EcosystemSlugLayout.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/partners/[partner_id]/edit/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/hooks/use-add-partner.ts
  • apps/dashboard/src/@/components/blocks/full-width-sidebar-layout.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/components/ecosystem-header.client.tsx
  • apps/dashboard/src/@/storybook/stubs.ts
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/TeamSidebarLayout.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/ecosystem/[slug]/(active)/configuration/components/client/auth-options-form.client.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/layout.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/layout.tsx
  • apps/dashboard/src/@/actions/billing.ts
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/[chain_id]/page.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/page.tsx
  • packages/thirdweb/src/react/web/ui/components/Modal.tsx
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/[chain_id]/_components/service-card.tsx
  • apps/dashboard/src/@/components/blocks/UpsellBannerCard.tsx
  • apps/dashboard/src/@/api/ecosystems.ts
  • apps/dashboard/src/@/api/team-subscription.ts
  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/[chain_id]/page.tsx
🧰 Additional context used
📓 Path-based instructions (2)
`**/*.{ts,tsx}`: Write idiomatic TypeScript with explicit function declarations ...

**/*.{ts,tsx}: Write idiomatic TypeScript with explicit function declarations and return types
Limit each file to one stateless, single-responsibility function for clarity
Re-use shared types from @/types or local types.ts barrels
Prefer type aliases over interface except for nominal shapes
Avoid any and unknown unless unavoidable; narrow generics when possible
Choose composition over inheritance; leverage utility types (Partial, Pick, etc.)
Comment only ambiguous logic; avoid restating TypeScript in prose
Load heavy dependencies inside async paths to keep initial bundle lean (lazy loading)

📄 Source: CodeRabbit Inference Engine (CLAUDE.md)

List of files the instruction was applied to:

  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/deploy-infrastructure-form.client.tsx
`apps/{dashboard,playground-web}/**/*.{tsx,ts}`: Import UI primitives from `@/co...

apps/{dashboard,playground-web}/**/*.{tsx,ts}: Import UI primitives from @/components/ui/* (Button, Input, Select, Tabs, Card, Sidebar, Badge, Separator) in dashboard and playground apps
Use NavLink for internal navigation with automatic active states in dashboard and playground apps
Use Tailwind CSS only – no inline styles or CSS modules
Use cn() from @/lib/utils for conditional class merging
Use design system tokens (e.g., bg-card, border-border, text-muted-foreground)
Expose className prop on root element for overrides in UI components
Server Components (Node edge): Start files with import "server-only";
Server Components: Read cookies/headers with next/headers
Server Components: Access server-only environment variables
Server Components: Perform heavy data fetching
Server Components: Implement redirect logic with redirect() from next/navigation
Client Components (browser): Begin files with 'use client';
Client Components: Handle interactive UI with React hooks (useState, useEffect, React Query, wallet hooks)
Client Components: Access browser APIs (localStorage, window, IntersectionObserver)
Client Components: Support fast transitions with prefetched data
Server Side Data Fetching: Always call getAuthToken() to retrieve JWT from cookies
Server Side Data Fetching: Use Authorization: Bearer header – never embed tokens in URLs
Server Side Data Fetching: Return typed results (Project[], User[]) – avoid any
Client Side Data Fetching: Wrap calls in React Query (@tanstack/react-query)
Client Side Data Fetching: Use descriptive, stable queryKeys for cache hits
Client Side Data Fetching: Configure staleTime/cacheTime based on freshness (default ≥ 60s)
Client Side Data Fetching: Keep tokens secret via internal API routes or server actions
Analytics Events: Never import posthog-js in server components

📄 Source: CodeRabbit Inference Engine (CLAUDE.md)

List of files the instruction was applied to:

  • apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/deploy-infrastructure-form.client.tsx
🧠 Learnings (2)
📓 Common learnings
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T10:25:29.488Z
Learning: Surface breaking changes prominently in PR descriptions
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/deploy-infrastructure-form.client.tsx (29)
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-30T10:26:04.389Z
Learning: Applies to dashboard/**/components/*.client.tsx : Interactive UI that relies on hooks (`useState`, `useEffect`, React Query, wallet hooks).
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T10:25:29.489Z
Learning: Applies to apps/{dashboard,playground-web}/**/*.{tsx,ts} : Client Components: Handle interactive UI with React hooks (`useState`, `useEffect`, React Query, wallet hooks)
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T10:25:29.488Z
Learning: Applies to apps/{dashboard,playground-web}/**/*.{tsx,ts} : Import UI primitives from `@/components/ui/*` (Button, Input, Select, Tabs, Card, Sidebar, Badge, Separator) in dashboard and playground apps
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-30T10:26:04.389Z
Learning: Applies to dashboard/**/components/*.client.tsx : Anything that consumes hooks from `@tanstack/react-query` or thirdweb SDKs.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-30T10:26:04.389Z
Learning: Applies to dashboard/**/components/**/*.{ts,tsx} : For notices & skeletons rely on `AnnouncementBanner`, `GenericLoadingPage`, `EmptyStateCard`.
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T10:25:29.489Z
Learning: Applies to apps/{dashboard,playground-web}/**/*.{tsx,ts} : Client Components: Support fast transitions with prefetched data
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-30T10:26:04.389Z
Learning: Applies to dashboard/**/components/*.{tsx,client.tsx} : Name files after the component in PascalCase; append `.client.tsx` when interactive.
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T10:25:29.489Z
Learning: Applies to apps/{dashboard,playground-web}/**/*.{tsx,ts} : Server Components: Perform heavy data fetching
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T10:25:29.489Z
Learning: Applies to apps/{dashboard,playground-web}/**/*.{tsx,ts} : Client Components (browser): Begin files with `'use client';`
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-30T10:26:04.389Z
Learning: Applies to dashboard/**/components/**/*.{ts,tsx} : Reuse core UI primitives; avoid re-implementing buttons, cards, modals.
Learnt from: jnsdls
PR: thirdweb-dev/js#6929
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx:14-19
Timestamp: 2025-05-21T05:17:31.283Z
Learning: In Next.js server components, the `params` object can sometimes be a Promise that needs to be awaited, despite type annotations suggesting otherwise. In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/insight/webhooks/page.tsx, it's necessary to await the params object before accessing its properties.
Learnt from: MananTank
PR: thirdweb-dev/js#7177
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/public-pages/erc20/_hooks/useTokenTransfers.ts:41-44
Timestamp: 2025-05-27T19:56:16.920Z
Learning: When reviewing hooks that use environment variables like NEXT_PUBLIC_DASHBOARD_THIRDWEB_CLIENT_ID for API calls, MananTank prefers not to add explicit validation checks for these variables, trusting they will be set in the deployment environment.
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T10:25:29.488Z
Learning: Applies to **/*.test.{ts,tsx} : Use `FORKED_ETHEREUM_CHAIN` for mainnet interactions and `ANVIL_CHAIN` for isolated tests
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T10:25:29.488Z
Learning: Applies to apps/{dashboard,playground-web}/**/*.{tsx,ts} : Use `cn()` from `@/lib/utils` for conditional class merging
Learnt from: CR
PR: thirdweb-dev/js#0
File: CLAUDE.md:0-0
Timestamp: 2025-06-30T10:25:29.488Z
Learning: Applies to **/*.{ts,tsx} : Comment only ambiguous logic; avoid restating TypeScript in prose
Learnt from: MananTank
PR: thirdweb-dev/js#7315
File: apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx:153-226
Timestamp: 2025-06-10T00:50:20.795Z
Learning: In apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/(sidebar)/assets/create/nft/launch-nft.tsx, the updateStatus function correctly expects a complete MultiStepState["status"] object. For pending states, { type: "pending" } is the entire status object. For error states, { type: "error", message: React.ReactNode } is the entire status object. The current code incorrectly spreads the entire step object instead of passing just the status object.
Learnt from: jnsdls
PR: thirdweb-dev/js#7364
File: apps/dashboard/src/app/(app)/account/components/AccountHeader.tsx:36-41
Timestamp: 2025-06-18T02:13:34.500Z
Learning: In the logout flow in apps/dashboard/src/app/(app)/account/components/AccountHeader.tsx, when `doLogout()` fails, the cleanup steps (resetAnalytics(), wallet disconnect, router refresh) should NOT execute. This is intentional to maintain consistency - if server-side logout fails, client-side cleanup should not occur.
Learnt from: MananTank
PR: thirdweb-dev/js#7434
File: apps/dashboard/src/app/(app)/team/~/~/contract/[chain]/[contractAddress]/components/project-selector.tsx:62-76
Timestamp: 2025-06-24T21:38:03.155Z
Learning: In the project-selector.tsx component for contract imports, the addToProject.mutate() call is intentionally not awaited (fire-and-forget pattern) to allow immediate navigation to the contract page while the import happens in the background. This is a deliberate design choice to prioritize user experience.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-30T10:26:04.389Z
Learning: Applies to dashboard/**/pages/*.client.tsx : Pages requiring fast transitions where data is prefetched on the client.
Learnt from: MananTank
PR: thirdweb-dev/js#7152
File: apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/claim-conditions/shared-claim-conditions-page.tsx:43-49
Timestamp: 2025-05-26T16:31:02.480Z
Learning: In the thirdweb dashboard codebase, when `redirectToContractLandingPage()` is called, an explicit return statement is not required afterward because the function internally calls Next.js's `redirect()` which throws an error to halt execution.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-30T10:26:04.389Z
Learning: Applies to dashboard/**/components/**/*.{ts,tsx} : Local state or effects live inside; data fetching happens in hooks.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-30T10:26:04.389Z
Learning: Applies to dashboard/**/components/**/*.{ts,tsx} : Always import from the central UI library under `@/components/ui/*` – e.g. `import { Button } from "@/components/ui/button"`.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-30T10:26:04.389Z
Learning: Applies to dashboard/**/components/**/*.{ts,tsx} : Prefer composable primitives over custom markup: `Button`, `Input`, `Select`, `Tabs`, `Card`, `Sidebar`, `Separator`, `Badge`.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-30T10:26:04.389Z
Learning: Applies to dashboard/**/components/**/*.{ts,tsx} : Icons come from `lucide-react` or the project-specific `…/icons` exports – never embed raw SVG.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-30T10:26:04.389Z
Learning: Applies to dashboard/**/components/**/*.{ts,tsx} : Use `NavLink` (`@/components/ui/NavLink`) for internal navigation so active states are handled automatically.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-30T10:26:04.389Z
Learning: Applies to dashboard/**/components/**/*.{ts,tsx} : Stick to design-tokens: background (`bg-card`), borders (`border-border`), muted text (`text-muted-foreground`) etc.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-30T10:26:04.389Z
Learning: Applies to dashboard/**/components/*.client.tsx : Client components must start with `'use client';` before imports.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-30T10:26:04.389Z
Learning: Applies to dashboard/**/components/**/*.{ts,tsx} : Place the file close to its feature: `feature/components/MyComponent.tsx`.
Learnt from: CR
PR: thirdweb-dev/js#0
File: .cursor/rules/dashboard.mdc:0-0
Timestamp: 2025-06-30T10:26:04.389Z
Learning: Applies to dashboard/**/components/**/index.ts : Group related components in their own folder and expose a single barrel `index.ts` where necessary.
⏰ Context from checks skipped due to timeout of 90000ms (4)
  • GitHub Check: Unit Tests
  • GitHub Check: Lint Packages
  • GitHub Check: Build Packages
  • GitHub Check: Analyze (javascript)
🔇 Additional comments (2)
apps/dashboard/src/app/(app)/team/[team_slug]/(team)/~/infrastructure/deploy/_components/deploy-infrastructure-form.client.tsx (2)

19-61: LGTM: Well-structured service configuration.

The service configuration object is well-designed with proper TypeScript constraints using satisfies. The pricing structure is clear and the type safety ensures consistency across the codebase.


175-203: LGTM: Checkout function properly implemented.

The checkout function now correctly uses startTransition to wrap the async operation and includes proper error handling with user feedback via toast notifications.

@jnsdls jnsdls merged commit 0e159f7 into main Jul 4, 2025
25 checks passed
@jnsdls jnsdls deleted the 06-26-self-serve_infra_deployment branch July 4, 2025 00:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Dashboard Involves changes to the Dashboard. Ecosystem Portal Involves changes to the Ecosystem Portal packages Playground Changes involving the Playground codebase. Portal Involves changes to the Portal (docs) codebase. SDK Involves changes to the thirdweb SDK
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant