-
-
Notifications
You must be signed in to change notification settings - Fork 488
♻️ Refactor user provider and navigation structure #1859
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
Conversation
|
The latest updates on your projects. Learn more about Vercel for Git ↗︎
1 Skipped Deployment
|
WalkthroughThis update refactors user and session management across the application, introducing a required Changes
Sequence Diagram(s)sequenceDiagram
participant Browser
participant NextAuth
participant AppServer
participant PostHog
participant UserProvider
Browser->>NextAuth: Request session
NextAuth->>AppServer: Fetch user/token
AppServer-->>NextAuth: Return user/token
NextAuth->>NextAuth: Set session.user.isGuest
NextAuth-->>Browser: Return session with isGuest
Browser->>AppServer: Load page
AppServer->>UserProvider: Provide user (with isGuest)
UserProvider->>PostHog: Identify user (if id present)
UserProvider-->>AppServer: Provide user context
AppServer-->>Browser: Rendered page with user context
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Poem
Note ⚡️ Unit Test Generation is now available in beta!Learn more here, or try it out under "Finishing Touches" below. 📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (3)
🚧 Files skipped from review as they are similar to previous changes (2)
🧰 Additional context used📓 Path-based instructions (5)**/*.{js,jsx,ts,tsx}📄 CodeRabbit Inference Engine (.windsurfrules)
Files:
**/*.{ts,tsx}📄 CodeRabbit Inference Engine (.windsurfrules)
Files:
**/*.{jsx,tsx}📄 CodeRabbit Inference Engine (.windsurfrules)
Files:
**/*.tsx📄 CodeRabbit Inference Engine (.windsurfrules)
Files:
**/*📄 CodeRabbit Inference Engine (.windsurfrules)
Files:
🧠 Learnings (2)📓 Common learningsapps/web/src/app/components/page-layout.tsx (5)Learnt from: CR Learnt from: CR Learnt from: CR Learnt from: CR Learnt from: CR 🧬 Code Graph Analysis (1)apps/web/src/app/components/page-layout.tsx (1)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
🔇 Additional comments (4)
✨ Finishing Touches
🧪 Generate unit tests
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed 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)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 7
🔭 Outside diff range comments (2)
apps/web/src/app/[locale]/poll/[urlId]/duplicate-dialog.tsx (1)
45-58: Handle mutation errors to avoid silent failures
duplicate.mutatedefinesonSuccessbut noonError. A rejected promise will leave the dialog spinning and give no user feedback.duplicate.mutate( { pollId, newTitle: data.title }, { + onError: (e) => { + toast.error(t("somethingWentWrong", { defaults: "Something went wrong" })); + }, onSuccess: async (res) => { posthog?.capture("duplicate poll", { pollId, newPollId: res.id, }); router.push(`/poll/${res.id}`); }, }, );apps/web/src/components/optimized-avatar-image.tsx (1)
8-17: Fix TypeScript type inconsistency for optional size prop.The parameter has a default value but the type definition shows
sizeas required. Update the type to reflect the optional nature:- size: "sm" | "md" | "lg" | "xl"; + size?: "sm" | "md" | "lg" | "xl";The default value approach is good for component usability and aligns with the coding guideline to keep props minimal.
🧹 Nitpick comments (5)
apps/web/src/app/[locale]/poll/[urlId]/duplicate-dialog.tsx (1)
34-38: Providedefaultson every<Trans>usageClient components are required to pass a fallback via the
defaultsprop. Omitting it breaks the guideline and risks missing text when the key is absent.-<Trans i18nKey="duplicate" /> +<Trans i18nKey="duplicate" defaults="Duplicate" /> ... -<Trans i18nKey="duplicateDescription" /> +<Trans i18nKey="duplicateDescription" defaults="Give the copy a new title" /> ... -<Trans i18nKey="cancel" /> +<Trans i18nKey="cancel" defaults="Cancel" /> ... -<Trans i18nKey="duplicate" /> +<Trans i18nKey="duplicate" defaults="Duplicate" />Also applies to: 63-65, 72-73
apps/web/src/app/[locale]/(space)/account/billing/page.tsx (1)
44-45: Remove unused imports.The imports for
tfrom "i18next" andtitlefrom "process" are not used anywhere in the component and should be removed to keep the code clean.-import { t } from "i18next"; -import { title } from "process";apps/web/src/app/[locale]/(space)/account/components/sidebar.tsx (1)
14-51: LGTM with minor improvements: Well-structured sidebar component.The component follows good patterns with proper translation, navigation, and icon usage. However, consider using React module APIs as per coding guidelines.
Consider using React module APIs instead of standalone hooks:
+import React from "react"; -import { usePathname } from "next/navigation"; -import { useTranslation } from "@/i18n/client"; +import { usePathname } from "next/navigation"; +import { useTranslation } from "@/i18n/client"; export function AccountSidebarMenu() { - const { t } = useTranslation(); - const pathname = usePathname(); + const { t } = useTranslation(); + const pathname = usePathname();Note: The standalone hooks are actually appropriate here since
usePathnameis a Next.js hook anduseTranslationis from the i18n library, not React hooks.apps/web/src/components/user-provider.tsx (2)
29-36: Consider improving the error message for better developer experience.The hook correctly enforces authenticated user access, but the error message could be more descriptive.
export const useAuthenticatedUser = () => { const { user } = useUser(); if (!user || user.isGuest) { - throw new Error("User is not defined"); + throw new Error("useAuthenticatedUser can only be used with authenticated users. Use useUser() for components that support guest users."); } return { user }; };
45-54: Remove redundant dependency from useMemo.The
isGuestvariable is derived fromuser, so including both in the dependencies array is redundant.- }, [user, isGuest]); + }, [user]);
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (64)
CLAUDE.md(1 hunks)apps/web/declarations/next-auth.d.ts(1 hunks)apps/web/src/app/[locale]/(optional-space)/layout.tsx(1 hunks)apps/web/src/app/[locale]/(optional-space)/new/page.tsx(1 hunks)apps/web/src/app/[locale]/(optional-space)/poll/[urlId]/duplicate-dialog.tsx(1 hunks)apps/web/src/app/[locale]/(optional-space)/poll/[urlId]/guest-poll-alert.tsx(1 hunks)apps/web/src/app/[locale]/(optional-space)/poll/[urlId]/page.tsx(1 hunks)apps/web/src/app/[locale]/(space)/(dashboard)/components/sidebar/space-sidebar.tsx(3 hunks)apps/web/src/app/[locale]/(space)/(dashboard)/layout.tsx(1 hunks)apps/web/src/app/[locale]/(space)/(dashboard)/members/components/header.tsx(1 hunks)apps/web/src/app/[locale]/(space)/(dashboard)/members/page.tsx(1 hunks)apps/web/src/app/[locale]/(space)/(dashboard)/polls/page.tsx(1 hunks)apps/web/src/app/[locale]/(space)/account/billing/page.tsx(3 hunks)apps/web/src/app/[locale]/(space)/account/components/sidebar.tsx(1 hunks)apps/web/src/app/[locale]/(space)/account/components/sign-out-button.tsx(1 hunks)apps/web/src/app/[locale]/(space)/account/layout.tsx(1 hunks)apps/web/src/app/[locale]/(space)/account/loading.tsx(1 hunks)apps/web/src/app/[locale]/(space)/account/preferences/page.tsx(1 hunks)apps/web/src/app/[locale]/(space)/account/profile/page.tsx(2 hunks)apps/web/src/app/[locale]/(space)/account/profile/profile-email-address.tsx(3 hunks)apps/web/src/app/[locale]/(space)/account/profile/profile-picture.tsx(3 hunks)apps/web/src/app/[locale]/(space)/app-card.tsx(0 hunks)apps/web/src/app/[locale]/(space)/layout.tsx(1 hunks)apps/web/src/app/[locale]/layout.tsx(4 hunks)apps/web/src/app/[locale]/poll/[urlId]/duplicate-dialog.tsx(1 hunks)apps/web/src/app/[locale]/poll/[urlId]/page.tsx(0 hunks)apps/web/src/app/components/logout-button.tsx(1 hunks)apps/web/src/auth/client.tsx(1 hunks)apps/web/src/auth/data.ts(3 hunks)apps/web/src/components/create-poll.tsx(3 hunks)apps/web/src/components/discussion/discussion.tsx(4 hunks)apps/web/src/components/forms/poll-settings.tsx(2 hunks)apps/web/src/components/layouts/poll-layout.tsx(2 hunks)apps/web/src/components/new-participant-modal.tsx(3 hunks)apps/web/src/components/optimized-avatar-image.tsx(1 hunks)apps/web/src/components/poll/manage-poll.tsx(4 hunks)apps/web/src/components/poll/notifications-toggle.tsx(5 hunks)apps/web/src/components/poll/poll-header.tsx(1 hunks)apps/web/src/components/user-dropdown.tsx(3 hunks)apps/web/src/components/user-provider.tsx(1 hunks)apps/web/src/contexts/permissions.tsx(1 hunks)apps/web/src/contexts/preferences.tsx(1 hunks)apps/web/src/features/navigation/command-menu/command-menu.tsx(1 hunks)apps/web/src/features/space/ability.ts(1 hunks)apps/web/src/features/space/client.tsx(1 hunks)apps/web/src/features/space/components/space-dropdown.tsx(1 hunks)apps/web/src/features/space/constants.ts(1 hunks)apps/web/src/features/space/member/ability.ts(1 hunks)apps/web/src/features/user/ability.ts(3 hunks)apps/web/src/features/user/data.ts(3 hunks)apps/web/src/features/user/queries.ts(0 hunks)apps/web/src/features/user/schema.ts(2 hunks)apps/web/src/next-auth.ts(1 hunks)apps/web/src/trpc/context.ts(0 hunks)apps/web/src/trpc/routers/polls.ts(2 hunks)apps/web/src/trpc/routers/polls/participants.ts(1 hunks)apps/web/src/trpc/routers/user.ts(2 hunks)apps/web/src/trpc/server/create-ssr-helper.ts(0 hunks)biome.json(1 hunks)packages/posthog/package.json(1 hunks)packages/posthog/src/client.tsx(2 hunks)packages/posthog/tsconfig.json(0 hunks)packages/ui/src/avatar.tsx(1 hunks)packages/ui/src/sidebar.tsx(1 hunks)
💤 Files with no reviewable changes (6)
- apps/web/src/trpc/server/create-ssr-helper.ts
- apps/web/src/trpc/context.ts
- apps/web/src/app/[locale]/poll/[urlId]/page.tsx
- packages/posthog/tsconfig.json
- apps/web/src/features/user/queries.ts
- apps/web/src/app/[locale]/(space)/app-card.tsx
🧰 Additional context used
📓 Path-based instructions (7)
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit Inference Engine (.windsurfrules)
**/*.{js,jsx,ts,tsx}: Use dayjs for date handling
Use tailwindcss for styling
Use react-query for data fetching
Use react-hook-form for form handling
Prefer implicit return values over explicit return values
Use zod for form validation
Prefer double quotes for strings over single quotes
Only add comments when it is necessary to explain code that isn't self-explanatory
Files:
apps/web/src/app/[locale]/(space)/(dashboard)/polls/page.tsxapps/web/src/app/[locale]/(optional-space)/new/page.tsxapps/web/src/app/[locale]/(optional-space)/poll/[urlId]/guest-poll-alert.tsxapps/web/src/app/[locale]/(space)/(dashboard)/members/page.tsxapps/web/src/app/[locale]/poll/[urlId]/duplicate-dialog.tsxapps/web/src/auth/client.tsxapps/web/src/app/[locale]/(space)/(dashboard)/members/components/header.tsxapps/web/src/trpc/routers/user.tsapps/web/src/features/space/constants.tsapps/web/src/features/space/components/space-dropdown.tsxapps/web/src/components/forms/poll-settings.tsxapps/web/src/components/poll/poll-header.tsxapps/web/src/contexts/preferences.tsxapps/web/src/trpc/routers/polls.tsapps/web/src/app/components/logout-button.tsxpackages/ui/src/sidebar.tsxapps/web/src/app/[locale]/(optional-space)/poll/[urlId]/page.tsxapps/web/src/app/[locale]/(space)/account/profile/profile-picture.tsxapps/web/src/auth/data.tsapps/web/declarations/next-auth.d.tsapps/web/src/app/[locale]/(space)/account/billing/page.tsxapps/web/src/app/[locale]/(space)/account/profile/profile-email-address.tsxapps/web/src/features/user/data.tsapps/web/src/features/space/client.tsxapps/web/src/app/[locale]/(space)/layout.tsxapps/web/src/contexts/permissions.tsxapps/web/src/app/[locale]/(optional-space)/layout.tsxapps/web/src/components/new-participant-modal.tsxapps/web/src/features/space/ability.tsapps/web/src/features/user/schema.tsapps/web/src/app/[locale]/(space)/account/components/sign-out-button.tsxapps/web/src/components/create-poll.tsxapps/web/src/components/poll/manage-poll.tsxapps/web/src/app/[locale]/(space)/(dashboard)/components/sidebar/space-sidebar.tsxapps/web/src/app/[locale]/(space)/account/preferences/page.tsxpackages/ui/src/avatar.tsxapps/web/src/next-auth.tspackages/posthog/src/client.tsxapps/web/src/components/poll/notifications-toggle.tsxapps/web/src/features/space/member/ability.tsapps/web/src/trpc/routers/polls/participants.tsapps/web/src/app/[locale]/(space)/account/components/sidebar.tsxapps/web/src/features/navigation/command-menu/command-menu.tsxapps/web/src/app/[locale]/(space)/account/loading.tsxapps/web/src/app/[locale]/(space)/account/profile/page.tsxapps/web/src/components/optimized-avatar-image.tsxapps/web/src/app/[locale]/(space)/(dashboard)/layout.tsxapps/web/src/app/[locale]/(optional-space)/poll/[urlId]/duplicate-dialog.tsxapps/web/src/components/discussion/discussion.tsxapps/web/src/components/user-dropdown.tsxapps/web/src/app/[locale]/layout.tsxapps/web/src/app/[locale]/(space)/account/layout.tsxapps/web/src/components/layouts/poll-layout.tsxapps/web/src/features/user/ability.tsapps/web/src/components/user-provider.tsx
**/*.{ts,tsx}
📄 CodeRabbit Inference Engine (.windsurfrules)
Create separate import statements for types
Files:
apps/web/src/app/[locale]/(space)/(dashboard)/polls/page.tsxapps/web/src/app/[locale]/(optional-space)/new/page.tsxapps/web/src/app/[locale]/(optional-space)/poll/[urlId]/guest-poll-alert.tsxapps/web/src/app/[locale]/(space)/(dashboard)/members/page.tsxapps/web/src/app/[locale]/poll/[urlId]/duplicate-dialog.tsxapps/web/src/auth/client.tsxapps/web/src/app/[locale]/(space)/(dashboard)/members/components/header.tsxapps/web/src/trpc/routers/user.tsapps/web/src/features/space/constants.tsapps/web/src/features/space/components/space-dropdown.tsxapps/web/src/components/forms/poll-settings.tsxapps/web/src/components/poll/poll-header.tsxapps/web/src/contexts/preferences.tsxapps/web/src/trpc/routers/polls.tsapps/web/src/app/components/logout-button.tsxpackages/ui/src/sidebar.tsxapps/web/src/app/[locale]/(optional-space)/poll/[urlId]/page.tsxapps/web/src/app/[locale]/(space)/account/profile/profile-picture.tsxapps/web/src/auth/data.tsapps/web/declarations/next-auth.d.tsapps/web/src/app/[locale]/(space)/account/billing/page.tsxapps/web/src/app/[locale]/(space)/account/profile/profile-email-address.tsxapps/web/src/features/user/data.tsapps/web/src/features/space/client.tsxapps/web/src/app/[locale]/(space)/layout.tsxapps/web/src/contexts/permissions.tsxapps/web/src/app/[locale]/(optional-space)/layout.tsxapps/web/src/components/new-participant-modal.tsxapps/web/src/features/space/ability.tsapps/web/src/features/user/schema.tsapps/web/src/app/[locale]/(space)/account/components/sign-out-button.tsxapps/web/src/components/create-poll.tsxapps/web/src/components/poll/manage-poll.tsxapps/web/src/app/[locale]/(space)/(dashboard)/components/sidebar/space-sidebar.tsxapps/web/src/app/[locale]/(space)/account/preferences/page.tsxpackages/ui/src/avatar.tsxapps/web/src/next-auth.tspackages/posthog/src/client.tsxapps/web/src/components/poll/notifications-toggle.tsxapps/web/src/features/space/member/ability.tsapps/web/src/trpc/routers/polls/participants.tsapps/web/src/app/[locale]/(space)/account/components/sidebar.tsxapps/web/src/features/navigation/command-menu/command-menu.tsxapps/web/src/app/[locale]/(space)/account/loading.tsxapps/web/src/app/[locale]/(space)/account/profile/page.tsxapps/web/src/components/optimized-avatar-image.tsxapps/web/src/app/[locale]/(space)/(dashboard)/layout.tsxapps/web/src/app/[locale]/(optional-space)/poll/[urlId]/duplicate-dialog.tsxapps/web/src/components/discussion/discussion.tsxapps/web/src/components/user-dropdown.tsxapps/web/src/app/[locale]/layout.tsxapps/web/src/app/[locale]/(space)/account/layout.tsxapps/web/src/components/layouts/poll-layout.tsxapps/web/src/features/user/ability.tsapps/web/src/components/user-provider.tsx
**/*.{jsx,tsx}
📄 CodeRabbit Inference Engine (.windsurfrules)
**/*.{jsx,tsx}: All text in the UI should be translated using either the Trans component or the useTranslation hook
Prefer composable components in the style of shadcn UI over large monolithic components
DropdownMenuItem is a flex container with a preset gap so there is no need to add margins to the children
The size and colour of an icon should be set by wrapping it with the component from @rallly/ui/icon which will give it the correct colour and size.
Keep the props of a component as minimal as possible. Pass only the bare minimum amount of information needed to it.
All text in the UI should be translatable.
Always use a composable patterns when building components
Usecn()from @rallly/ui to compose classes
Prefer using the React module APIs (e.g. React.useState) instead of standalone hooks (e.g. useState)
Files:
apps/web/src/app/[locale]/(space)/(dashboard)/polls/page.tsxapps/web/src/app/[locale]/(optional-space)/new/page.tsxapps/web/src/app/[locale]/(optional-space)/poll/[urlId]/guest-poll-alert.tsxapps/web/src/app/[locale]/(space)/(dashboard)/members/page.tsxapps/web/src/app/[locale]/poll/[urlId]/duplicate-dialog.tsxapps/web/src/auth/client.tsxapps/web/src/app/[locale]/(space)/(dashboard)/members/components/header.tsxapps/web/src/features/space/components/space-dropdown.tsxapps/web/src/components/forms/poll-settings.tsxapps/web/src/components/poll/poll-header.tsxapps/web/src/contexts/preferences.tsxapps/web/src/app/components/logout-button.tsxpackages/ui/src/sidebar.tsxapps/web/src/app/[locale]/(optional-space)/poll/[urlId]/page.tsxapps/web/src/app/[locale]/(space)/account/profile/profile-picture.tsxapps/web/src/app/[locale]/(space)/account/billing/page.tsxapps/web/src/app/[locale]/(space)/account/profile/profile-email-address.tsxapps/web/src/features/space/client.tsxapps/web/src/app/[locale]/(space)/layout.tsxapps/web/src/contexts/permissions.tsxapps/web/src/app/[locale]/(optional-space)/layout.tsxapps/web/src/components/new-participant-modal.tsxapps/web/src/app/[locale]/(space)/account/components/sign-out-button.tsxapps/web/src/components/create-poll.tsxapps/web/src/components/poll/manage-poll.tsxapps/web/src/app/[locale]/(space)/(dashboard)/components/sidebar/space-sidebar.tsxapps/web/src/app/[locale]/(space)/account/preferences/page.tsxpackages/ui/src/avatar.tsxpackages/posthog/src/client.tsxapps/web/src/components/poll/notifications-toggle.tsxapps/web/src/app/[locale]/(space)/account/components/sidebar.tsxapps/web/src/features/navigation/command-menu/command-menu.tsxapps/web/src/app/[locale]/(space)/account/loading.tsxapps/web/src/app/[locale]/(space)/account/profile/page.tsxapps/web/src/components/optimized-avatar-image.tsxapps/web/src/app/[locale]/(space)/(dashboard)/layout.tsxapps/web/src/app/[locale]/(optional-space)/poll/[urlId]/duplicate-dialog.tsxapps/web/src/components/discussion/discussion.tsxapps/web/src/components/user-dropdown.tsxapps/web/src/app/[locale]/layout.tsxapps/web/src/app/[locale]/(space)/account/layout.tsxapps/web/src/components/layouts/poll-layout.tsxapps/web/src/components/user-provider.tsx
**/*.tsx
📄 CodeRabbit Inference Engine (.windsurfrules)
Add the "use client" directive to the top of any .tsx file that requires client-side javascript
Files:
apps/web/src/app/[locale]/(space)/(dashboard)/polls/page.tsxapps/web/src/app/[locale]/(optional-space)/new/page.tsxapps/web/src/app/[locale]/(optional-space)/poll/[urlId]/guest-poll-alert.tsxapps/web/src/app/[locale]/(space)/(dashboard)/members/page.tsxapps/web/src/app/[locale]/poll/[urlId]/duplicate-dialog.tsxapps/web/src/auth/client.tsxapps/web/src/app/[locale]/(space)/(dashboard)/members/components/header.tsxapps/web/src/features/space/components/space-dropdown.tsxapps/web/src/components/forms/poll-settings.tsxapps/web/src/components/poll/poll-header.tsxapps/web/src/contexts/preferences.tsxapps/web/src/app/components/logout-button.tsxpackages/ui/src/sidebar.tsxapps/web/src/app/[locale]/(optional-space)/poll/[urlId]/page.tsxapps/web/src/app/[locale]/(space)/account/profile/profile-picture.tsxapps/web/src/app/[locale]/(space)/account/billing/page.tsxapps/web/src/app/[locale]/(space)/account/profile/profile-email-address.tsxapps/web/src/features/space/client.tsxapps/web/src/app/[locale]/(space)/layout.tsxapps/web/src/contexts/permissions.tsxapps/web/src/app/[locale]/(optional-space)/layout.tsxapps/web/src/components/new-participant-modal.tsxapps/web/src/app/[locale]/(space)/account/components/sign-out-button.tsxapps/web/src/components/create-poll.tsxapps/web/src/components/poll/manage-poll.tsxapps/web/src/app/[locale]/(space)/(dashboard)/components/sidebar/space-sidebar.tsxapps/web/src/app/[locale]/(space)/account/preferences/page.tsxpackages/ui/src/avatar.tsxpackages/posthog/src/client.tsxapps/web/src/components/poll/notifications-toggle.tsxapps/web/src/app/[locale]/(space)/account/components/sidebar.tsxapps/web/src/features/navigation/command-menu/command-menu.tsxapps/web/src/app/[locale]/(space)/account/loading.tsxapps/web/src/app/[locale]/(space)/account/profile/page.tsxapps/web/src/components/optimized-avatar-image.tsxapps/web/src/app/[locale]/(space)/(dashboard)/layout.tsxapps/web/src/app/[locale]/(optional-space)/poll/[urlId]/duplicate-dialog.tsxapps/web/src/components/discussion/discussion.tsxapps/web/src/components/user-dropdown.tsxapps/web/src/app/[locale]/layout.tsxapps/web/src/app/[locale]/(space)/account/layout.tsxapps/web/src/components/layouts/poll-layout.tsxapps/web/src/components/user-provider.tsx
**/*
📄 CodeRabbit Inference Engine (.windsurfrules)
Always use kebab-case for file names
Files:
apps/web/src/app/[locale]/(space)/(dashboard)/polls/page.tsxapps/web/src/app/[locale]/(optional-space)/new/page.tsxapps/web/src/app/[locale]/(optional-space)/poll/[urlId]/guest-poll-alert.tsxapps/web/src/app/[locale]/(space)/(dashboard)/members/page.tsxapps/web/src/app/[locale]/poll/[urlId]/duplicate-dialog.tsxapps/web/src/auth/client.tsxapps/web/src/app/[locale]/(space)/(dashboard)/members/components/header.tsxapps/web/src/trpc/routers/user.tsapps/web/src/features/space/constants.tsapps/web/src/features/space/components/space-dropdown.tsxpackages/posthog/package.jsonapps/web/src/components/forms/poll-settings.tsxapps/web/src/components/poll/poll-header.tsxapps/web/src/contexts/preferences.tsxapps/web/src/trpc/routers/polls.tsapps/web/src/app/components/logout-button.tsxpackages/ui/src/sidebar.tsxapps/web/src/app/[locale]/(optional-space)/poll/[urlId]/page.tsxapps/web/src/app/[locale]/(space)/account/profile/profile-picture.tsxapps/web/src/auth/data.tsapps/web/declarations/next-auth.d.tsapps/web/src/app/[locale]/(space)/account/billing/page.tsxapps/web/src/app/[locale]/(space)/account/profile/profile-email-address.tsxapps/web/src/features/user/data.tsapps/web/src/features/space/client.tsxapps/web/src/app/[locale]/(space)/layout.tsxapps/web/src/contexts/permissions.tsxapps/web/src/app/[locale]/(optional-space)/layout.tsxapps/web/src/components/new-participant-modal.tsxapps/web/src/features/space/ability.tsapps/web/src/features/user/schema.tsapps/web/src/app/[locale]/(space)/account/components/sign-out-button.tsxbiome.jsonapps/web/src/components/create-poll.tsxapps/web/src/components/poll/manage-poll.tsxapps/web/src/app/[locale]/(space)/(dashboard)/components/sidebar/space-sidebar.tsxapps/web/src/app/[locale]/(space)/account/preferences/page.tsxpackages/ui/src/avatar.tsxapps/web/src/next-auth.tspackages/posthog/src/client.tsxapps/web/src/components/poll/notifications-toggle.tsxapps/web/src/features/space/member/ability.tsapps/web/src/trpc/routers/polls/participants.tsapps/web/src/app/[locale]/(space)/account/components/sidebar.tsxapps/web/src/features/navigation/command-menu/command-menu.tsxapps/web/src/app/[locale]/(space)/account/loading.tsxapps/web/src/app/[locale]/(space)/account/profile/page.tsxapps/web/src/components/optimized-avatar-image.tsxapps/web/src/app/[locale]/(space)/(dashboard)/layout.tsxapps/web/src/app/[locale]/(optional-space)/poll/[urlId]/duplicate-dialog.tsxapps/web/src/components/discussion/discussion.tsxapps/web/src/components/user-dropdown.tsxapps/web/src/app/[locale]/layout.tsxapps/web/src/app/[locale]/(space)/account/layout.tsxapps/web/src/components/layouts/poll-layout.tsxapps/web/src/features/user/ability.tsCLAUDE.mdapps/web/src/components/user-provider.tsx
**/*.ts
📄 CodeRabbit Inference Engine (.windsurfrules)
On the server use the
getTranslationsfunction from @/i18n/server to get the translations.
Files:
apps/web/src/trpc/routers/user.tsapps/web/src/features/space/constants.tsapps/web/src/trpc/routers/polls.tsapps/web/src/auth/data.tsapps/web/declarations/next-auth.d.tsapps/web/src/features/user/data.tsapps/web/src/features/space/ability.tsapps/web/src/features/user/schema.tsapps/web/src/next-auth.tsapps/web/src/features/space/member/ability.tsapps/web/src/trpc/routers/polls/participants.tsapps/web/src/features/user/ability.ts
packages/ui/**/*.{js,jsx,ts,tsx}
📄 CodeRabbit Inference Engine (.windsurfrules)
shadcn-ui components should be added to packages/ui
Files:
packages/ui/src/sidebar.tsxpackages/ui/src/avatar.tsx
🧠 Learnings (49)
📓 Common learnings
Learnt from: lukevella
PR: lukevella/rallly#1189
File: apps/web/src/utils/auth.ts:202-202
Timestamp: 2024-07-03T10:52:47.959Z
Learning: The `mergeGuestsIntoUser()` function in `apps/web/src/utils/auth.ts` is correctly awaited.
apps/web/src/app/[locale]/(space)/(dashboard)/polls/page.tsx (4)
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : All text in the UI should be translated using either the Trans component or the useTranslation hook
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{ts,tsx} : Create separate import statements for types
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{tsx} : Use the component in client components from @/components/trans. Use the defaults prop to provide the default text.
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : All text in the UI should be translatable.
apps/web/src/app/[locale]/(optional-space)/new/page.tsx (6)
Learnt from: lukevella
PR: #1189
File: apps/web/src/utils/auth.ts:202-202
Timestamp: 2024-07-03T10:52:47.959Z
Learning: The mergeGuestsIntoUser() function in apps/web/src/utils/auth.ts is correctly awaited.
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : All text in the UI should be translated using either the Trans component or the useTranslation hook
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : All text in the UI should be translatable.
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.ts : On the server use the getTranslations function from @/i18n/server to get the translations.
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{tsx} : Use the component in client components from @/components/trans. Use the defaults prop to provide the default text.
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Use react-query for data fetching
apps/web/src/app/[locale]/(optional-space)/poll/[urlId]/guest-poll-alert.tsx (2)
Learnt from: lukevella
PR: #1189
File: apps/web/src/utils/auth.ts:202-202
Timestamp: 2024-07-03T10:52:47.959Z
Learning: The mergeGuestsIntoUser() function in apps/web/src/utils/auth.ts is correctly awaited.
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : All text in the UI should be translatable.
apps/web/src/app/[locale]/(space)/(dashboard)/members/page.tsx (2)
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{ts,tsx} : Create separate import statements for types
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : All text in the UI should be translatable.
apps/web/src/app/[locale]/poll/[urlId]/duplicate-dialog.tsx (3)
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{tsx} : Use the component in client components from @/components/trans. Use the defaults prop to provide the default text.
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : All text in the UI should be translated using either the Trans component or the useTranslation hook
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : All text in the UI should be translatable.
apps/web/src/auth/client.tsx (2)
Learnt from: lukevella
PR: #1189
File: apps/web/src/utils/auth.ts:202-202
Timestamp: 2024-07-03T10:52:47.959Z
Learning: The mergeGuestsIntoUser() function in apps/web/src/utils/auth.ts is correctly awaited.
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.tsx : Add the "use client" directive to the top of any .tsx file that requires client-side javascript
apps/web/src/app/[locale]/(space)/(dashboard)/members/components/header.tsx (4)
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : The size and colour of an icon should be set by wrapping it with the component from @rallly/ui/icon which will give it the correct colour and size.
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{tsx} : Use the component in client components from @/components/trans. Use the defaults prop to provide the default text.
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : All text in the UI should be translated using either the Trans component or the useTranslation hook
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : All text in the UI should be translatable.
apps/web/src/trpc/routers/user.ts (1)
Learnt from: lukevella
PR: #1446
File: packages/emails/src/queue.ts:0-0
Timestamp: 2024-11-30T17:57:41.144Z
Learning: In the codebase, QStash is optional. The createQstashClient function in packages/emails/src/queue.ts should return null if QSTASH_TOKEN is not set, rather than throwing an error.
apps/web/src/features/space/components/space-dropdown.tsx (1)
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : DropdownMenuItem is a flex container with a preset gap so there is no need to add margins to the children
packages/posthog/package.json (4)
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Use react-query for data fetching
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Use react-hook-form for form handling
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.tsx : Add the "use client" directive to the top of any .tsx file that requires client-side javascript
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : Prefer using the React module APIs (e.g. React.useState) instead of standalone hooks (e.g. useState)
apps/web/src/components/poll/poll-header.tsx (1)
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : DropdownMenuItem is a flex container with a preset gap so there is no need to add margins to the children
apps/web/src/contexts/preferences.tsx (2)
Learnt from: lukevella
PR: #1189
File: apps/web/src/utils/auth.ts:202-202
Timestamp: 2024-07-03T10:52:47.959Z
Learning: The mergeGuestsIntoUser() function in apps/web/src/utils/auth.ts is correctly awaited.
Learnt from: lukevella
PR: #1776
File: apps/web/src/auth/adapters/prisma.ts:40-60
Timestamp: 2025-06-14T16:32:39.967Z
Learning: In the Rallly codebase, optional user fields like timeZone, weekStart, timeFormat, and locale correspond to nullable database columns, so passing undefined values won't cause insert failures.
apps/web/src/trpc/routers/polls.ts (1)
Learnt from: lukevella
PR: #1446
File: packages/emails/src/queue.ts:0-0
Timestamp: 2024-11-30T17:57:41.144Z
Learning: In the codebase, QStash is optional. The createQstashClient function in packages/emails/src/queue.ts should return null if QSTASH_TOKEN is not set, rather than throwing an error.
packages/ui/src/sidebar.tsx (7)
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : DropdownMenuItem is a flex container with a preset gap so there is no need to add margins to the children
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to packages/ui/**/*.{js,jsx,ts,tsx} : shadcn-ui components should be added to packages/ui
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : Prefer composable components in the style of shadcn UI over large monolithic components
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : Keep the props of a component as minimal as possible. Pass only the bare minimum amount of information needed to it.
Learnt from: smncd
PR: #1408
File: apps/web/src/components/poll/mobile-poll/time-slot-option.tsx:3-3
Timestamp: 2024-10-23T17:08:22.079Z
Learning: The project does not use CSS modules, so suggestions should avoid introducing them.
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : The size and colour of an icon should be set by wrapping it with the component from @rallly/ui/icon which will give it the correct colour and size.
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : Use cn() from @rallly/ui to compose classes
apps/web/src/app/[locale]/(optional-space)/poll/[urlId]/page.tsx (2)
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{tsx} : Use the component in client components from @/components/trans. Use the defaults prop to provide the default text.
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : Prefer composable components in the style of shadcn UI over large monolithic components
apps/web/src/app/[locale]/(space)/account/profile/profile-picture.tsx (2)
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : All text in the UI should be translated using either the Trans component or the useTranslation hook
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : Prefer using the React module APIs (e.g. React.useState) instead of standalone hooks (e.g. useState)
apps/web/src/auth/data.ts (2)
Learnt from: lukevella
PR: #1189
File: apps/web/src/utils/auth.ts:202-202
Timestamp: 2024-07-03T10:52:47.959Z
Learning: The mergeGuestsIntoUser() function in apps/web/src/utils/auth.ts is correctly awaited.
Learnt from: lukevella
PR: #1776
File: apps/web/src/auth/adapters/prisma.ts:40-60
Timestamp: 2025-06-14T16:32:39.967Z
Learning: In the Rallly authentication system, data migration (via options.migrateData) happens at login time, not during user creation. The createUser method in CustomPrismaAdapter should not call migrateData.
apps/web/declarations/next-auth.d.ts (1)
Learnt from: lukevella
PR: #1189
File: apps/web/src/utils/auth.ts:202-202
Timestamp: 2024-07-03T10:52:47.959Z
Learning: The mergeGuestsIntoUser() function in apps/web/src/utils/auth.ts is correctly awaited.
apps/web/src/app/[locale]/(space)/account/billing/page.tsx (5)
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : All text in the UI should be translatable.
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : All text in the UI should be translated using either the Trans component or the useTranslation hook
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{tsx} : Use the component in client components from @/components/trans. Use the defaults prop to provide the default text.
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : Prefer composable components in the style of shadcn UI over large monolithic components
Learnt from: lukevella
PR: #1557
File: packages/emails/src/templates/abandoned-checkout.tsx:0-0
Timestamp: 2025-02-12T04:21:35.353Z
Learning: In React components that display discount values in email templates, make the discount configurable through props with a default value to improve maintainability and reduce duplication.
apps/web/src/app/[locale]/(space)/account/profile/profile-email-address.tsx (8)
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : All text in the UI should be translated using either the Trans component or the useTranslation hook
Learnt from: lukevella
PR: #1557
File: packages/emails/src/templates/abandoned-checkout.tsx:0-0
Timestamp: 2025-02-12T04:21:35.353Z
Learning: In React components that display discount values in email templates, make the discount configurable through props with a default value to improve maintainability and reduce duplication.
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{tsx} : Use the component in client components from @/components/trans. Use the defaults prop to provide the default text.
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : All text in the UI should be translatable.
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : Prefer using the React module APIs (e.g. React.useState) instead of standalone hooks (e.g. useState)
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Use zod for form validation
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.ts : On the server use the getTranslations function from @/i18n/server to get the translations.
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Use react-hook-form for form handling
apps/web/src/features/user/data.ts (3)
Learnt from: lukevella
PR: #1189
File: apps/web/src/utils/auth.ts:202-202
Timestamp: 2024-07-03T10:52:47.959Z
Learning: The mergeGuestsIntoUser() function in apps/web/src/utils/auth.ts is correctly awaited.
Learnt from: lukevella
PR: #1189
File: apps/web/src/utils/auth.ts:202-202
Timestamp: 2024-10-09T07:45:26.195Z
Learning: The isEmailBlocked() function in apps/web/src/utils/auth.ts is not asynchronous.
Learnt from: lukevella
PR: #1776
File: apps/web/src/auth/adapters/prisma.ts:40-60
Timestamp: 2025-06-14T16:32:39.967Z
Learning: In the Rallly authentication system, data migration (via options.migrateData) happens at login time, not during user creation. The createUser method in CustomPrismaAdapter should not call migrateData.
apps/web/src/features/space/client.tsx (1)
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : Prefer using the React module APIs (e.g. React.useState) instead of standalone hooks (e.g. useState)
apps/web/src/app/[locale]/(space)/layout.tsx (2)
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : Prefer composable components in the style of shadcn UI over large monolithic components
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : Keep the props of a component as minimal as possible. Pass only the bare minimum amount of information needed to it.
apps/web/src/contexts/permissions.tsx (1)
Learnt from: lukevella
PR: #1189
File: apps/web/src/utils/auth.ts:202-202
Timestamp: 2024-07-03T10:52:47.959Z
Learning: The mergeGuestsIntoUser() function in apps/web/src/utils/auth.ts is correctly awaited.
apps/web/src/app/[locale]/(optional-space)/layout.tsx (4)
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{tsx} : Use the component in client components from @/components/trans. Use the defaults prop to provide the default text.
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : All text in the UI should be translated using either the Trans component or the useTranslation hook
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : Prefer composable components in the style of shadcn UI over large monolithic components
Learnt from: lukevella
PR: #1189
File: apps/web/src/utils/auth.ts:202-202
Timestamp: 2024-07-03T10:52:47.959Z
Learning: The mergeGuestsIntoUser() function in apps/web/src/utils/auth.ts is correctly awaited.
apps/web/src/components/new-participant-modal.tsx (6)
Learnt from: lukevella
PR: #1189
File: apps/web/src/utils/auth.ts:202-202
Timestamp: 2024-07-03T10:52:47.959Z
Learning: The mergeGuestsIntoUser() function in apps/web/src/utils/auth.ts is correctly awaited.
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.tsx : Add the "use client" directive to the top of any .tsx file that requires client-side javascript
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Use zod for form validation
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Use react-hook-form for form handling
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : All text in the UI should be translated using either the Trans component or the useTranslation hook
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : Prefer using the React module APIs (e.g. React.useState) instead of standalone hooks (e.g. useState)
apps/web/src/features/user/schema.ts (3)
Learnt from: lukevella
PR: #1189
File: apps/web/src/utils/auth.ts:202-202
Timestamp: 2024-07-03T10:52:47.959Z
Learning: The mergeGuestsIntoUser() function in apps/web/src/utils/auth.ts is correctly awaited.
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Use zod for form validation
Learnt from: lukevella
PR: #1776
File: apps/web/src/auth/adapters/prisma.ts:40-60
Timestamp: 2025-06-14T16:32:39.967Z
Learning: In the Rallly codebase, optional user fields like timeZone, weekStart, timeFormat, and locale correspond to nullable database columns, so passing undefined values won't cause insert failures.
biome.json (3)
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to /i18n//*.json : Never manually add translations to .json files. This will be handled by our tooling.
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to /i18n//*.json : i18n keys are in camelCase.
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Use tailwindcss for styling
apps/web/src/components/create-poll.tsx (5)
Learnt from: lukevella
PR: #1189
File: apps/web/src/utils/auth.ts:202-202
Timestamp: 2024-07-03T10:52:47.959Z
Learning: The mergeGuestsIntoUser() function in apps/web/src/utils/auth.ts is correctly awaited.
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Use react-hook-form for form handling
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : All text in the UI should be translated using either the Trans component or the useTranslation hook
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{tsx} : Use the component in client components from @/components/trans. Use the defaults prop to provide the default text.
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : Prefer using the React module APIs (e.g. React.useState) instead of standalone hooks (e.g. useState)
apps/web/src/components/poll/manage-poll.tsx (6)
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : All text in the UI should be translated using either the Trans component or the useTranslation hook
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{tsx} : Use the component in client components from @/components/trans. Use the defaults prop to provide the default text.
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : Prefer using the React module APIs (e.g. React.useState) instead of standalone hooks (e.g. useState)
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : Use cn() from @rallly/ui to compose classes
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : All text in the UI should be translatable.
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : DropdownMenuItem is a flex container with a preset gap so there is no need to add margins to the children
apps/web/src/app/[locale]/(space)/(dashboard)/components/sidebar/space-sidebar.tsx (8)
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : DropdownMenuItem is a flex container with a preset gap so there is no need to add margins to the children
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to packages/ui/**/*.{js,jsx,ts,tsx} : shadcn-ui components should be added to packages/ui
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : The size and colour of an icon should be set by wrapping it with the component from @rallly/ui/icon which will give it the correct colour and size.
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : All text in the UI should be translated using either the Trans component or the useTranslation hook
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{tsx} : Use the component in client components from @/components/trans. Use the defaults prop to provide the default text.
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : All text in the UI should be translatable.
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : Prefer composable components in the style of shadcn UI over large monolithic components
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : Use cn() from @rallly/ui to compose classes
apps/web/src/app/[locale]/(space)/account/preferences/page.tsx (4)
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{tsx} : Use the component in client components from @/components/trans. Use the defaults prop to provide the default text.
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : All text in the UI should be translated using either the Trans component or the useTranslation hook
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : All text in the UI should be translatable.
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : Prefer composable components in the style of shadcn UI over large monolithic components
packages/ui/src/avatar.tsx (2)
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : The size and colour of an icon should be set by wrapping it with the component from @rallly/ui/icon which will give it the correct colour and size.
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : Use cn() from @rallly/ui to compose classes
apps/web/src/next-auth.ts (1)
Learnt from: lukevella
PR: #1189
File: apps/web/src/utils/auth.ts:202-202
Timestamp: 2024-07-03T10:52:47.959Z
Learning: The mergeGuestsIntoUser() function in apps/web/src/utils/auth.ts is correctly awaited.
packages/posthog/src/client.tsx (4)
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : Prefer using the React module APIs (e.g. React.useState) instead of standalone hooks (e.g. useState)
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Use react-hook-form for form handling
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.tsx : Add the "use client" directive to the top of any .tsx file that requires client-side javascript
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Use react-query for data fetching
apps/web/src/components/poll/notifications-toggle.tsx (4)
Learnt from: lukevella
PR: #1189
File: apps/web/src/utils/auth.ts:202-202
Timestamp: 2024-07-03T10:52:47.959Z
Learning: The mergeGuestsIntoUser() function in apps/web/src/utils/auth.ts is correctly awaited.
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : All text in the UI should be translated using either the Trans component or the useTranslation hook
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : All text in the UI should be translatable.
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{tsx} : Use the component in client components from @/components/trans. Use the defaults prop to provide the default text.
apps/web/src/app/[locale]/(space)/account/components/sidebar.tsx (1)
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : All text in the UI should be translated using either the Trans component or the useTranslation hook
apps/web/src/features/navigation/command-menu/command-menu.tsx (6)
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to packages/ui/**/*.{js,jsx,ts,tsx} : shadcn-ui components should be added to packages/ui
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : The size and colour of an icon should be set by wrapping it with the component from @rallly/ui/icon which will give it the correct colour and size.
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : All text in the UI should be translated using either the Trans component or the useTranslation hook
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{tsx} : Use the component in client components from @/components/trans. Use the defaults prop to provide the default text.
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : Use cn() from @rallly/ui to compose classes
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : All text in the UI should be translatable.
apps/web/src/app/[locale]/(space)/account/profile/page.tsx (2)
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{tsx} : Use the component in client components from @/components/trans. Use the defaults prop to provide the default text.
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : All text in the UI should be translated using either the Trans component or the useTranslation hook
apps/web/src/components/optimized-avatar-image.tsx (3)
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : The size and colour of an icon should be set by wrapping it with the component from @rallly/ui/icon which will give it the correct colour and size.
Learnt from: lukevella
PR: #1557
File: packages/emails/src/templates/abandoned-checkout.tsx:0-0
Timestamp: 2025-02-12T04:21:35.353Z
Learning: In React components that display discount values in email templates, make the discount configurable through props with a default value to improve maintainability and reduce duplication.
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : Keep the props of a component as minimal as possible. Pass only the bare minimum amount of information needed to it.
apps/web/src/app/[locale]/(space)/(dashboard)/layout.tsx (1)
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : Prefer composable components in the style of shadcn UI over large monolithic components
apps/web/src/app/[locale]/(optional-space)/poll/[urlId]/duplicate-dialog.tsx (4)
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : All text in the UI should be translated using either the Trans component or the useTranslation hook
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{tsx} : Use the component in client components from @/components/trans. Use the defaults prop to provide the default text.
Learnt from: lukevella
PR: #1557
File: packages/emails/src/templates/abandoned-checkout.tsx:0-0
Timestamp: 2025-02-12T04:21:35.353Z
Learning: In React components that display discount values in email templates, make the discount configurable through props with a default value to improve maintainability and reduce duplication.
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : All text in the UI should be translatable.
apps/web/src/components/discussion/discussion.tsx (5)
Learnt from: lukevella
PR: #1189
File: apps/web/src/utils/auth.ts:202-202
Timestamp: 2024-07-03T10:52:47.959Z
Learning: The mergeGuestsIntoUser() function in apps/web/src/utils/auth.ts is correctly awaited.
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Use react-hook-form for form handling
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : Prefer using the React module APIs (e.g. React.useState) instead of standalone hooks (e.g. useState)
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : All text in the UI should be translated using either the Trans component or the useTranslation hook
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : Use cn() from @rallly/ui to compose classes
apps/web/src/components/user-dropdown.tsx (3)
Learnt from: lukevella
PR: #1189
File: apps/web/src/utils/auth.ts:202-202
Timestamp: 2024-07-03T10:52:47.959Z
Learning: The mergeGuestsIntoUser() function in apps/web/src/utils/auth.ts is correctly awaited.
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : The size and colour of an icon should be set by wrapping it with the component from @rallly/ui/icon which will give it the correct colour and size.
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : DropdownMenuItem is a flex container with a preset gap so there is no need to add margins to the children
apps/web/src/app/[locale]/layout.tsx (7)
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : All text in the UI should be translated using either the Trans component or the useTranslation hook
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : Use cn() from @rallly/ui to compose classes
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{tsx} : Use the component in client components from @/components/trans. Use the defaults prop to provide the default text.
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : The size and colour of an icon should be set by wrapping it with the component from @rallly/ui/icon which will give it the correct colour and size.
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : All text in the UI should be translatable.
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{js,jsx,ts,tsx} : Use tailwindcss for styling
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : Prefer composable components in the style of shadcn UI over large monolithic components
apps/web/src/app/[locale]/(space)/account/layout.tsx (3)
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : Prefer composable components in the style of shadcn UI over large monolithic components
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : The size and colour of an icon should be set by wrapping it with the component from @rallly/ui/icon which will give it the correct colour and size.
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : Use cn() from @rallly/ui to compose classes
apps/web/src/components/layouts/poll-layout.tsx (7)
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : All text in the UI should be translated using either the Trans component or the useTranslation hook
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{tsx} : Use the component in client components from @/components/trans. Use the defaults prop to provide the default text.
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : Use cn() from @rallly/ui to compose classes
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : Prefer composable components in the style of shadcn UI over large monolithic components
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : The size and colour of an icon should be set by wrapping it with the component from @rallly/ui/icon which will give it the correct colour and size.
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : Prefer using the React module APIs (e.g. React.useState) instead of standalone hooks (e.g. useState)
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.tsx : Add the "use client" directive to the top of any .tsx file that requires client-side javascript
apps/web/src/components/user-provider.tsx (3)
Learnt from: lukevella
PR: #1189
File: apps/web/src/utils/auth.ts:202-202
Timestamp: 2024-07-03T10:52:47.959Z
Learning: The mergeGuestsIntoUser() function in apps/web/src/utils/auth.ts is correctly awaited.
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.tsx : Add the "use client" directive to the top of any .tsx file that requires client-side javascript
Learnt from: CR
PR: lukevella/rallly#0
File: .windsurfrules:0-0
Timestamp: 2025-07-21T13:12:34.705Z
Learning: Applies to **/*.{jsx,tsx} : All text in the UI should be translated using either the Trans component or the useTranslation hook
🧬 Code Graph Analysis (27)
apps/web/src/app/[locale]/(optional-space)/new/page.tsx (2)
apps/web/src/next-auth.ts (1)
getLoggedIn(193-196)apps/web/src/features/instance-settings/queries.ts (1)
getInstanceSettings(7-27)
apps/web/src/app/[locale]/(optional-space)/poll/[urlId]/guest-poll-alert.tsx (1)
apps/web/src/trpc/routers/user.ts (1)
user(25-251)
apps/web/src/trpc/routers/user.ts (1)
apps/web/src/utils/emails.ts (1)
getEmailClient(9-34)
apps/web/src/features/space/components/space-dropdown.tsx (1)
packages/ui/src/dropdown-menu.tsx (1)
DropdownMenuSeparator(211-211)
apps/web/src/components/forms/poll-settings.tsx (1)
apps/web/src/features/space/client.tsx (1)
useSpace(26-28)
apps/web/src/contexts/preferences.tsx (1)
apps/web/src/trpc/routers/user.ts (1)
user(25-251)
apps/web/src/trpc/routers/polls.ts (1)
apps/web/src/utils/emails.ts (1)
getEmailClient(9-34)
apps/web/src/app/components/logout-button.tsx (1)
packages/ui/src/button.tsx (1)
ButtonProps(47-52)
apps/web/src/app/[locale]/(space)/account/profile/profile-picture.tsx (2)
apps/web/src/components/user-provider.tsx (1)
useAuthenticatedUser(29-36)apps/web/src/trpc/routers/user.ts (1)
user(25-251)
apps/web/src/auth/data.ts (1)
apps/web/src/features/user/data.ts (1)
getUser(21-33)
apps/web/src/app/[locale]/(space)/account/billing/page.tsx (2)
apps/web/src/app/components/page-layout.tsx (4)
PageContainer(6-15)PageHeader(36-53)PageTitle(17-34)PageContent(87-97)apps/web/src/app/[locale]/(space)/account/components/settings-layout.tsx (1)
SettingsContent(5-7)
apps/web/src/features/space/client.tsx (2)
apps/web/src/features/space/ability.ts (1)
defineAbilityForSpace(15-25)apps/web/src/features/space/member/ability.ts (1)
defineAbilityForMember(29-46)
apps/web/src/app/[locale]/(optional-space)/layout.tsx (2)
apps/web/src/auth/data.ts (1)
requireSpace(167-205)apps/web/src/features/space/client.tsx (1)
SpaceProvider(30-60)
apps/web/src/components/new-participant-modal.tsx (2)
apps/web/src/components/user-provider.tsx (1)
useUser(25-27)apps/web/src/auth/client.tsx (1)
createGuest(5-9)
apps/web/src/components/poll/manage-poll.tsx (1)
apps/web/src/features/space/client.tsx (1)
useSpace(26-28)
apps/web/src/app/[locale]/(space)/(dashboard)/components/sidebar/space-sidebar.tsx (4)
apps/web/src/features/space/components/space-dropdown.tsx (1)
SpaceDropdown(24-97)apps/web/src/features/space/components/space-icon.tsx (1)
SpaceIcon(12-18)packages/ui/src/icon.tsx (1)
Icon(33-50)packages/ui/src/sidebar.tsx (1)
SidebarSeparator(760-760)
apps/web/src/next-auth.ts (1)
apps/web/src/next-auth.config.ts (1)
session(24-32)
packages/posthog/src/client.tsx (1)
packages/posthog/src/server.ts (1)
posthog(14-14)
apps/web/src/trpc/routers/polls/participants.ts (2)
apps/web/src/utils/emails.ts (1)
getEmailClient(9-34)packages/utils/src/absolute-url.ts (1)
absoluteUrl(18-38)
apps/web/src/app/[locale]/(space)/account/loading.tsx (3)
apps/web/src/app/[locale]/(space)/account/preferences/loading.tsx (1)
Loading(3-5)apps/web/src/components/router-loading-indicator.tsx (1)
RouterLoadingIndicator(7-72)apps/web/src/app/components/page-layout.tsx (1)
PageSkeleton(99-129)
apps/web/src/app/[locale]/(space)/(dashboard)/layout.tsx (9)
apps/web/src/auth/data.ts (1)
requireUser(147-165)apps/web/src/features/setup/utils.ts (1)
isUserOnboarded(4-6)apps/web/src/app/[locale]/(space)/(dashboard)/components/sidebar/space-sidebar-provider.tsx (1)
SpaceSidebarProvider(6-22)apps/web/src/features/navigation/command-menu/command-menu.tsx (1)
CommandMenu(40-112)apps/web/src/app/[locale]/(space)/(dashboard)/components/sidebar/space-sidebar.tsx (1)
SpaceSidebar(40-137)packages/ui/src/sidebar.tsx (2)
SidebarInset(748-748)SidebarTrigger(761-761)apps/web/src/app/[locale]/(space)/(dashboard)/components/top-bar.tsx (3)
TopBar(3-20)TopBarLeft(22-24)TopBarRight(26-32)apps/web/src/components/optimized-avatar-image.tsx (1)
OptimizedAvatarImage(7-44)apps/web/src/features/licensing/components/license-limit-warning.tsx (1)
LicenseLimitWarning(7-42)
apps/web/src/components/discussion/discussion.tsx (3)
apps/web/src/components/user-provider.tsx (1)
useUser(25-27)apps/web/src/components/participants-provider.tsx (1)
useParticipants(16-18)apps/web/src/auth/client.tsx (1)
createGuest(5-9)
apps/web/src/components/user-dropdown.tsx (3)
apps/web/src/components/user-provider.tsx (1)
useAuthenticatedUser(29-36)packages/ui/src/dropdown-menu.tsx (1)
DropdownMenuItem(206-206)apps/web/src/next-auth.ts (1)
signOut(198-198)
apps/web/src/app/[locale]/layout.tsx (3)
packages/posthog/src/client.tsx (1)
PostHogIdentify(28-37)apps/web/src/app/posthog-page-view.tsx (1)
PostHogPageView(6-24)apps/web/src/components/user-provider.tsx (1)
UserProvider(38-56)
apps/web/src/app/[locale]/(space)/account/layout.tsx (4)
packages/ui/src/sidebar.tsx (11)
SidebarProvider(758-758)Sidebar(739-739)SidebarContent(740-740)SidebarGroup(742-742)SidebarGroupContent(744-744)SidebarMenu(749-749)SidebarMenuItem(753-753)SidebarMenuButton(752-752)SidebarGroupLabel(745-745)SidebarFooter(741-741)SidebarInset(748-748)packages/ui/src/icon.tsx (1)
Icon(33-50)apps/web/src/app/[locale]/(space)/account/components/sidebar.tsx (1)
AccountSidebarMenu(14-51)apps/web/src/app/[locale]/(space)/account/components/sign-out-button.tsx (1)
SignOutButton(12-35)
apps/web/src/features/user/ability.ts (2)
apps/web/src/features/user/schema.ts (1)
UserRole(6-6)apps/web/src/trpc/routers/user.ts (1)
user(25-251)
apps/web/src/components/user-provider.tsx (3)
apps/web/src/features/user/schema.ts (1)
UserDTO(8-21)apps/web/src/features/user/ability.ts (2)
UserAbility(18-18)defineAbilityFor(20-39)apps/web/src/utils/permissions.ts (1)
isOwner(1-10)
🪛 Biome (2.1.2)
apps/web/src/app/[locale]/(space)/account/billing/page.tsx
[error] 44-44: This import is unused.
Unused imports might be the result of an incomplete refactoring.
Unsafe fix: Remove the unused imports.
(lint/correctness/noUnusedImports)
[error] 45-45: This import is unused.
Unused imports might be the result of an incomplete refactoring.
Unsafe fix: Remove the unused imports.
(lint/correctness/noUnusedImports)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Integration tests
🔇 Additional comments (95)
biome.json (1)
65-67: Includes list looks solid—just double-check that all source roots are coveredRemoving the previous explicit exclusion is safe because
apps/landing/public/static/**is already outside thesrc/subtree, so it still won’t be linted.
Before merging, quickly verify that no other source folders (e.g. generated code, scripts, or storybook files) need lint coverage; otherwise add them now to avoid blind spots.CLAUDE.md (2)
9-16: Confirm stated framework versions are accurateThe doc claims “Next.js 15” and “React 19”. These versions are not publicly released at the moment; if you meant preview/beta versions, clarify that, otherwise adjust to the actual versions in
package.jsonto avoid confusing contributors.
120-126: Nice touch documenting code-style stackGood to see Biome + Tailwind standards spelled out here. That will help onboarding dramatically.
apps/web/src/app/[locale]/(space)/(dashboard)/polls/page.tsx (1)
16-16: Import alias looks goodSwitching to the
@/app/componentsalias improves path stability and avoids brittle relative paths. No further action needed.packages/ui/src/sidebar.tsx (1)
493-493: Visual-only tweak acknowledgedReducing the vertical gap from
gap-1.5togap-0.5is a harmless style refinement; no logical impact.apps/web/src/app/[locale]/(space)/(dashboard)/members/components/header.tsx (1)
18-18: Path change is correctLocal-relative import keeps the component co-located and reduces brittle absolute paths. Looks good.
apps/web/src/app/[locale]/(optional-space)/new/page.tsx (1)
15-18: Excellent performance optimization!Using
Promise.allto fetch bothisLoggedInandinstanceSettingsconcurrently reduces the total loading time since these operations are independent. This is a clean and effective optimization.apps/web/src/app/[locale]/(space)/(dashboard)/members/page.tsx (1)
20-21: LGTM: Improved local module organization.The change from absolute to relative imports for local components improves maintainability and makes the module structure more explicit within the members feature directory.
apps/web/src/components/poll/poll-header.tsx (1)
35-35: Good simplification of user presence check.Changing from
user.emailtouserdirectly is cleaner and more robust. This aligns well with the broader user context refactoring mentioned in the PR objectives.apps/web/src/app/[locale]/(optional-space)/poll/[urlId]/guest-poll-alert.tsx (1)
19-19: Excellent defensive programming improvement.Using optional chaining
user?.isGuest === falseprevents potential null/undefined access errors that could occur with the previous!user.isGuestcheck. This makes the code more robust and safe.apps/web/src/features/space/constants.ts (1)
1-1: Good environment-based feature flag implementation.Making
isSpacesEnabledconditional on the development environment is a solid approach for testing features in development while keeping them disabled in production. This follows standard feature flag best practices.apps/web/declarations/next-auth.d.ts (1)
13-13: LGTM! Clean type extension for guest user support.The addition of the
isGuestboolean property to the Session user interface is well-structured and aligns with the guest user authentication refactor described in the PR.apps/web/src/features/space/components/space-dropdown.tsx (1)
77-77: LGTM! Good UI refinement for menu item grouping.Moving the separator above the "Create Space" item improves the visual organization of the dropdown menu without affecting any functionality.
apps/web/src/trpc/routers/user.ts (2)
11-11: LGTM! Good refactor to centralize email client creation.The import of
getEmailClientsupports moving email client instantiation from user context methods to a standalone utility function, which improves code organization and reusability.
138-138: LGTM! Consistent with email client refactoring pattern.The change from
ctx.user.getEmailClient()togetEmailClient(ctx.user.locale)properly maintains the locale-specific email functionality while using the centralized email client creation pattern.apps/web/src/auth/client.tsx (1)
1-9: LGTM! Clean client-side utility for guest authentication.The
createGuestfunction is well-implemented:
- Properly uses "use client" directive for client-side functionality
- Correctly calls
signInwith the guest provider and redirect: false- Follows coding guidelines with implicit return and clear naming
This centralizes guest user creation and supports the authentication refactor.
apps/web/src/contexts/preferences.tsx (1)
71-71: LGTM! Good defensive programming to prevent runtime errors.Adding the null safety check (
user && !user.isGuest) prevents potential errors when the user object is undefined or null, while still properly excluding guests from server-side preference updates.apps/web/src/components/new-participant-modal.tsx (3)
13-13: LGTM! Import updated to use centralized guest creation.The import change aligns with the refactoring to move guest user creation from the user context to a standalone auth client function.
94-95: Improved logic clarity with explicit guest check.The updated user check
user && !user.isGuestis more explicit and readable than the previous approach, clearly distinguishing between authenticated users and guests.
115-117: Cleaner guest creation logic.The conditional
if (!user) { await createGuest(); }is more explicit and performant than the previous approach, only creating a guest when actually needed.packages/ui/src/avatar.tsx (1)
12-15: Enhanced visual hierarchy with differentiated border radius.The updated border radius classes (
rounded-lg,rounded,rounded-sm) create better visual differentiation between avatar sizes, improving the component's design consistency.apps/web/src/app/[locale]/(space)/account/loading.tsx (1)
1-1: Improved loading UX with structured skeleton.Replacing the
SpinnerwithPageSkeletonprovides a better loading experience by showing a structured layout that resembles the actual content, which is more informative to users.Also applies to: 8-8
apps/web/src/trpc/routers/polls.ts (2)
257-257: Consistent refactoring to standalone email client.The change from
ctx.user.getEmailClient()togetEmailClient(ctx.user.locale)aligns with the broader refactoring to decouple email client retrieval from the user context, improving separation of concerns.
803-803: Consistent email client usage pattern.Same refactoring applied here as in the poll creation flow, maintaining consistency across the codebase by using the standalone
getEmailClientfunction with locale parameter.packages/posthog/src/client.tsx (1)
3-3: Well-implemented PostHog identification component.The
PostHogIdentifycomponent follows best practices:
- Uses React module APIs as per coding guidelines
- Proper effect cleanup with dependency array
- Handles both user identification and reset scenarios
- Appropriate null return for side-effect-only component
Also applies to: 28-37
apps/web/src/app/[locale]/(optional-space)/poll/[urlId]/page.tsx (1)
1-5: Inconsistency between summary and code annotations.The AI summary indicates this component was removed, but the annotations show it as a new file with all lines added. Please clarify whether this file is being added or removed.
The component structure itself is clean and minimal, following React conventions as a simple wrapper component.
Likely an incorrect or invalid review comment.
apps/web/src/app/components/logout-button.tsx (2)
5-5: LGTM! Good refactoring to use standard next-auth signOut.This import aligns well with the broader refactoring to decouple authentication side effects from the user context.
16-16: Clean migration from custom logout to next-auth signOut.The change maintains the same async behavior while using the standard next-auth pattern. The onClick handler chaining is preserved correctly.
apps/web/src/features/space/ability.ts (2)
15-15: Good safety improvement making context optional.This change aligns with the broader refactoring to make context handling more resilient throughout the codebase.
18-18: Proper use of optional chaining for safety.The optional chaining prevents runtime errors when context is undefined while maintaining the existing permission logic correctly.
apps/web/src/contexts/permissions.tsx (1)
33-34: Good safety improvement with optional chaining.The optional chaining prevents runtime errors when the user object is undefined/null, which aligns well with the broader user context refactoring. The permission logic remains intact.
apps/web/src/features/user/schema.ts (1)
1-1: LGTM! Clean schema updates supporting guest user handling.The addition of the
isGuestboolean property and the type refinement oftimeFormatto use the specificTimeFormatenum from Prisma align well with the refactoring objectives. The separate import statement for the type also follows the coding guidelines correctly.Also applies to: 14-14, 17-17
apps/web/src/components/forms/poll-settings.tsx (1)
20-20: Space context and “hobby” tier mapping verifiedBoth concerns have been addressed:
- SpaceContext default value and the required SpaceProvider prop ensure
space.datais always defined (no null/undefined).- The
tierunion in features/space/types.ts ("hobby" | "pro") and the mapping in features/space/data.ts (subscription?.active ? "pro" : "hobby") confirm that"hobby"correctly represents the free tier.No further changes needed.
apps/web/src/features/user/data.ts (2)
3-3: LGTM! Good performance optimization with React cache.The addition of React's
cachewrapper aroundgetUseris an excellent performance optimization for repeated calls with the same user ID. This aligns with the centralization of user data access mentioned in the refactoring objectives.Also applies to: 21-21, 33-33
18-18: LGTM! Correct default for database users.Setting
isGuest: falsefor database users increateUserDTOis correct, as users stored in the database are registered users, not guests.apps/web/src/app/[locale]/(space)/account/preferences/page.tsx (1)
6-7: LGTM! Excellent adherence to coding guidelines and consistent layout pattern.The structured page layout using composable components (
PageContainer,PageHeader,PageContent) follows the shadcn UI style guidelines perfectly. The use of the<Trans>component with thedefaultsprop for the page title also adheres to the translation guidelines.This creates a consistent user experience across account pages as mentioned in the broader refactoring.
Also applies to: 10-21
apps/web/src/auth/data.ts (1)
8-8: LGTM! Excellent centralization of user data access.The replacement of direct Prisma calls with the cached
getUserfunction centralizes user data access and eliminates code duplication. This change:
- Benefits from the caching optimization in
getUser- Maintains consistent return types (UserDTO)
- Aligns with the broader refactoring to centralize user data handling
The functions continue to return the same UserDTO objects, ensuring no breaking changes to dependent code.
Also applies to: 19-19, 25-25, 158-158, 164-164
apps/web/src/components/poll/manage-poll.tsx (3)
30-30: LGTM: Import path updated for new directory structure.The import path correctly reflects the new
(optional-space)directory structure introduced in this refactor.
36-36: LGTM: Migration from user to space context for tier checks.The transition from
useUsertouseSpacehook aligns with the broader refactoring to centralize permission and tier checks around space data rather than user data. This change is consistent across the codebase.Also applies to: 130-130
207-207: LGTM: Consistent tier checking logic using space context.The paywall gating logic now correctly uses
space.data.tierinstead ofuser.tierfor both "finalize poll" and "duplicate poll" actions. This change aligns with the centralized space-based permission model.Also applies to: 236-236
apps/web/src/app/[locale]/(space)/account/profile/profile-picture.tsx (4)
6-6: LGTM: Updated imports for new user context pattern.The transition from
useUsertouseAuthenticatedUserhook and the addition of Next.jsuseRouteralign with the broader refactoring of user context management.Also applies to: 11-11
147-148: LGTM: Proper use of authenticated user hook and router.The
useAuthenticatedUserhook ensures the user is authenticated before accessing user data, and the router provides UI refresh functionality to replace the removed user context refresh method.
157-157: LGTM: Router-based UI refresh replaces user context refresh.Using
router.refresh()is the appropriate way to trigger UI updates after avatar operations, replacing the removedrefreshfunction from the user context.Also applies to: 164-164
161-161: Good defensive programming with null-safe check.The optional chaining (
user?.image) prevents potential runtime errors and is a good practice when dealing with user data that might be undefined.apps/web/src/next-auth.ts (1)
159-169: LGTM: Well-implemented session callback for guest user support.The session callback correctly enriches the session object with user data from the token and properly identifies guest users based on the absence of an email address. The logic aligns with the broader refactoring to support guest user workflows throughout the application.
Key implementation details:
- Proper null handling for email (defaulting to empty string)
- Clear guest user identification logic (
isGuest = !token.email)- Consistent with NextAuth patterns
apps/web/src/app/[locale]/(space)/account/billing/page.tsx (1)
65-71: LGTM: Consistent page layout structure.The introduction of
PageContainer,PageHeader,PageTitle, andPageContentcomponents creates a standardized layout structure that aligns with other account pages. This improves UI consistency across the application.Also applies to: 290-291
apps/web/src/app/[locale]/(space)/account/profile/page.tsx (2)
7-12: LGTM: Layout component imports for standardized page structure.The imports bring in the necessary components to create a consistent page layout structure across all account pages.
27-80: LGTM: Standardized page layout implementation.The profile page now follows the same layout structure as other account pages (
PageContainer→PageHeader→PageTitle→PageContent), creating a consistent user experience across the account section. All existing functionality is preserved within the new layout structure.apps/web/src/components/create-poll.tsx (3)
18-18: LGTM - Good architectural separation.Moving guest creation to a dedicated auth module improves separation of concerns and makes the authentication logic more modular.
43-43: LGTM - Context usage simplification.The simplified destructuring aligns with the refactored user context that now focuses on core user state rather than auth methods.
100-107: LGTM - Analytics updated for simplified user model.The removal of the
tierproperty aligns with the user context refactoring where tier-based logic has been moved to space context.apps/web/src/app/[locale]/(space)/(dashboard)/components/sidebar/space-sidebar.tsx (3)
24-24: LGTM - Consistent import path organization.The change to relative import aligns with the module resolution improvements mentioned in the PR objectives.
49-69: LGTM - Improved button implementation.The refactor to a native button element with enhanced styling improves both accessibility and visual design. The use of the
Iconcomponent follows the coding guidelines correctly.
120-120: LGTM - Improved spacing control.The addition of vertical margin classes enhances the visual spacing in the sidebar footer.
apps/web/src/features/space/client.tsx (2)
27-27: Simplified hook aligns with non-null context pattern.The removal of null checking is consistent with the initialized context. However, this means components will silently use default values instead of failing when SpaceProvider is missing, which could make debugging harder.
14-24: All useSpace calls are properly wrapped by SpaceProviderWe verified that SpaceProvider is declared in both
apps/web/src/app/[locale]/(optional-space)/layout.tsxapps/web/src/app/[locale]/(space)/layout.tsxand that all detected
useSpace()calls occur within those providers:
apps/web/src/components/forms/poll-settings.tsxapps/web/src/components/poll/manage-poll.tsxapps/web/src/app/[locale]/(space)/(dashboard)/members/components/header.tsxDefaults will only apply as intended. LGTM.
apps/web/src/app/[locale]/(optional-space)/layout.tsx (1)
21-21: LGTM - Appropriate fallback for optional space context.The fallback correctly returns unwrapped children for unauthenticated or guest users, allowing components to use the default space context values when space context isn't available.
apps/web/src/app/[locale]/(space)/layout.tsx (1)
30-30: LGTM - Good separation of layout concerns.The simplification effectively separates core layout functionality (data loading, context provision) from UI presentation, allowing the dashboard-specific layout to handle UI elements. This follows the composable component pattern and improves maintainability.
apps/web/src/app/[locale]/(space)/account/profile/profile-email-address.tsx (3)
24-24: LGTM: More specific hook improves type safety.The change to
useAuthenticatedUseris appropriate for a profile component that should only be accessible to authenticated users.
33-33: LGTM: Consistent with the new user context structure.
38-38: LGTM: Simplified based on guaranteed non-null email.The removal of the fallback empty string suggests that authenticated users are guaranteed to have an email address, which is reasonable for this profile component.
apps/web/src/features/space/member/ability.ts (3)
29-29: LGTM: Optional parameter improves flexibility.Making the context parameter optional allows for more defensive usage patterns and aligns with the broader refactor.
32-34: LGTM: Safe default for missing context.The guard clause appropriately returns an empty ability (no permissions) when no context is provided, which is the secure default behavior.
40-42: LGTM: Simplified switch statement with sensible default.Using the default case for member rules is appropriate and makes the code more maintainable by handling any new roles that might be added in the future with member-level permissions.
apps/web/src/app/[locale]/(space)/account/components/sign-out-button.tsx (6)
5-5: LGTM: Imports support the component refactor.The new imports align with the sidebar redesign and the addition of concurrent sign-out handling.
Also applies to: 8-9
14-14: LGTM: Proper use of React transitions.Using
useTransitionfor the sign-out process provides better user experience by handling the async operation smoothly without blocking the UI.
16-17: LGTM: Visual feedback during sign-out.The conditional loading indicator provides good user feedback during the sign-out process.
18-32: LGTM: Proper sidebar component integration.The switch to
SidebarMenuButtonwith proper icon wrapping aligns well with the sidebar redesign and follows the established UI patterns.
20-25: LGTM: Improved async handling and operation order.The proper awaiting of
signOutand sequencing of PostHog reset after sign-out ensures the analytics state is cleaned up only after successful sign-out.
16-16: LGTM: Fragment wrapper for multiple elements.The React fragment is necessary to return both the conditional loading indicator and the button.
Also applies to: 33-33
apps/web/src/trpc/routers/polls/participants.ts (1)
214-225: LGTM: Improved decoupling and explicit dependencies.The change from
ctx.user.getEmailClient()togetEmailClient(ctx.user.locale)makes the locale dependency explicit and decouples email client access from the user context, improving testability and clarity.apps/web/src/features/navigation/command-menu/command-menu.tsx (1)
13-13: LGTM: Admin-specific icons removed as intended.The removal of admin-related icons aligns with the broader refactoring to remove admin-specific UI elements from the command menu, leaving only the
PlusIconfor core functionality.apps/web/src/components/discussion/discussion.tsx (4)
31-31: LGTM: Guest creation centralized in auth client.The import of
createGuestfrom the auth client aligns with the refactoring to remove guest creation logic from the user context and centralize it in dedicated auth modules.
58-70: LGTM: Improved author name logic with explicit guest handling.The updated logic using the
isGuestproperty provides clearer guest user detection and appropriate fallback behavior for determining the comment author name.
96-98: LGTM: Simplified guest creation flow.The direct use of
createGuest()when no user exists is cleaner than the previouscreateGuestIfNeeded()approach, making the guest creation flow more explicit and straightforward.
115-115: LGTM: Correct conditional logic for author name input visibility.The condition
user && !user.isGuestproperly hides the author name input for authenticated non-guest users while keeping it visible for guest users and unauthenticated users who need to provide their name.apps/web/src/app/[locale]/(optional-space)/poll/[urlId]/duplicate-dialog.tsx (1)
1-79: LGTM: Well-implemented duplicate dialog component.The component follows all coding guidelines effectively:
- Proper use of "use client" directive
- Double quotes for strings
- Internationalization with Trans components
- Clean TypeScript typing with proper props extension
- PostHog analytics integration with relevant event data
- Proper async handling and navigation flow
The implementation is clean, composable, and handles all the necessary states (loading, success) appropriately.
apps/web/src/app/[locale]/layout.tsx (4)
4-4: LGTM: PostHog user identification component added.The addition of
PostHogIdentifyto the PostHog imports enables proper user identification for analytics tracking, which is implemented later in the layout.
15-15: LGTM: Import path updated to reflect module reorganization.The import path change from queries to data module aligns with the refactoring where
getUserwas moved and enhanced with React cache memoization.
56-56: LGTM: Simplified user data handling.The removal of session from destructuring and elimination of fallback logic makes the user data handling cleaner and more predictable, relying solely on the properly fetched user object.
77-77: LGTM: Enhanced analytics and simplified user provider.The addition of
PostHogIdentifyenables proper user identification for analytics, while the simplifiedUserProviderprops align with the refactored user context management. Both changes improve code clarity and functionality.Also applies to: 80-80
apps/web/src/app/[locale]/(space)/(dashboard)/layout.tsx (1)
1-66: LGTM: Well-structured dashboard layout with proper authentication.The layout implementation follows all coding guidelines effectively:
- Proper async data loading with authentication enforcement
- Responsive design with mobile-friendly top bar
- Clean component composition using shadcn UI patterns
- Appropriate onboarding checks with redirect
- Good accessibility with proper avatar alt text
- Consistent use of the updated user context pattern
The separation into reusable components (TopBar, SpaceSidebar, etc.) promotes maintainability and follows the composable component guidelines.
apps/web/src/components/poll/notifications-toggle.tsx (2)
31-31: LGTM - Null-safe user access implemented correctly.The optional chaining (
user?.id) properly handles cases whereusermight be undefined, preventing potential runtime errors.Also applies to: 47-47, 68-68
85-85: LGTM - Guest user handling implemented correctly.The button is properly disabled and the tooltip shows appropriate messaging for both unauthenticated users and guests.
Also applies to: 112-112
apps/web/src/components/user-dropdown.tsx (3)
31-34: LGTM - Authentication simplification implemented correctly.Using
useAuthenticatedUserensures this dropdown only renders for authenticated users, eliminating the need for conditional rendering based on authentication state.
72-77: LGTM - Profile menu item always rendered for authenticated users.Since the component now only handles authenticated users, the profile link can be rendered unconditionally.
133-141: LGTM - Simplified logout implementation.The direct use of
signOut()from next-auth/react is cleaner and more appropriate than the previous context-based logout method.apps/web/src/app/[locale]/(space)/account/layout.tsx (2)
1-26: LGTM - Proper imports and component structure.The imports are well-organized with type imports separated, and the component signature remains unchanged while implementing the new sidebar layout.
28-63: LGTM - Well-structured sidebar layout implementation.The sidebar layout is properly implemented with:
- Correct component nesting (SidebarProvider > Sidebar > SidebarContent/Footer)
- Proper use of translation components with defaults
- Icon usage following the coding guidelines
- Composable structure with separated navigation and settings groups
apps/web/src/components/layouts/poll-layout.tsx (1)
83-83: Verify poll-specific authorization is enforcedThe
PermissionGuardwrapper was removed fromPollLayout, leaving only the globalwithAuthmiddleware—which checks login but not granular poll access. Please confirm that poll-level permissions are now handled elsewhere, for example:
- In the server component at
apps/web/src/app/[locale]/poll/[pollId]/page.tsx
– ensure acanReadPoll(or equivalent) guard runs and returns a 403/redirect for unauthorized users.- In the API route at
apps/web/src/app/api/polls/[pollId]/route.ts
– apply the same authorization check before returning poll data.- Add or update tests to cover unauthorized access to a poll endpoint/page.
Once you’ve verified these, we can safely approve the layout simplification.
apps/web/src/features/user/ability.ts (2)
14-17: LGTM - Well-designed ability context type.The
UserAbilityContexttype is properly focused on authorization needs, containing only the essentialroleandidfields required for permission checks.
20-20: LGTM - Consistent type usage throughout ability functions.The parameter type updates are applied consistently across all ability definition functions, maintaining the same authorization logic with a cleaner interface.
Also applies to: 43-43, 80-80
apps/web/src/components/user-provider.tsx (3)
1-7: LGTM! Imports are well-organized.The "use client" directive is correctly placed at the top, and type imports are properly separated following the coding guidelines.
9-21: Well-structured type definitions using discriminated unions.The
GuestUsertype withisGuest: truecreates a clear discriminated union pattern withUserDTO, enabling proper type narrowing in TypeScript.
23-27: Context and hook implementation follows best practices.Good use of
useRequiredContextutility to ensure the context is properly provided and avoid null checks in consuming components.
| if (session?.user && !session.user.isGuest) { | ||
| const space = await requireSpace(); | ||
| return ( | ||
| <SpaceProvider data={space} userId={session.user.id}> | ||
| {children} | ||
| </SpaceProvider> | ||
| ); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
LGTM - Conditional space context logic is sound.
The conditional logic properly checks for authenticated non-guest users before providing space context. The implementation correctly uses the isGuest flag and provides the required props to SpaceProvider.
🏁 Script executed:
#!/bin/bash
# Description: Verify requireSpace error handling for users without spaces
# Check the requireSpace implementation to understand error handling
ast-grep --pattern 'export const requireSpace = $_'
# Also check for any error handling around requireSpace calls
rg -A 5 -B 2 'requireSpace\(\)'Length of output: 7990
Review requireSpace error handling for users without spaces
We confirmed that requireSpace() (apps/web/src/auth/data.ts:167–205) will:
- Return the user’s activeSpaceId space if present.
- Fall back to their owned space.
- Throw an AppError (code:
"NOT_FOUND", message:"User does not own any spaces") when no space exists.
In apps/web/src/app/[locale]/(optional-space)/layout.tsx, this error will bubble uncaught and surface as a server error. If your intent is to guide new users to create a space rather than show an error, wrap the call in a try/catch and redirect or render a fallback:
• File: apps/web/src/app/[locale]/(optional-space)/layout.tsx
Lines: ~12–19
Suggested change:
- if (session?.user && !session.user.isGuest) {
- const space = await requireSpace();
- return (
- <SpaceProvider data={space} userId={session.user.id}>
- {children}
- </SpaceProvider>
- );
- }
+ if (session?.user && !session.user.isGuest) {
+ try {
+ const space = await requireSpace();
+ return (
+ <SpaceProvider data={space} userId={session.user.id}>
+ {children}
+ </SpaceProvider>
+ );
+ } catch (error) {
+ if (error instanceof AppError && error.code === "NOT_FOUND") {
+ // Redirect new users to the onboarding/setup page
+ redirect(`/${session.user.locale}/setup`);
+ }
+ throw error;
+ }
+ }Otherwise, if an unhandled error is acceptable here, no change is needed.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if (session?.user && !session.user.isGuest) { | |
| const space = await requireSpace(); | |
| return ( | |
| <SpaceProvider data={space} userId={session.user.id}> | |
| {children} | |
| </SpaceProvider> | |
| ); | |
| } | |
| if (session?.user && !session.user.isGuest) { | |
| try { | |
| const space = await requireSpace(); | |
| return ( | |
| <SpaceProvider data={space} userId={session.user.id}> | |
| {children} | |
| </SpaceProvider> | |
| ); | |
| } catch (error) { | |
| if (error instanceof AppError && error.code === "NOT_FOUND") { | |
| // Redirect new users to the onboarding/setup page | |
| redirect(`/${session.user.locale}/setup`); | |
| } | |
| throw error; | |
| } | |
| } |
🤖 Prompt for AI Agents
In apps/web/src/app/[locale]/(optional-space)/layout.tsx around lines 12 to 19,
the call to requireSpace() can throw an AppError if the user does not own any
spaces, which currently bubbles up as a server error. To fix this, wrap the
requireSpace() call in a try/catch block and handle the "NOT_FOUND" error by
either redirecting the user to a space creation page or rendering a fallback UI
that guides them to create a space, preventing the server error from surfacing.
apps/web/src/app/[locale]/(space)/account/profile/profile-email-address.tsx
Outdated
Show resolved
Hide resolved
9b3bceb to
9d40130
Compare
Summary by CodeRabbit
New Features
Enhancements
Bug Fixes
Refactor
Chores
Documentation