feat(platform): add first-visit tab intro cards for Agents, Marketplace, Build - #13805
Conversation
…ce, Build Introduce a shared TabIntroCard shell plus a per-tab wrapper that opens once per user on the Agents, Marketplace and Build tabs, gated behind the new onboarding-tab-intros flag (off by default). Dismissal is recorded as a per-tab onboarding step so the card stays gone across devices, with a user-scoped localStorage cache covering the window before that write lands. Build vetoes the card when deep-linked into a saved graph, so the intro is kept for a later blank canvas rather than burned.
|
/review |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📜 Recent review details⏰ Context from checks skipped due to timeout. (16)
WalkthroughThe PR adds first-visit introduction cards for the Agents, Marketplace, and Build tabs. It adds onboarding persistence, analytics, tab-specific actions, accessibility behavior, and backend validation. ChangesTab introduction onboarding
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant User
participant TabIntroCard
participant useTabIntroCard
participant Onboarding API
participant PostHog
User->>TabIntroCard: Select CTA or dismiss
TabIntroCard->>useTabIntroCard: Invoke action handler
useTabIntroCard->>Onboarding API: Complete tab-introduction step
useTabIntroCard->>PostHog: Capture onboarding event
Possibly related PRs
Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
🔍 PR Overlap DetectionThis check compares your PR against all other open PRs targeting the same branch to detect potential merge conflicts early. 🟢 Low Risk — File Overlap OnlyThese PRs touch the same files but different sections (click to expand)
Summary: 0 conflict(s), 0 medium risk, 4 low risk (out of 4 PRs with file overlap) Auto-generated on push. Ignores: |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (1)
autogpt_platform/frontend/src/app/(platform)/marketplace/components/FeaturedSection/FeaturedSection.tsx (1)
29-29: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winUse a function declaration for
FeaturedSection.Line 29 declares a React component with an arrow function. Use a function declaration for components.
Proposed fix
-export const FeaturedSection = ({ featuredAgents }: FeaturedSectionProps) => { +export function FeaturedSection({ featuredAgents }: FeaturedSectionProps) {As per coding guidelines, “Use function declarations (not arrow functions) for components/handlers.”
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@autogpt_platform/frontend/src/app/`(platform)/marketplace/components/FeaturedSection/FeaturedSection.tsx at line 29, Change the FeaturedSection component from an arrow-function assignment to a function declaration, preserving its FeaturedSectionProps parameter type, existing JSX, and export.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@autogpt_platform/frontend/src/app/`(platform)/components/TabIntroCard/TabIntroCard.tsx:
- Line 42: Update the dialog behavior in TabIntroCard, using an accessible
dialog primitive or implementing focus containment so Tab and Shift+Tab remain
within the open dialog while aria-modal="true" is active. Capture the previously
focused element when opening and restore focus to it on close, then add keyboard
tests covering focus trapping and restoration.
- Around line 46-55: Update the useEffect handling the Escape key in
TabIntroCard to include onDismiss in its dependency array, then remove the
react-hooks/exhaustive-deps suppression comment. Preserve the existing focus,
listener registration, and cleanup behavior.
In
`@autogpt_platform/frontend/src/app/`(platform)/components/TabIntroCard/useTabIntroCard.ts:
- Around line 32-35: Update the useEffect in useTabIntroCard to always
setIsFinished from the boolean result of peekTabIntroSeen(tab, userId), allowing
false to reset completion when tab or userId changes. Add a regression test
covering dismissal by user A, switching to user B, and rerendering to verify the
intro card is shown for user B.
---
Nitpick comments:
In
`@autogpt_platform/frontend/src/app/`(platform)/marketplace/components/FeaturedSection/FeaturedSection.tsx:
- Line 29: Change the FeaturedSection component from an arrow-function
assignment to a function declaration, preserving its FeaturedSectionProps
parameter type, existing JSX, and export.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 056f7714-6016-4a66-b85a-0c667d64f2ff
📒 Files selected for processing (19)
autogpt_platform/backend/backend/api/features/onboarding_step_test.pyautogpt_platform/backend/backend/data/onboarding_steps.pyautogpt_platform/frontend/src/app/(platform)/build/components/BuildTabIntro/BuildTabIntro.tsxautogpt_platform/frontend/src/app/(platform)/build/page.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/TabIntroCard.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/TabIntroCard.test.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/tab-intros.test.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/useTabIntroCard.test.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/helpers.tsautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/useTabIntroCard.tsautogpt_platform/frontend/src/app/(platform)/library/components/AgentsTabIntro/AgentsTabIntro.tsxautogpt_platform/frontend/src/app/(platform)/library/page.tsxautogpt_platform/frontend/src/app/(platform)/marketplace/components/FeaturedSection/FeaturedSection.tsxautogpt_platform/frontend/src/app/(platform)/marketplace/components/MainMarketplacePage/MainMarketplacePage.tsxautogpt_platform/frontend/src/app/(platform)/marketplace/components/MarketplaceTabIntro/MarketplaceTabIntro.tsxautogpt_platform/frontend/src/app/api/openapi.jsonautogpt_platform/frontend/src/lib/autogpt-server-api/types.tsautogpt_platform/frontend/src/services/feature-flags/use-get-flag.tsautogpt_platform/frontend/src/services/onboarding/tab-intro-analytics.ts
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## dev #13805 +/- ##
==========================================
+ Coverage 77.74% 77.90% +0.15%
==========================================
Files 2876 2914 +38
Lines 217618 219435 +1817
Branches 20707 20826 +119
==========================================
+ Hits 169191 170942 +1751
- Misses 43912 43951 +39
- Partials 4515 4542 +27
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
📋 Automated Review — PR #13805
PR #13805 — feat(platform): add first-visit tab intro cards for Agents, Marketplace, Build
Author: Abhi1992002 | Files: 19
🎯 Verdict: APPROVE
PR Description Quality
✅ Has Why + What + How — the description explains the goal (orient first-time users per tab), the mechanism (shared shell + per-tab wrappers, flag-gated, server + localStorage dismissal), and behavior (Build ?flowID= veto). Two manual-test checklist boxes remain unchecked (browser pass with flag forced on; config-changes) — the QA specialist has since covered the browser pass end-to-end.
What This PR Does
Adds a first-visit intro card to each of the Agents, Marketplace, and Build tabs — a single card with an icon, one-line description, one primary CTA, and one way out. The whole feature sits behind the ONBOARDING_TAB_INTROS LaunchDarkly flag (default off), and dismissal is recorded both server-side (three new additive OnboardingStep enum values) and in a user-id-keyed localStorage cache. The Build card vetoes itself when the user arrived via a ?flowID= deep link so it doesn't interrupt a targeted edit.
Specialist Findings
🛡️ Security ✅ — No user-controlled data reaches the rendered card (static literals through the Text atom, React-escaped), no SQL/raw Prisma/command execution, no secrets, no new endpoints. The three new steps are client-writable via POST /onboarding/step; the code marks them "unrewarded."
🔵 Confirm complete_onboarding_step grants no credits for the new steps so an authed user can't self-award (backend/data/onboarding_steps.py:61).
🏗️ Architecture ✅ — Clean render/gate/helpers split matching repo convention; shared shell + three thin wrappers is properly DRY; enum + Literal + openapi.json changes are additive and backward-compatible; flag isolation is correct. Consistent with the existing OnboardingWelcomeDialog pattern.
🟠 Reimplements modal mechanics instead of the molecules/Dialog primitive — propagates bespoke-modal debt and omits a focus trap (TabIntroCard.tsx:62).
⚡ Performance ✅ — Zero backend query surface (enum-only). All ops O(1). Only note: the three wrappers mount on every visit to high-traffic tabs and run a synchronous localStorage.getItem + context subscriptions even when the flag is off by default (useTabIntroCard.ts:26).
🧪 Testing ✅ — Strong for a feature PR: parametrized backend acceptance test, component suite, hook suite, and per-tab integration suite (CTA routing, veto, localStorage-throws). Gaps: focus-management claim untested, delayed-userId re-check path untested, no negative backend (422) case, Marketplace CTA missing its analytics assertion.
📖 Quality ✅ — Well-named, well-separated, thoroughly commented (arguably over per AGENTS.md). Convention gaps: altAction is a raw <button> while others use the Button atom; hardcoded gradient hex and !important font-size overrides instead of design tokens; loose string types on analytics cta/tab.
📦 Product ✅ — Behavior matches the description completely; happy-path and error handling (localStorage failure, blocked analytics, missing featured section) all graceful.
🟠 Marketplace CTA can silently do nothing when no agents are featured (MarketplaceTabIntro.tsx:17); accidental backdrop/Escape dismissal is permanent across devices.
📬 Discussion ✅ — CI green (40/42 success; chromatic skipped, Vercel Agent Review neutral), mergeable: clean, no line-level conflicts. Three unanswered CodeRabbit threads (one Major a11y focus-trap) + one nitpick; no human review submitted yet (PR is minutes old).
🔎 QA ✅ — Verified live end-to-end: backend accepts all three steps (200 + DB-persisted), rejects invalid (422) and unauthenticated (401); all three cards render, dismiss, record their per-tab step, and honor the ?flowID= veto without burning the step; localStorage cache is user-id-keyed as claimed. An early 500 was traced to a missing seeded platform.User row (env artifact — existing step BUILDER_OPEN reproduced it identically), not a PR defect.
QA Screenshots
🟠 Should Fix
- Dialog has no focus trap or focus restoration (
TabIntroCard.tsx:44) — declaresrole="dialog"+aria-modal="true"and moves focus in on open, butTab/Shift+Tabcan reach background controls and focus isn't restored on close. Thearia-modalclaim mismatches actual keyboard behavior. Add containment + restoration (or adoptmolecules/Dialog). (Flagged by: security, architect, testing, quality, product, discussion — 6 specialists) - Marketplace CTA can silently do nothing (
MarketplaceTabIntro.tsx:17) — "Browse featured agents" scrolls toFEATURED_SECTION_ID, but when nothing is featured the section isn't rendered, so the card just closes with no visible movement — undermining the orientation the card exists to provide. Hide/relabel the CTA or fall back to scrolling the store listing. (Flagged by: product; behavior codified by existing test) - In-session account switch doesn't reset
isFinished(useTabIntroCard.ts:35) — when the account changes without an unmount,isFinishedstays latched, so user B won't see their own intro that session. The existing "different account" test renders fresh and does not cover a live auth switch. Re-derive frompeekTabIntroSeen(tab, userId)onuserIdchange and add a regression test. (Flagged by: discussion/CodeRabbit) - Stale-closure / suppressed exhaustive-deps in Escape effect (
TabIntroCard.tsx:55) — effect disablesreact-hooks/exhaustive-depsand depends only on[isOpen]whileonDismissis recreated each render; a future change can silently break it. Store the latest callback in a ref (or add it to deps) and drop the disable. (Flagged by: architect, quality, discussion — 3 specialists) - Test gaps on claimed behaviors — no test asserts focus lands in the card on open (
TabIntroCard.test.tsx), no test for the delayed-userIdre-check (useTabIntroCard.ts:34), and no negative backend case proving a non-FrontendOnboardingStepvalue still 422s (onboarding_step_test.py:50). These lock in behaviors the PR explicitly relies on. (Flagged by: testing) - Design-system convention drift (
TabIntroCard.tsx:86,103) —altActionshould use theButtonatom (link/ghost variant) rather than a raw<button>, and the gradient should use design tokens rather than hardcoded hex (#e6dbff/#ddccff/#d0b9ff), per AGENTS.md. (Flagged by: architect, quality — 2 specialists)
🟡 Nice to Have
- Extract a shared onboarding modal shell onto
molecules/Dialogto consolidate this card andOnboardingWelcomeDialogand get a11y for free (TabIntroCard.tsx). (architect) - Tighten analytics types — type
ctaas a literal union and reuse the existingTabIntroTabfortab(useTabIntroCard.ts:66,tab-intro-analytics.ts:20). (quality) - Skip localStorage/context work when flag is off on the three high-traffic tabs (
useTabIntroCard.ts:26). (performance)
🔵 Nits
!text-[1.25rem]/!text-[0.9375rem]!importantoverrides fight theTextatom's variant sizing; magicz-[100]/ inline shadow — prefer tokens (TabIntroCard.tsx:96).- Unenforced "Capped at 20 words" JSDoc on
bodyreads as a constraint (TabIntroCard.tsx:20). FeaturedSectionuses an arrow function; repo convention wants a function declaration (FeaturedSection.tsx:29).- Weak
.toBeDefined()assertions wheretoBeInTheDocument()expresses intent (TabIntroCard.test.tsx,tab-intros.test.tsx). - Confirm the new steps grant no reward (
onboarding_steps.py:61).
Human Review Needed
NO — This is a flag-gated (default off), additive frontend UX feature plus a backward-compatible enum addition. No changes to authentication, credential/secret handling, or service trust boundaries. QA verified it end-to-end with DB evidence and screenshots.
Risk Assessment
Merge risk: LOW | Rollback: EASY (flag default off; additive enum values; single commit)
CI Status
GitHub CI: green per PR check status — 40/42 check-runs success, all commit statuses (Vercel, snyk, CLA, CodeRabbit) green; chromatic skipped and Vercel Agent Review neutral (neither a failure); mergeable: clean.
Local harness note: pnpm test:unit failed in the review sandbox, but GitHub CI ran the same suite green on this head SHA — this is environment skew (the sandbox shipped with an unseeded DB, per QA), not a PR defect. Lint, typecheck, and build all passed locally.
UI Testing — Variant Results
✅ local: All three tab intro cards render, dismiss, record their per-tab onboarding step, and honor the flowID veto; backend accepts the three new steps (422 on invalid, 401 unauthorized) — verified end-to-end with DB persistence and screenshots.
✅ hosted: All three tab intro cards render and function end-to-end with the flag on, backend accepts and persists the three new onboarding steps (200), negatives return 422/401, and the flowID veto plus once-only guarantee both hold — no defects found.
Accessibility - Trap Tab/Shift+Tab inside the intro card and restore focus to whatever opened it on close, so `aria-modal="true"` is honoured instead of merely declared. Covered by keyboard tests. - Drop the react-hooks/exhaustive-deps suppression on the Escape handler; the listener now reads `onDismiss` through a ref so it can never call a stale closure. Correctness - The first-visit gate no longer latches the localStorage cache into state. It is derived during render, which removes a one-frame window where a returning user's card opened (and reported `tab_intro_shown`) before their user id resolved. Dismissal is tracked per user id, so a second account signing in behind the same mounted hook still gets its own intro. - The cache read sits last in the gate, so a disabled flag never touches localStorage. - The Marketplace CTA falls back to the full listing when nothing is featured, instead of closing the card and moving nothing. Conventions - altAction renders through the Button atom; Text uses real variants rather than `!important` size overrides. - CTA identifiers and the analytics `tab` property are typed unions. - FeaturedSection is a function declaration. Flag - The tab intros ride the existing ONBOARDING_BRAIN_DUMP flag rather than one of their own, so they ship and roll back with the rest of the new onboarding. Tests - Backend: posting a rewarded, backend-only OnboardingStep still 422s, and the three tab-intro steps grant no credits. - Frontend: focus containment and restoration, analytics failure is swallowed, Marketplace CTA analytics, late-arriving user id, in-session account switch, and a single `tab_intro_shown` per open.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
autogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/TabIntroCard.tsx (1)
34-176: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy liftSplit
TabIntroCardby responsibility.
TabIntroCardcombines focus lifecycle logic and card rendering across more than 140 lines. Extract the focus lifecycle into a dedicateduseTabIntro...hook in its own.tsfile. Extract card presentation if needed to keep each render function and hook below the project target.As per coding guidelines, “Keep render functions and hooks under ~50 lines; extract named helpers or sub-components when they grow longer.” As per coding guidelines, “Separate render logic from business logic using component.tsx + useComponent.ts + helpers.ts pattern.”
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@autogpt_platform/frontend/src/app/`(platform)/components/TabIntroCard/TabIntroCard.tsx around lines 34 - 176, Split TabIntroCard responsibilities by extracting its focus lifecycle into a dedicated useTabIntro... hook in a separate .ts file, including focus restoration, Escape handling, and Tab trapping. Keep TabIntroCard focused on presentation and wire it to the hook through its existing dialogRef and isOpen state; extract the card markup into a named subcomponent if needed so the hook and render functions remain under the project’s approximately 50-line target.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@autogpt_platform/backend/backend/api/features/onboarding_step_test.py`:
- Around line 110-111: Move the onboarding_module and UserOnboarding imports
from their local scope into the module-level import section of
onboarding_step_test.py, and remove the inner import statements. Keep all
existing references unchanged.
---
Nitpick comments:
In
`@autogpt_platform/frontend/src/app/`(platform)/components/TabIntroCard/TabIntroCard.tsx:
- Around line 34-176: Split TabIntroCard responsibilities by extracting its
focus lifecycle into a dedicated useTabIntro... hook in a separate .ts file,
including focus restoration, Escape handling, and Tab trapping. Keep
TabIntroCard focused on presentation and wire it to the hook through its
existing dialogRef and isOpen state; extract the card markup into a named
subcomponent if needed so the hook and render functions remain under the
project’s approximately 50-line target.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 7aad5fb5-6b7f-4f50-8834-71d6791b5a01
📒 Files selected for processing (13)
autogpt_platform/backend/backend/api/features/onboarding_step_test.pyautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/TabIntroCard.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/TabIntroCard.test.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/tab-intros.test.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/useTabIntroCard.test.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/helpers.tsautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/useTabIntroCard.tsautogpt_platform/frontend/src/app/(platform)/marketplace/components/FeaturedSection/FeaturedSection.tsxautogpt_platform/frontend/src/app/(platform)/marketplace/components/MainMarketplacePage/MainMarketplacePage.tsxautogpt_platform/frontend/src/app/(platform)/marketplace/components/MarketplaceTabIntro/MarketplaceTabIntro.tsxautogpt_platform/frontend/src/app/(platform)/marketplace/components/MarketplaceTabIntro/helpers.tsautogpt_platform/frontend/src/services/onboarding/__tests__/tab-intro-analytics.test.tsautogpt_platform/frontend/src/services/onboarding/tab-intro-analytics.ts
🚧 Files skipped from review as they are similar to previous changes (5)
- autogpt_platform/frontend/src/app/(platform)/marketplace/components/MainMarketplacePage/MainMarketplacePage.tsx
- autogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/tests/tab-intros.test.tsx
- autogpt_platform/frontend/src/app/(platform)/marketplace/components/MarketplaceTabIntro/MarketplaceTabIntro.tsx
- autogpt_platform/frontend/src/services/onboarding/tab-intro-analytics.ts
- autogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/useTabIntroCard.ts
📜 Review details
⏰ Context from checks skipped due to timeout. (15)
- GitHub Check: integration_test
- GitHub Check: lint
- GitHub Check: check API types
- GitHub Check: Seer Code Review
- GitHub Check: test (3.13)
- GitHub Check: type-check (3.12)
- GitHub Check: type-check (3.13)
- GitHub Check: test (3.11)
- GitHub Check: test (3.12)
- GitHub Check: type-check (3.11)
- GitHub Check: lint
- GitHub Check: end-to-end tests
- GitHub Check: Check PR Status
- GitHub Check: Analyze (typescript)
- GitHub Check: Analyze (python)
🧰 Additional context used
📓 Path-based instructions (21)
autogpt_platform/frontend/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
autogpt_platform/frontend/**/*.{ts,tsx,js,jsx}: Use Node.js 21+ with pnpm package manager for frontend development
Always run 'pnpm format' for formatting and linting code in frontend developmentFormat frontend code using
pnpm format
autogpt_platform/frontend/**/*.{ts,tsx,js,jsx}: Fully capitalize acronyms in symbols, e.g.graphID,useBackendAPI
No linter suppressors (//@ts-ignore``,// eslint-disable) — fix the actual issue
Files:
autogpt_platform/frontend/src/app/(platform)/marketplace/components/MarketplaceTabIntro/helpers.tsautogpt_platform/frontend/src/services/onboarding/__tests__/tab-intro-analytics.test.tsautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/TabIntroCard.test.tsxautogpt_platform/frontend/src/app/(platform)/marketplace/components/FeaturedSection/FeaturedSection.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/useTabIntroCard.test.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/helpers.tsautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/TabIntroCard.tsx
autogpt_platform/frontend/**/*.{tsx,ts}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
autogpt_platform/frontend/**/*.{tsx,ts}: Use function declarations for components and handlers (not arrow functions) in React components
Only use arrow functions for small inline lambdas (map, filter, etc.) in React components
Use PascalCase for component names and camelCase with 'use' prefix for hook names in React
Use Tailwind CSS utilities only for styling in frontend components
Use design system components from 'src/components/' (atoms, molecules, organisms) in frontend development
Never use 'src/components/legacy/' in frontend code
Only use Phosphor Icons (@phosphor-icons/react) for icons in frontend components
Use generated API hooks from '@/app/api/__generated__/endpoints/' instead of deprecated 'BackendAPI' or 'src/lib/autogpt-server-api/'
Use React Query for server state (via generated hooks) in frontend development
Default to client components ('use client') in Next.js; only use server components for SEO or extreme TTFB needs
Use '' component for rendering errors in frontend UI; use toast notifications for mutation errors; use 'Sentry.captureException()' for manual exceptions
Separate render logic from data/behavior in React components; keep comments minimal (code should be self-documenting)
Files:
autogpt_platform/frontend/src/app/(platform)/marketplace/components/MarketplaceTabIntro/helpers.tsautogpt_platform/frontend/src/services/onboarding/__tests__/tab-intro-analytics.test.tsautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/TabIntroCard.test.tsxautogpt_platform/frontend/src/app/(platform)/marketplace/components/FeaturedSection/FeaturedSection.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/useTabIntroCard.test.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/helpers.tsautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/TabIntroCard.tsx
autogpt_platform/frontend/**/*.{ts,tsx}
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
autogpt_platform/frontend/**/*.{ts,tsx}: No barrel files or 'index.ts' re-exports in frontend code
Regenerate API hooks with 'pnpm generate:api' after backend OpenAPI spec changes in frontend development
autogpt_platform/frontend/**/*.{ts,tsx}: Use function declarations (not arrow functions) for components/handlers
Noanytypes unless the value genuinely can be anything
Keep render functions and hooks under ~50 lines; extract named helpers or sub-components when they grow longer
Files:
autogpt_platform/frontend/src/app/(platform)/marketplace/components/MarketplaceTabIntro/helpers.tsautogpt_platform/frontend/src/services/onboarding/__tests__/tab-intro-analytics.test.tsautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/TabIntroCard.test.tsxautogpt_platform/frontend/src/app/(platform)/marketplace/components/FeaturedSection/FeaturedSection.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/useTabIntroCard.test.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/helpers.tsautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/TabIntroCard.tsx
autogpt_platform/frontend/src/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
autogpt_platform/frontend/src/**/*.{ts,tsx}: Use generated API hooks from@/app/api/__generated__/endpoints/following the patternuse{Method}{Version}{OperationName}, and regenerate withpnpm generate:api
Separate render logic from business logic using component.tsx + useComponent.ts + helpers.ts pattern, colocate state when possible and avoid creating large components, use sub-components in local/componentsfolder
Use function declarations for components and handlers, use arrow functions only for callbacks
Do not useuseCallbackoruseMemounless asked to optimise a given function
autogpt_platform/frontend/src/**/*.{ts,tsx}: Keep files under ~200 lines; extract sub-components or hooks into their own files when a file grows beyond this
Use generated API hooks from@/app/api/__generated__/endpoints/with patternuse{Method}{Version}{OperationName}
Always import the-Icon-suffixed alias from@phosphor-icons/react(e.g.TrashIcon,PlusIcon,SquareIcon) — bare exports are deprecated
Do not useuseCallbackoruseMemounless asked to optimize a given function
Never usesrc/components/__legacy__/*— use design system components fromsrc/components/
Files:
autogpt_platform/frontend/src/app/(platform)/marketplace/components/MarketplaceTabIntro/helpers.tsautogpt_platform/frontend/src/services/onboarding/__tests__/tab-intro-analytics.test.tsautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/TabIntroCard.test.tsxautogpt_platform/frontend/src/app/(platform)/marketplace/components/FeaturedSection/FeaturedSection.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/useTabIntroCard.test.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/helpers.tsautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/TabIntroCard.tsx
autogpt_platform/frontend/**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
No barrel files or
index.tsre-exports in the frontend
Files:
autogpt_platform/frontend/src/app/(platform)/marketplace/components/MarketplaceTabIntro/helpers.tsautogpt_platform/frontend/src/services/onboarding/__tests__/tab-intro-analytics.test.tsautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/helpers.ts
autogpt_platform/frontend/src/**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Do not type hook returns, let Typescript infer as much as possible
autogpt_platform/frontend/src/**/*.ts: Extract component logic into custom hooks grouped by concern, not by component, with each hook in its own.tsfile
Do not type hook returns; let TypeScript infer as much as possible
Files:
autogpt_platform/frontend/src/app/(platform)/marketplace/components/MarketplaceTabIntro/helpers.tsautogpt_platform/frontend/src/services/onboarding/__tests__/tab-intro-analytics.test.tsautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/helpers.ts
autogpt_platform/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Never type with
any, if no types available useunknown
Files:
autogpt_platform/frontend/src/app/(platform)/marketplace/components/MarketplaceTabIntro/helpers.tsautogpt_platform/frontend/src/services/onboarding/__tests__/tab-intro-analytics.test.tsautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/TabIntroCard.test.tsxautogpt_platform/frontend/src/app/(platform)/marketplace/components/FeaturedSection/FeaturedSection.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/useTabIntroCard.test.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/helpers.tsautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/TabIntroCard.tsx
autogpt_platform/frontend/src/**/components/**/*.{ts,tsx}
📄 CodeRabbit inference engine (autogpt_platform/frontend/AGENTS.md)
Structure components as
ComponentName/ComponentName.tsx+useComponentName.ts+helpers.ts
Files:
autogpt_platform/frontend/src/app/(platform)/marketplace/components/MarketplaceTabIntro/helpers.tsautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/TabIntroCard.test.tsxautogpt_platform/frontend/src/app/(platform)/marketplace/components/FeaturedSection/FeaturedSection.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/useTabIntroCard.test.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/helpers.tsautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/TabIntroCard.tsx
autogpt_platform/frontend/src/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (autogpt_platform/frontend/AGENTS.md)
Avoid index and barrel files
Files:
autogpt_platform/frontend/src/app/(platform)/marketplace/components/MarketplaceTabIntro/helpers.tsautogpt_platform/frontend/src/services/onboarding/__tests__/tab-intro-analytics.test.tsautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/TabIntroCard.test.tsxautogpt_platform/frontend/src/app/(platform)/marketplace/components/FeaturedSection/FeaturedSection.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/useTabIntroCard.test.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/helpers.tsautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/TabIntroCard.tsx
autogpt_platform/frontend/**/*.{test,spec}.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
autogpt_platform/frontend/**/*.{test,spec}.{ts,tsx}: Use Vitest + RTL + MSW for integration tests as the primary testing approach (~90%, page-level), use Playwright for E2E critical flows, and use Storybook for design system components
Run frontend integration tests withpnpm test:unit(Vitest + RTL + MSW)
Files:
autogpt_platform/frontend/src/services/onboarding/__tests__/tab-intro-analytics.test.tsautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/TabIntroCard.test.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/useTabIntroCard.test.tsx
autogpt_platform/frontend/src/**/__tests__/**/*.{test,spec}.{ts,tsx}
📄 CodeRabbit inference engine (autogpt_platform/frontend/AGENTS.md)
Use Orval-generated MSW handlers from
@/app/api/__generated__/endpoints/{tag}/{tag}.msw.tsfor API mocking
Files:
autogpt_platform/frontend/src/services/onboarding/__tests__/tab-intro-analytics.test.tsautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/TabIntroCard.test.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/useTabIntroCard.test.tsx
autogpt_platform/frontend/**/*.{tsx,css}
📄 CodeRabbit inference engine (AGENTS.md)
Use Tailwind CSS only for styling, use design tokens, and use Phosphor Icons only
Files:
autogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/TabIntroCard.test.tsxautogpt_platform/frontend/src/app/(platform)/marketplace/components/FeaturedSection/FeaturedSection.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/useTabIntroCard.test.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/TabIntroCard.tsx
autogpt_platform/frontend/src/**/*.tsx
📄 CodeRabbit inference engine (AGENTS.md)
Component props should use
interface Props { ... }(not exported) unless the interface needs to be used outside the component
Files:
autogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/TabIntroCard.test.tsxautogpt_platform/frontend/src/app/(platform)/marketplace/components/FeaturedSection/FeaturedSection.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/useTabIntroCard.test.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/TabIntroCard.tsx
autogpt_platform/frontend/**/*.{tsx,jsx}
📄 CodeRabbit inference engine (autogpt_platform/frontend/AGENTS.md)
autogpt_platform/frontend/**/*.{tsx,jsx}: Nodark:Tailwind classes — the design system handles dark mode
Use Next.js<Link>for internal navigation — never raw<a>tags
Use Tailwind CSS only for styling with design tokens and Phosphor Icons only
Files:
autogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/TabIntroCard.test.tsxautogpt_platform/frontend/src/app/(platform)/marketplace/components/FeaturedSection/FeaturedSection.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/useTabIntroCard.test.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/TabIntroCard.tsx
autogpt_platform/frontend/src/**/components/**/*.{tsx,jsx}
📄 CodeRabbit inference engine (autogpt_platform/frontend/AGENTS.md)
Put sub-components in local
components/folder; component props should betype Props = { ... }(not exported) unless used outside the component
Files:
autogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/TabIntroCard.test.tsxautogpt_platform/frontend/src/app/(platform)/marketplace/components/FeaturedSection/FeaturedSection.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/useTabIntroCard.test.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/TabIntroCard.tsx
autogpt_platform/frontend/src/app/**/__tests__/**/*.{test,spec}.{ts,tsx}
📄 CodeRabbit inference engine (autogpt_platform/frontend/AGENTS.md)
Write integration tests in
__tests__/next topage.tsxusing Vitest + RTL + MSW for new pages/features
Files:
autogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/TabIntroCard.test.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/useTabIntroCard.test.tsx
autogpt_platform/backend/**/*.py
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
autogpt_platform/backend/**/*.py: Use Python 3.11 (required; managed by Poetry via pyproject.toml) for backend development
Always run 'poetry run format' (Black + isort) before linting in backend development
Always run 'poetry run lint' (ruff) after formatting in backend development
autogpt_platform/backend/**/*.py: Usepoetry run ...command for executing Python package dependencies
Use top-level imports only — avoid local/inner imports except for lazy imports of heavy optional dependencies likeopenpyxl
Use absolute imports withfrom backend.module import ...for cross-package imports; single-dot relative imports are acceptable for sibling modules within the same package; avoid double-dot relative imports
Do not use duck typing — avoidhasattr/getattr/isinstancefor type dispatch; use typed interfaces/unions/protocols instead
Use Pydantic models over dataclass/namedtuple/dict for structured data
Do not use linter suppressors — no# type: ignore,# noqa,# pyright: ignore; fix the type/code instead
Prefer list comprehensions over manual loop-and-append patterns
Use early return with guard clauses first to avoid deep nesting
Use%sfor deferred interpolation indebuglog statements for efficiency; use f-strings elsewhere for readability (e.g.,logger.debug("Processing %s items", count)vslogger.info(f"Processing {count} items"))
Sanitize error paths by usingos.path.basename()in error messages to avoid leaking directory structure
Be aware of TOCTOU (Time-Of-Check-Time-Of-Use) issues — avoid check-then-act patterns for file access and credit charging
Usetransaction=Truefor Redis pipelines to ensure atomicity on multi-step operations
Usemax(0, value)guards for computed values that should never be negative
Keep files under ~300 lines; if a file grows beyond this, split by responsibility (extract helpers, models, or a sub-module into a new file)
Keep functions under ~40 lines; extract named helpers when a function grows longer
...
Files:
autogpt_platform/backend/backend/api/features/onboarding_step_test.py
autogpt_platform/backend/backend/api/features/**/*.py
📄 CodeRabbit inference engine (.github/copilot-instructions.md)
Update routes in '/backend/backend/api/features/' and add/update Pydantic models in the same directory for API development
Files:
autogpt_platform/backend/backend/api/features/onboarding_step_test.py
autogpt_platform/{backend,autogpt_libs}/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
Format Python code with
poetry run format
Files:
autogpt_platform/backend/backend/api/features/onboarding_step_test.py
autogpt_platform/backend/**/api/**/*.py
📄 CodeRabbit inference engine (autogpt_platform/backend/AGENTS.md)
autogpt_platform/backend/**/api/**/*.py: UseSecurity()instead ofDepends()for authentication dependencies to get proper OpenAPI security specification
Follow SSE (Server-Sent Events) protocol: usedata:lines for frontend-parsed events (must match Zod schema) and: commentlines for heartbeats/status
Files:
autogpt_platform/backend/backend/api/features/onboarding_step_test.py
autogpt_platform/backend/**/*_test.py
📄 CodeRabbit inference engine (autogpt_platform/backend/AGENTS.md)
autogpt_platform/backend/**/*_test.py: Use pytest with snapshot testing for API responses
Colocate test files with source files using*_test.pynaming convention
Mock at boundaries — mock where the symbol is used, not where it's defined; after refactoring, update mock targets to match new module paths
UseAsyncMockfromunittest.mockfor async functions in tests
When writing tests, use Test-Driven Development (TDD): write failing tests marked with@pytest.mark.xfailbefore implementation, then remove the marker once the implementation is complete
When creating snapshots in tests, usepoetry run pytest path/to/test.py --snapshot-update; always review snapshot changes withgit diffbefore committing
Files:
autogpt_platform/backend/backend/api/features/onboarding_step_test.py
🧠 Learnings (23)
📚 Learning: 2026-04-01T18:54:16.035Z
Learnt from: Bentlybro
Repo: Significant-Gravitas/AutoGPT PR: 12633
File: autogpt_platform/frontend/src/app/(platform)/library/components/AgentFilterMenu/AgentFilterMenu.tsx:3-10
Timestamp: 2026-04-01T18:54:16.035Z
Learning: In the frontend, the legacy Select component at `@/components/__legacy__/ui/select` is an intentional, codebase-wide visual-consistency pattern. During code reviews, do not flag or block PRs merely for continuing to use this legacy Select. If a migration to the newer design-system Select is desired, bundle it into a single dedicated cleanup/migration PR that updates all Select usages together (e.g., avoid piecemeal replacements).
Applied to files:
autogpt_platform/frontend/src/app/(platform)/marketplace/components/MarketplaceTabIntro/helpers.tsautogpt_platform/frontend/src/services/onboarding/__tests__/tab-intro-analytics.test.tsautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/TabIntroCard.test.tsxautogpt_platform/frontend/src/app/(platform)/marketplace/components/FeaturedSection/FeaturedSection.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/useTabIntroCard.test.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/helpers.tsautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/TabIntroCard.tsx
📚 Learning: 2026-04-07T09:24:16.582Z
Learnt from: 0ubbe
Repo: Significant-Gravitas/AutoGPT PR: 12686
File: autogpt_platform/frontend/src/app/(no-navbar)/onboarding/steps/__tests__/PainPointsStep.test.tsx:1-19
Timestamp: 2026-04-07T09:24:16.582Z
Learning: In Significant-Gravitas/AutoGPT’s `autogpt_platform/frontend` (Vite + `vitejs/plugin-react` with the automatic JSX transform), do not flag usages of React types/components (e.g., `React.ReactNode`) in `.ts`/`.tsx` files as missing `React` imports. Since the React namespace is made available by the project’s TS/Vite setup, an explicit `import React from 'react'` or `import type { ReactNode } ...` is not required; only treat it as missing if typechecking (e.g., `pnpm types`) would actually fail.
Applied to files:
autogpt_platform/frontend/src/app/(platform)/marketplace/components/MarketplaceTabIntro/helpers.tsautogpt_platform/frontend/src/services/onboarding/__tests__/tab-intro-analytics.test.tsautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/TabIntroCard.test.tsxautogpt_platform/frontend/src/app/(platform)/marketplace/components/FeaturedSection/FeaturedSection.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/useTabIntroCard.test.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/helpers.tsautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/TabIntroCard.tsx
📚 Learning: 2026-07-28T15:32:54.931Z
Learnt from: Abhi1992002
Repo: Significant-Gravitas/AutoGPT PR: 13699
File: autogpt_platform/frontend/src/components/layout/Navbar/components/Wallet/components/WalletFullPanel.tsx:0-0
Timestamp: 2026-07-28T15:32:54.931Z
Learning: In AutoGPT's frontend (autogpt_platform/frontend), prefer importing the non-legacy ScrollArea component from `@/components/ui/scroll-area` over `@/components/__legacy__/ui/scroll-area` for new or migrated code. The non-legacy component is a drop-in superset: it preserves the legacy component’s props and additionally supports the optional `showScrollToTop` prop—so reviewers should flag new legacy imports unless there’s a specific, documented reason they can’t use the non-legacy version.
Applied to files:
autogpt_platform/frontend/src/app/(platform)/marketplace/components/MarketplaceTabIntro/helpers.tsautogpt_platform/frontend/src/services/onboarding/__tests__/tab-intro-analytics.test.tsautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/TabIntroCard.test.tsxautogpt_platform/frontend/src/app/(platform)/marketplace/components/FeaturedSection/FeaturedSection.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/useTabIntroCard.test.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/helpers.tsautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/TabIntroCard.tsx
📚 Learning: 2026-04-02T05:43:49.128Z
Learnt from: 0ubbe
Repo: Significant-Gravitas/AutoGPT PR: 12640
File: autogpt_platform/frontend/src/app/(no-navbar)/onboarding/steps/WelcomeStep.tsx:13-13
Timestamp: 2026-04-02T05:43:49.128Z
Learning: Do not flag `import { Question } from "phosphor-icons/react"` as an invalid import. `Question` is a valid named export from `phosphor-icons/react` (as reflected in the package’s generated `.d.ts` files and re-exports via `dist/index.d.ts`), so it should be treated as a supported named export during code reviews.
Applied to files:
autogpt_platform/frontend/src/app/(platform)/marketplace/components/MarketplaceTabIntro/helpers.tsautogpt_platform/frontend/src/services/onboarding/__tests__/tab-intro-analytics.test.tsautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/TabIntroCard.test.tsxautogpt_platform/frontend/src/app/(platform)/marketplace/components/FeaturedSection/FeaturedSection.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/useTabIntroCard.test.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/helpers.tsautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/TabIntroCard.tsx
📚 Learning: 2026-08-06T15:47:58.674Z
Learnt from: 0ubbe
Repo: Significant-Gravitas/AutoGPT PR: 13787
File: autogpt_platform/frontend/src/app/(platform)/team/[expertId]/components/ExpertAboutSection.tsx:5-5
Timestamp: 2026-08-06T15:47:58.674Z
Learning: Within autogpt_platform/frontend, use Hugeicons through the shared Icon atom at src/components/atoms/Icon/Icon.tsx. Pass Hugeicons-compatible IconSvgElement values because the atom renders HugeiconsIcon. Do not follow the stale root AGENTS.md Phosphor icon quick-reference guidance for this frontend.
Applied to files:
autogpt_platform/frontend/src/app/(platform)/marketplace/components/MarketplaceTabIntro/helpers.tsautogpt_platform/frontend/src/services/onboarding/__tests__/tab-intro-analytics.test.tsautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/TabIntroCard.test.tsxautogpt_platform/frontend/src/app/(platform)/marketplace/components/FeaturedSection/FeaturedSection.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/useTabIntroCard.test.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/helpers.tsautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/TabIntroCard.tsx
📚 Learning: 2026-04-20T20:07:22.981Z
Learnt from: ntindle
Repo: Significant-Gravitas/AutoGPT PR: 11235
File: autogpt_platform/frontend/src/app/(platform)/admin/diagnostics/__tests__/ExecutionsTable.test.tsx:27-76
Timestamp: 2026-04-20T20:07:22.981Z
Learning: In this codebase, Orval-generated API modules under `src/app/api/__generated__/` are not committed to git and must be generated via `pnpm generate:api` (requires a running backend). In integration tests, it’s acceptable—and expected—to stub generated hooks/modules by mocking them with `vi.mock("`@/app/api/__generated__/endpoints/`{tag}/{tag}")`. Do not treat `vi.mock` of these generated hook modules as a violation of the MSW handler guideline, since the corresponding MSW handlers cannot be imported at test time when generated files are absent.
Applied to files:
autogpt_platform/frontend/src/services/onboarding/__tests__/tab-intro-analytics.test.tsautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/TabIntroCard.test.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/useTabIntroCard.test.tsx
📚 Learning: 2026-02-27T10:45:49.499Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12213
File: autogpt_platform/frontend/src/app/(platform)/copilot/tools/RunMCPTool/helpers.tsx:23-24
Timestamp: 2026-02-27T10:45:49.499Z
Learning: Prefer using generated OpenAPI types from '`@/app/api/__generated__/`' for payloads defined in openapi.json (e.g., MCPToolsDiscoveredResponse, MCPToolOutputResponse). Use inline TypeScript interfaces only for payloads that are SSE-stream-only and not exposed via OpenAPI. Apply this pattern to frontend tool components (e.g., RunMCPTool) and related areas where similar SSE/openapi-discrepancies occur; avoid re-implementing types when a generated type is available.
Applied to files:
autogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/TabIntroCard.test.tsxautogpt_platform/frontend/src/app/(platform)/marketplace/components/FeaturedSection/FeaturedSection.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/useTabIntroCard.test.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/TabIntroCard.tsx
📚 Learning: 2026-03-24T02:05:04.672Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12526
File: autogpt_platform/frontend/src/app/(platform)/copilot/CopilotPage.tsx:0-0
Timestamp: 2026-03-24T02:05:04.672Z
Learning: When gating React component logic on a React Query result (e.g., hooks like `useQuery` / `useGetV2GetCopilotUsage`), prefer destructuring and checking `isSuccess` (or aliasing it to a meaningful boolean like `isSuccess: hasUsage`) instead of relying on `!isLoading`. Reason: `isLoading` can be `false` in error/idle states where `data` may still be `undefined`, while `isSuccess` indicates the query completed successfully and `data` is populated.
Applied to files:
autogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/TabIntroCard.test.tsxautogpt_platform/frontend/src/app/(platform)/marketplace/components/FeaturedSection/FeaturedSection.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/useTabIntroCard.test.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/TabIntroCard.tsx
📚 Learning: 2026-04-13T13:11:07.445Z
Learnt from: 0ubbe
Repo: Significant-Gravitas/AutoGPT PR: 12764
File: autogpt_platform/frontend/src/app/(platform)/library/components/SitrepItem/SitrepItem.tsx:143-145
Timestamp: 2026-04-13T13:11:07.445Z
Learning: In `autogpt_platform/frontend`, do not flag direct interpolation of `executionID` UUID strings into URL query parameters (e.g., `activeItem=${executionID}` in JSX/Next links). If the value is a UUID string matching `[0-9a-f-]`, it contains no reserved URL characters, so additional `encodeURIComponent` or Next.js object-based `href` encoding is unnecessary. Only treat it as an encoding issue if the query-param value is not guaranteed to be UUID-formatted (i.e., may include characters outside `[0-9a-f-]`).
Applied to files:
autogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/TabIntroCard.test.tsxautogpt_platform/frontend/src/app/(platform)/marketplace/components/FeaturedSection/FeaturedSection.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/useTabIntroCard.test.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/TabIntroCard.tsx
📚 Learning: 2026-04-15T22:49:06.896Z
Learnt from: ntindle
Repo: Significant-Gravitas/AutoGPT PR: 11235
File: autogpt_platform/frontend/src/app/(platform)/admin/diagnostics/components/ExecutionsTable.tsx:0-0
Timestamp: 2026-04-15T22:49:06.896Z
Learning: In the AutoGPT frontend (React Query + toast/ErrorCard patterns), do not require `Sentry.captureException` in React Query mutation `catch` blocks. React Query handles error propagation for mutation paths, so follow the established pattern: show toast notifications for mutation errors and use `ErrorCard` for render/fetch errors. Only add `Sentry.captureException` for truly manual/unexpected exception paths that are outside React Query’s control (e.g., standalone async utilities or event handlers not wired through React Query).
Applied to files:
autogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/TabIntroCard.test.tsxautogpt_platform/frontend/src/app/(platform)/marketplace/components/FeaturedSection/FeaturedSection.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/useTabIntroCard.test.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/TabIntroCard.tsx
📚 Learning: 2026-07-03T04:19:11.799Z
Learnt from: Abhi1992002
Repo: Significant-Gravitas/AutoGPT PR: 13474
File: autogpt_platform/frontend/src/app/(platform)/PlatformChrome/PlatformChrome.tsx:38-38
Timestamp: 2026-07-03T04:19:11.799Z
Learning: When reviewing Tailwind usage in .tsx components, allow intentional raw hex color values if they exactly match the design-spec and there is no equivalent Tailwind design token/utility class available (e.g., a utility like `bg-zinc-50` may be a different shade than the required `#f9f9f9`). Do not flag these as "design-token violations" as long as the reviewer can confirm that an appropriate Tailwind token does not exist or would not match the exact color.
Applied to files:
autogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/TabIntroCard.test.tsxautogpt_platform/frontend/src/app/(platform)/marketplace/components/FeaturedSection/FeaturedSection.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/useTabIntroCard.test.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/TabIntroCard.tsx
📚 Learning: 2026-04-20T13:17:39.951Z
Learnt from: 0ubbe
Repo: Significant-Gravitas/AutoGPT PR: 12854
File: autogpt_platform/frontend/src/app/(platform)/library/__tests__/briefing.test.tsx:84-84
Timestamp: 2026-04-20T13:17:39.951Z
Learning: In the AutoGPT frontend, `testing-library/react` cleanup is already handled globally after each test via `src/tests/integrations/vitest.setup.tsx`. Therefore, for integration test files under `__tests__/`, do NOT add redundant `afterEach(() => cleanup())`. Only add local `afterEach` teardown for resources that are not covered globally—specifically, when using fake timers, add `afterEach(() => vi.useRealTimers())` (or equivalent) to restore real timers and prevent cross-test interference.
Applied to files:
autogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/TabIntroCard.test.tsxautogpt_platform/frontend/src/app/(platform)/components/TabIntroCard/__tests__/useTabIntroCard.test.tsx
📚 Learning: 2026-02-26T17:02:22.448Z
Learnt from: Pwuts
Repo: Significant-Gravitas/AutoGPT PR: 12211
File: .pre-commit-config.yaml:160-179
Timestamp: 2026-02-26T17:02:22.448Z
Learning: Keep the pre-commit hook pattern broad for autogpt_platform/backend to ensure OpenAPI schema changes are captured. Do not narrow to backend/api/ alone, since the generated schema depends on Pydantic models across multiple directories (backend/data/, backend/blocks/, backend/copilot/, backend/integrations/, backend/util/). Narrowing could miss schema changes and cause frontend type desynchronization.
Applied to files:
autogpt_platform/backend/backend/api/features/onboarding_step_test.py
📚 Learning: 2026-03-05T15:42:08.207Z
Learnt from: ntindle
Repo: Significant-Gravitas/AutoGPT PR: 12297
File: .claude/skills/backend-check/SKILL.md:14-16
Timestamp: 2026-03-05T15:42:08.207Z
Learning: In Python files under autogpt_platform/backend (recursively), rely on poetry run format to perform formatting (Black + isort) and linting (ruff). Do not run poetry run lint as a separate step after poetry run format, since format already includes linting checks.
Applied to files:
autogpt_platform/backend/backend/api/features/onboarding_step_test.py
📚 Learning: 2026-03-16T16:35:40.236Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12440
File: autogpt_platform/backend/backend/api/features/workflow_import.py:54-63
Timestamp: 2026-03-16T16:35:40.236Z
Learning: Avoid using the word 'competitor' in public-facing identifiers and text. Use neutral naming for API paths, model names, function names, and UI text. Examples: rename 'CompetitorFormat' to 'SourcePlatform', 'convert_competitor_workflow' to 'convert_workflow', '/competitor-workflow' to '/workflow'. Apply this guideline to files under autogpt_platform/backend and autogpt_platform/frontend.
Applied to files:
autogpt_platform/backend/backend/api/features/onboarding_step_test.py
📚 Learning: 2026-03-31T15:37:38.626Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12623
File: autogpt_platform/backend/backend/copilot/tools/agent_generator/fixer.py:37-47
Timestamp: 2026-03-31T15:37:38.626Z
Learning: When validating/constructing Anthropic API model IDs in Significant-Gravitas/AutoGPT, allow the hyphen-separated Claude Opus 4.6 model ID `claude-opus-4-6` (it corresponds to `LlmModel.CLAUDE_4_6_OPUS` in `autogpt_platform/backend/backend/blocks/llm.py`). Do NOT require the dot-separated form in Anthropic contexts. Only OpenRouter routing variants should use the dot separator (e.g., `anthropic/claude-opus-4.6`); `claude-opus-4-6` should be treated as correct when passed to Anthropic, and flagged only if it’s used in the OpenRouter path where the dot form is expected.
Applied to files:
autogpt_platform/backend/backend/api/features/onboarding_step_test.py
📚 Learning: 2026-04-15T02:43:36.890Z
Learnt from: ntindle
Repo: Significant-Gravitas/AutoGPT PR: 12780
File: autogpt_platform/backend/backend/copilot/tools/workspace_files.py:0-0
Timestamp: 2026-04-15T02:43:36.890Z
Learning: When reviewing Python exception handlers, do not flag `isinstance(e, X)` checks as dead/unreachable if the caught exception `X` is a subclass of the exception type being handled. For example, if `X` (e.g., `VirusScanError`) inherits from `ValueError` (directly or via an intermediate class) and it can be raised within an `except ValueError:` block, then `isinstance(e, X)` inside that handler is reachable and should not be treated as dead code.
Applied to files:
autogpt_platform/backend/backend/api/features/onboarding_step_test.py
📚 Learning: 2026-05-23T05:29:43.085Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 13200
File: autogpt_platform/backend/backend/executor/scheduler.py:590-593
Timestamp: 2026-05-23T05:29:43.085Z
Learning: When reviewing Python code that uses Pydantic discriminated/tagged unions (e.g., `Annotated[Union[...], Field(discriminator="kind")]`), recognize that using `isinstance(x, SomeVariantInfo)` to narrow the union is an intentional and correct runtime guard and should also enable static type narrowing in tools like Pyright. Do not recommend replacing such `isinstance`-based narrowing with `cast(...)` when the check already proves the variant at runtime.
Applied to files:
autogpt_platform/backend/backend/api/features/onboarding_step_test.py
📚 Learning: 2026-04-22T11:46:04.431Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12881
File: autogpt_platform/backend/backend/copilot/config.py:0-0
Timestamp: 2026-04-22T11:46:04.431Z
Learning: Do not flag the Claude Sonnet 4.6 model ID as incorrect when it uses the project’s established hyphenated convention: `anthropic/claude-sonnet-4-6`. This hyphen form is the intentional, production convention and should be treated as valid (including in files like llm.py, blocks tests, reasoning.py, `_is_anthropic_model` tests, and config defaults). Note that OpenRouter also accepts the dot variant `anthropic/claude-sonnet-4.6`, so either form may be tolerated, but `anthropic/claude-sonnet-4-6` should be considered the standard to match project usage.
Applied to files:
autogpt_platform/backend/backend/api/features/onboarding_step_test.py
📚 Learning: 2026-04-22T11:46:12.892Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 12881
File: autogpt_platform/backend/backend/copilot/baseline/service.py:322-332
Timestamp: 2026-04-22T11:46:12.892Z
Learning: In this codebase (Significant-Gravitas/AutoGPT), OpenRouter-routed Anthropic model IDs should use the hyphen-separated convention (e.g., `anthropic/claude-sonnet-4-6`, `anthropic/claude-opus-4-6`). Although OpenRouter may accept both hyphen and dot variants, treat the hyphen-separated form as the intended, correct codebase-wide convention and do not flag it as an error. Only flag the dot-separated variant (e.g., `anthropic/claude-sonnet-4.6`) as incorrect when reviewing/validating model ID strings for OpenRouter-routed Anthropic models.
Applied to files:
autogpt_platform/backend/backend/api/features/onboarding_step_test.py
📚 Learning: 2026-05-07T18:48:14.242Z
Learnt from: majdyz
Repo: Significant-Gravitas/AutoGPT PR: 13040
File: autogpt_platform/backend/backend/blocks/llm.py:0-0
Timestamp: 2026-05-07T18:48:14.242Z
Learning: In this repository, isort may split imports from the same module into separate blocks when some imports are aliased (e.g., `from module import X as Y`) and others are not. Preserve the two-block layout when it results from isort (such as keeping `from openai.types.chat import ChatCompletion as OpenAIChatCompletion` separate from non-aliased imports from `openai.types.chat`). Do not treat that split as a style issue during review; merging them into a single block can fail CI with `Imports are incorrectly sorted and/or formatted`.
Applied to files:
autogpt_platform/backend/backend/api/features/onboarding_step_test.py
📚 Learning: 2026-05-26T14:24:34.866Z
Learnt from: Abhi1992002
Repo: Significant-Gravitas/AutoGPT PR: 13217
File: autogpt_platform/backend/backend/api/features/search/service.py:137-137
Timestamp: 2026-05-26T14:24:34.866Z
Learning: In the Significant-Gravitas/AutoGPT backend, treat `user_id` (an opaque UUID used only for correlation/tracing) as non-PII. Do not flag direct logging of `user_id` in `logger.warning`/`logger.info` statements as a PII exposure issue, as the established convention is to log `user_id` for tracing while reserving PII for fields like email or display name.
Applied to files:
autogpt_platform/backend/backend/api/features/onboarding_step_test.py
📚 Learning: 2026-06-11T19:39:10.493Z
Learnt from: ntindle
Repo: Significant-Gravitas/AutoGPT PR: 13337
File: autogpt_platform/backend/backend/copilot/graphiti/reranker.py:0-0
Timestamp: 2026-06-11T19:39:10.493Z
Learning: In the Significant-Gravitas/AutoGPT Python backend, when calling the OpenAI Python client `chat.completions.create`, construct the `messages` payload using the concrete typed-dict variants from `openai.types.chat` (e.g., `ChatCompletionSystemMessageParam`, `ChatCompletionUserMessageParam`, etc.) rather than trying to instantiate `ChatCompletionMessageParam` directly. `ChatCompletionMessageParam` is a `Union` alias and is not constructible, so `ChatCompletionMessageParam(role=..., content=...)` should fail type checking. Build each message element with the appropriate concrete typed dict and then annotate the resulting list as `list[ChatCompletionMessageParam]` (e.g., `messages: list[ChatCompletionMessageParam] = [ChatCompletionSystemMessageParam(...), ...]`).
Applied to files:
autogpt_platform/backend/backend/api/features/onboarding_step_test.py
Top-level imports only, per the backend code style. Removes the repeated local imports of `onboarding` and `UserOnboarding` throughout the file.
|
/review |
There was a problem hiding this comment.
❓ INCONCLUSIVE
Failed to authenticate. API Error: 401 OAuth access token has been revoked.
Risk level: medium | Human review: recommended | Duration: 905s | Reviewed: e025437d
Specialist Reports
| Specialist | Status | Summary |
|---|---|---|
| security | ❌ FAIL | Failed to authenticate. API Error: 401 OAuth access token has been revoked. |
| architect | ❌ FAIL | Failed to authenticate. API Error: 401 OAuth access token has been revoked. |
| performance | ❌ FAIL | Failed to authenticate. API Error: 401 OAuth access token has been revoked. |
| testing | ❌ FAIL | Failed to authenticate. API Error: 401 OAuth access token has been revoked. |
| quality | ❌ FAIL | Failed to authenticate. API Error: 401 OAuth access token has been revoked. |
| product | ❌ FAIL | Failed to authenticate. API Error: 401 OAuth access token has been revoked. |
| discussion | ❌ FAIL | Failed to authenticate. API Error: 401 OAuth access token has been revoked. |
| ui-reviewer (local) | ❌ FAIL | Failed to authenticate. API Error: 401 OAuth access token has been revoked. |
| ui-reviewer (hosted) | ✅ PASS | All three tab intro cards render, dismiss, record their per-tab onboarding step, and grant no rewards; backend accepts the new steps and rejects rewarded/invalid ones with 422 — feature works end-to-end with no functional defects. |
Quality Checks
- ✅ lint: cd autogpt_platform/frontend && pnpm lint:
cd autogpt_platform/frontend && pnpm lint(77s) - ✅ lint: cd autogpt_platform/backend && poetry run lint:
cd autogpt_platform/backend && poetry run lint(98s) - ✅ typecheck: cd autogpt_platform/frontend && pnpm types:
cd autogpt_platform/frontend && pnpm types(43s) - ❌ test: cd autogpt_platform/frontend && mv .env /tmp/qa-env-stash 2>/dev/null; pnpm test:unit; rc=$?; [ -f /tmp/qa-env-stash ] && mv /tmp/qa-env-stash .env; exit $rc:
cd autogpt_platform/frontend && mv .env /tmp/qa-env-stash 2>/dev/null; pnpm test:unit; rc=$?; [ -f /tmp/qa-env-stash ] && mv /tmp/qa-env-stash .env; exit $rc(386s) - ✅ build: cd autogpt_platform/frontend && pnpm build:
cd autogpt_platform/frontend && pnpm build(288s)






Why / What / How
Why: The Agents, Marketplace and Build tabs give a new user no orientation — you land on a fleet view, a long storefront, or an empty canvas with no idea what the tab is for or what to do first. What: Each of those three tabs now shows a single first-visit intro card: an icon, a short title, one sentence, one way forward and one way out. How: A shared
TabIntroCardshell plus a thin per-tab wrapper, gated behind the existingonboarding-brain-dumpLaunchDarkly flag (off by default). Dismissal is recorded as a per-tab onboarding step so the backend record is the source of truth across devices, with a user-scopedlocalStoragecache covering the window before that write lands.Changes 🏗️
(platform)/components/TabIntroCard— card shell, theuseTabIntroCardfirst-visit gate, andhelpers.tsholding the step map, the CTA union and thelocalStoragecache. The card dismisses on "Got it", Escape, and a backdrop click. It moves focus into itself on open, containsTab/Shift+Tabwhile open, and restores focus to the opener on close.AgentsTabIntro(Library),MarketplaceTabIntro(CTA scrolls the featured carousel into view, falling back to the full listing when nothing is featured),BuildTabIntro(AutoPilot as the primary route, the existing builder tutorial as a quiet alternative).?flowID=) — the intro is about starting something and its tutorial clears the canvas. Vetoing leaves the step unrecorded, so a later blank/buildstill gets the introduction.isOpenwaits on the flag, the resolved user id, the onboarding record and the local cache, all evaluated during render. Nothing is copied into state, so the card cannot flash open for a returning user in the frame before their id resolves. Dismissal is tracked per user id, so a second account signing in behind the same mounted hook still gets its own intro. The cache read sits last in the expression, so a user with the flag off never toucheslocalStorage.OnboardingStepvalues (AGENTS_TAB_INTRO,MARKETPLACE_TAB_INTRO,BUILD_TAB_INTRO) added to the enum and toFrontendOnboardingStepsoPOST /onboarding/stepaccepts them instead of 422-ing. They are unrewarded, and there is a test asserting the credit model is never reached for them.Flag.ONBOARDING_BRAIN_DUMPrather than one of their own, so they ship and roll back with the rest of the new onboarding. No new flag key.tab_intro_shown/tab_intro_cta_clicked/tab_intro_dismissed, each carrying its tab, so one funnel shows both which tabs get discovered and whether the CTA earns its place. The tab and CTA properties are typed unions, not strings.FEATURED_SECTION_ID,AGENTS_SECTION_ID) live inMarketplaceTabIntro/helpers.tssoFeaturedSectionandMainMarketplacePagecan carry the ids without the intro importing its own parent page.Checklist 📋
For code changes:
TabIntroCardrenders its copy, CTA and "Got it"; renders nothing while closedTab/Shift+Tabwrap inside it rather than reaching the page behind, and focus returns to the opener on closelocalStoragethrows/copilotand the alternative launches the builder tutorial?flowID=and leaves the step unrecorded for laterPOST /onboarding/stepaccepts all three new steps, still 422s on rewarded backend-only steps, and grants no credits for the tab intros (parametrised)For configuration changes:
.env.defaultis updated or already compatible with my changesdocker-compose.ymlis updated or already compatible with my changesNo configuration changes. The feature is read through the existing
onboarding-brain-dumpLaunchDarkly wiring and defaults tofalse, so an environment with no flag key behaves exactly as before.