Skip to content

Conversation

@lukevella
Copy link
Owner

@lukevella lukevella commented Jul 28, 2025

Summary by CodeRabbit

  • New Features

    • Introduced new layout components for authenticated and dashboard routes, enhancing navigation and sidebar experiences.
    • Added a Duplicate Poll dialog for easier poll management.
    • Implemented an account sidebar menu for streamlined account navigation.
    • Added a PostHogIdentify component for improved analytics identification.
  • Enhancements

    • Improved billing, profile, and preferences pages with consistent page layouts and support sections.
    • Updated sidebar, dropdown, and avatar UI styles for better visual consistency.
    • Optimized asynchronous data fetching for faster page loads.
    • Enhanced notification toggling and discussion forms for better guest and user handling.
  • Bug Fixes

    • Improved null safety and error prevention in user and guest checks across multiple components.
  • Refactor

    • Simplified user context, removed legacy logout and analytics logic, and updated ability/permission handling.
    • Reorganized imports and internal logic for better maintainability.
    • Removed unused or redundant components and files.
    • Removed access permission guard from poll layout for streamlined user experience.
    • Refactored account layout to a sidebar-based navigation structure.
    • Updated logout and sign-out flows to use standardized authentication methods.
  • Chores

    • Updated dependencies and configuration files for improved development experience.
    • Added a new package manifest for dayjs.
    • Adjusted feature flags for spaces based on environment.
  • Documentation

    • Updated type definitions and interface properties to reflect new guest user handling and time format types.

@vercel
Copy link

vercel bot commented Jul 28, 2025

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

Name Status Preview Comments Updated (UTC)
app ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jul 28, 2025 8:13pm
1 Skipped Deployment
Name Status Preview Comments Updated (UTC)
landing ⬜️ Skipped (Inspect) Jul 28, 2025 8:13pm

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jul 28, 2025

Walkthrough

This update refactors user and session management across the application, introducing a required isGuest boolean property to user objects and session types. It updates authentication, user context, and ability logic, removes or simplifies user tier/role checks, and adjusts UI components and layouts for improved guest handling and permissions. Several components and utility functions are updated, replaced, or removed to reflect these changes.

Changes

Cohort / File(s) Change Summary
User Session & Schema Updates
apps/web/declarations/next-auth.d.ts, apps/web/src/next-auth.ts, apps/web/src/features/user/schema.ts, apps/web/src/features/user/data.ts
Adds isGuest boolean to user/session types and ensures session callback sets this property; updates user DTO and caches user fetching.
User Context & Provider Refactor
apps/web/src/components/user-provider.tsx, apps/web/src/components/user-dropdown.tsx, apps/web/src/components/logout-button.tsx
Removes tier/role from context, eliminates logout method, adds useAuthenticatedUser hook, and updates logout flow to use signOut directly.
Authentication & Guest Handling
apps/web/src/app/[locale]/layout.tsx, apps/web/src/app/components/logout-button.tsx
Refactors user identification and PostHog analytics to always identify users; simplifies user prop handling.
Ability & Permissions Logic
apps/web/src/features/user/ability.ts, apps/web/src/features/space/ability.ts, apps/web/src/features/space/member/ability.ts, apps/web/src/features/space/client.tsx
Updates ability functions to use new user/space context types and optional parameters; simplifies space context default.
UI & Layout Refactors
apps/web/src/app/[locale]/(space)/account/layout.tsx, apps/web/src/app/[locale]/(space)/account/components/sidebar.tsx, apps/web/src/app/[locale]/(space)/account/profile/page.tsx, apps/web/src/app/[locale]/(space)/account/preferences/page.tsx, apps/web/src/app/[locale]/(space)/account/billing/page.tsx, apps/web/src/app/[locale]/(space)/account/loading.tsx, apps/web/src/app/[locale]/(space)/layout.tsx, apps/web/src/app/[locale]/(space)/(dashboard)/layout.tsx, apps/web/src/app/[locale]/(space)/(dashboard)/members/page.tsx, apps/web/src/app/[locale]/(space)/(dashboard)/members/components/header.tsx, apps/web/src/app/[locale]/(space)/(dashboard)/polls/page.tsx, apps/web/src/app/[locale]/(space)/(dashboard)/components/sidebar/space-sidebar.tsx
Refactors layouts to use sidebar navigation, updates profile and preferences pages to new layout components, adjusts imports, and removes or simplifies sidebar/topbar elements.
Poll & Participant Components
apps/web/src/app/[locale]/(optional-space)/poll/[urlId]/duplicate-dialog.tsx, apps/web/src/app/[locale]/(optional-space)/poll/[urlId]/guest-poll-alert.tsx, apps/web/src/app/[locale]/(optional-space)/poll/[urlId]/page.tsx, apps/web/src/app/[locale]/(optional-space)/new/page.tsx, apps/web/src/components/poll/manage-poll.tsx, apps/web/src/components/poll/poll-header.tsx, apps/web/src/components/poll/notifications-toggle.tsx, apps/web/src/components/layouts/poll-layout.tsx, apps/web/src/components/discussion/discussion.tsx, apps/web/src/components/new-participant-modal.tsx, apps/web/src/components/forms/poll-settings.tsx
Adds/updates poll duplication dialog, refines guest checks, updates paywall gating to use space tier, improves null safety, and removes permission guard component.
User Profile & Avatar
apps/web/src/app/[locale]/(space)/account/profile/profile-email-address.tsx, apps/web/src/app/[locale]/(space)/account/profile/profile-picture.tsx, apps/web/src/components/optimized-avatar-image.tsx
Switches to useAuthenticatedUser, updates avatar refresh logic to use router, and makes avatar size prop optional with default.
Utilities & Constants
apps/web/src/features/space/constants.ts, apps/web/src/features/user/queries.ts, apps/web/src/trpc/context.ts, apps/web/src/trpc/routers/polls.ts, apps/web/src/trpc/routers/polls/participants.ts, apps/web/src/trpc/routers/user.ts, apps/web/src/trpc/server/create-ssr-helper.ts
Updates feature flag to be environment-based, removes unused user queries and email client methods, and updates email sending logic to use standalone function.
PostHog Analytics
packages/posthog/src/client.tsx, packages/posthog/package.json
Adds PostHogIdentify component for user identification, adds React as dependency.
UI Library Adjustments
packages/ui/src/avatar.tsx, packages/ui/src/sidebar.tsx
Updates avatar border radius and sidebar menu gap for improved UI consistency.
Miscellaneous/Removals
apps/web/src/app/[locale]/(space)/app-card.tsx, apps/web/src/app/[locale]/poll/[urlId]/page.tsx, biome.json, packages/dayjs/package.json, packages/posthog/tsconfig.json
Removes unused components, updates config patterns, adds new package manifest, and cleans up tsconfig includes.

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
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

A rabbit hopped through fields of code,
With isGuest flags and sessions bestowed.
User roles and tiers now clear,
Permissions checked—no need to fear!
Sidebars shine, layouts align,
Analytics track each user sign.
Review complete—now time for tea,
Hooray for code simplicity! 🐇✨

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.


📜 Recent review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 45e7ecd and 3d605a5.

📒 Files selected for processing (3)
  • 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/components/page-layout.tsx (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/web/src/app/[locale]/(space)/(dashboard)/layout.tsx
  • apps/web/src/app/[locale]/(space)/(dashboard)/components/sidebar/space-sidebar.tsx
🧰 Additional context used
📓 Path-based instructions (5)
**/*.{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/components/page-layout.tsx
**/*.{ts,tsx}

📄 CodeRabbit Inference Engine (.windsurfrules)

Create separate import statements for types

Files:

  • apps/web/src/app/components/page-layout.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
Use cn() 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/components/page-layout.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/components/page-layout.tsx
**/*

📄 CodeRabbit Inference Engine (.windsurfrules)

Always use kebab-case for file names

Files:

  • apps/web/src/app/components/page-layout.tsx
🧠 Learnings (2)
📓 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/components/page-layout.tsx (5)

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} : 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} : 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

🧬 Code Graph Analysis (1)
apps/web/src/app/components/page-layout.tsx (1)
packages/ui/src/sidebar.tsx (1)
  • SidebarTrigger (761-761)
⏰ 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 (4)
apps/web/src/app/components/page-layout.tsx (4)

4-4: LGTM!

Clean import addition that follows the established pattern and is properly utilized in the component.


32-32: LGTM!

Well-positioned sidebar trigger that appropriately hides on medium+ screens, maintaining responsive design consistency.


48-48: LGTM!

Consistent breakpoint adjustment that aligns the header layout changes with the sidebar trigger visibility, creating cohesive responsive behavior.


97-97: LGTM!

Consistent breakpoint adjustment that maintains responsive design coherence across all page layout components.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch remove-unused-code

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

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

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

Support

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

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

CodeRabbit Commands (Invoked using PR comments)

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

Other keywords and placeholders

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

CodeRabbit Configuration File (.coderabbit.yaml)

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

Documentation and Community

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

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 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.mutate defines onSuccess but no onError. 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 size as 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: Provide defaults on every <Trans> usage

Client components are required to pass a fallback via the defaults prop. 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 t from "i18next" and title from "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 usePathname is a Next.js hook and useTranslation is 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 isGuest variable is derived from user, so including both in the dependencies array is redundant.

-  }, [user, isGuest]);
+  }, [user]);
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 24f172a and 70fb908.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is 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.tsx
  • apps/web/src/app/[locale]/(optional-space)/new/page.tsx
  • apps/web/src/app/[locale]/(optional-space)/poll/[urlId]/guest-poll-alert.tsx
  • apps/web/src/app/[locale]/(space)/(dashboard)/members/page.tsx
  • apps/web/src/app/[locale]/poll/[urlId]/duplicate-dialog.tsx
  • apps/web/src/auth/client.tsx
  • apps/web/src/app/[locale]/(space)/(dashboard)/members/components/header.tsx
  • apps/web/src/trpc/routers/user.ts
  • apps/web/src/features/space/constants.ts
  • apps/web/src/features/space/components/space-dropdown.tsx
  • apps/web/src/components/forms/poll-settings.tsx
  • apps/web/src/components/poll/poll-header.tsx
  • apps/web/src/contexts/preferences.tsx
  • apps/web/src/trpc/routers/polls.ts
  • apps/web/src/app/components/logout-button.tsx
  • packages/ui/src/sidebar.tsx
  • apps/web/src/app/[locale]/(optional-space)/poll/[urlId]/page.tsx
  • apps/web/src/app/[locale]/(space)/account/profile/profile-picture.tsx
  • apps/web/src/auth/data.ts
  • apps/web/declarations/next-auth.d.ts
  • apps/web/src/app/[locale]/(space)/account/billing/page.tsx
  • apps/web/src/app/[locale]/(space)/account/profile/profile-email-address.tsx
  • apps/web/src/features/user/data.ts
  • apps/web/src/features/space/client.tsx
  • apps/web/src/app/[locale]/(space)/layout.tsx
  • apps/web/src/contexts/permissions.tsx
  • apps/web/src/app/[locale]/(optional-space)/layout.tsx
  • apps/web/src/components/new-participant-modal.tsx
  • apps/web/src/features/space/ability.ts
  • apps/web/src/features/user/schema.ts
  • apps/web/src/app/[locale]/(space)/account/components/sign-out-button.tsx
  • apps/web/src/components/create-poll.tsx
  • apps/web/src/components/poll/manage-poll.tsx
  • apps/web/src/app/[locale]/(space)/(dashboard)/components/sidebar/space-sidebar.tsx
  • apps/web/src/app/[locale]/(space)/account/preferences/page.tsx
  • packages/ui/src/avatar.tsx
  • apps/web/src/next-auth.ts
  • packages/posthog/src/client.tsx
  • apps/web/src/components/poll/notifications-toggle.tsx
  • apps/web/src/features/space/member/ability.ts
  • apps/web/src/trpc/routers/polls/participants.ts
  • apps/web/src/app/[locale]/(space)/account/components/sidebar.tsx
  • apps/web/src/features/navigation/command-menu/command-menu.tsx
  • apps/web/src/app/[locale]/(space)/account/loading.tsx
  • apps/web/src/app/[locale]/(space)/account/profile/page.tsx
  • apps/web/src/components/optimized-avatar-image.tsx
  • apps/web/src/app/[locale]/(space)/(dashboard)/layout.tsx
  • apps/web/src/app/[locale]/(optional-space)/poll/[urlId]/duplicate-dialog.tsx
  • apps/web/src/components/discussion/discussion.tsx
  • apps/web/src/components/user-dropdown.tsx
  • apps/web/src/app/[locale]/layout.tsx
  • apps/web/src/app/[locale]/(space)/account/layout.tsx
  • apps/web/src/components/layouts/poll-layout.tsx
  • apps/web/src/features/user/ability.ts
  • apps/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.tsx
  • apps/web/src/app/[locale]/(optional-space)/new/page.tsx
  • apps/web/src/app/[locale]/(optional-space)/poll/[urlId]/guest-poll-alert.tsx
  • apps/web/src/app/[locale]/(space)/(dashboard)/members/page.tsx
  • apps/web/src/app/[locale]/poll/[urlId]/duplicate-dialog.tsx
  • apps/web/src/auth/client.tsx
  • apps/web/src/app/[locale]/(space)/(dashboard)/members/components/header.tsx
  • apps/web/src/trpc/routers/user.ts
  • apps/web/src/features/space/constants.ts
  • apps/web/src/features/space/components/space-dropdown.tsx
  • apps/web/src/components/forms/poll-settings.tsx
  • apps/web/src/components/poll/poll-header.tsx
  • apps/web/src/contexts/preferences.tsx
  • apps/web/src/trpc/routers/polls.ts
  • apps/web/src/app/components/logout-button.tsx
  • packages/ui/src/sidebar.tsx
  • apps/web/src/app/[locale]/(optional-space)/poll/[urlId]/page.tsx
  • apps/web/src/app/[locale]/(space)/account/profile/profile-picture.tsx
  • apps/web/src/auth/data.ts
  • apps/web/declarations/next-auth.d.ts
  • apps/web/src/app/[locale]/(space)/account/billing/page.tsx
  • apps/web/src/app/[locale]/(space)/account/profile/profile-email-address.tsx
  • apps/web/src/features/user/data.ts
  • apps/web/src/features/space/client.tsx
  • apps/web/src/app/[locale]/(space)/layout.tsx
  • apps/web/src/contexts/permissions.tsx
  • apps/web/src/app/[locale]/(optional-space)/layout.tsx
  • apps/web/src/components/new-participant-modal.tsx
  • apps/web/src/features/space/ability.ts
  • apps/web/src/features/user/schema.ts
  • apps/web/src/app/[locale]/(space)/account/components/sign-out-button.tsx
  • apps/web/src/components/create-poll.tsx
  • apps/web/src/components/poll/manage-poll.tsx
  • apps/web/src/app/[locale]/(space)/(dashboard)/components/sidebar/space-sidebar.tsx
  • apps/web/src/app/[locale]/(space)/account/preferences/page.tsx
  • packages/ui/src/avatar.tsx
  • apps/web/src/next-auth.ts
  • packages/posthog/src/client.tsx
  • apps/web/src/components/poll/notifications-toggle.tsx
  • apps/web/src/features/space/member/ability.ts
  • apps/web/src/trpc/routers/polls/participants.ts
  • apps/web/src/app/[locale]/(space)/account/components/sidebar.tsx
  • apps/web/src/features/navigation/command-menu/command-menu.tsx
  • apps/web/src/app/[locale]/(space)/account/loading.tsx
  • apps/web/src/app/[locale]/(space)/account/profile/page.tsx
  • apps/web/src/components/optimized-avatar-image.tsx
  • apps/web/src/app/[locale]/(space)/(dashboard)/layout.tsx
  • apps/web/src/app/[locale]/(optional-space)/poll/[urlId]/duplicate-dialog.tsx
  • apps/web/src/components/discussion/discussion.tsx
  • apps/web/src/components/user-dropdown.tsx
  • apps/web/src/app/[locale]/layout.tsx
  • apps/web/src/app/[locale]/(space)/account/layout.tsx
  • apps/web/src/components/layouts/poll-layout.tsx
  • apps/web/src/features/user/ability.ts
  • apps/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
Use cn() 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.tsx
  • apps/web/src/app/[locale]/(optional-space)/new/page.tsx
  • apps/web/src/app/[locale]/(optional-space)/poll/[urlId]/guest-poll-alert.tsx
  • apps/web/src/app/[locale]/(space)/(dashboard)/members/page.tsx
  • apps/web/src/app/[locale]/poll/[urlId]/duplicate-dialog.tsx
  • apps/web/src/auth/client.tsx
  • apps/web/src/app/[locale]/(space)/(dashboard)/members/components/header.tsx
  • apps/web/src/features/space/components/space-dropdown.tsx
  • apps/web/src/components/forms/poll-settings.tsx
  • apps/web/src/components/poll/poll-header.tsx
  • apps/web/src/contexts/preferences.tsx
  • apps/web/src/app/components/logout-button.tsx
  • packages/ui/src/sidebar.tsx
  • apps/web/src/app/[locale]/(optional-space)/poll/[urlId]/page.tsx
  • apps/web/src/app/[locale]/(space)/account/profile/profile-picture.tsx
  • apps/web/src/app/[locale]/(space)/account/billing/page.tsx
  • apps/web/src/app/[locale]/(space)/account/profile/profile-email-address.tsx
  • apps/web/src/features/space/client.tsx
  • apps/web/src/app/[locale]/(space)/layout.tsx
  • apps/web/src/contexts/permissions.tsx
  • apps/web/src/app/[locale]/(optional-space)/layout.tsx
  • apps/web/src/components/new-participant-modal.tsx
  • apps/web/src/app/[locale]/(space)/account/components/sign-out-button.tsx
  • apps/web/src/components/create-poll.tsx
  • apps/web/src/components/poll/manage-poll.tsx
  • apps/web/src/app/[locale]/(space)/(dashboard)/components/sidebar/space-sidebar.tsx
  • apps/web/src/app/[locale]/(space)/account/preferences/page.tsx
  • packages/ui/src/avatar.tsx
  • packages/posthog/src/client.tsx
  • apps/web/src/components/poll/notifications-toggle.tsx
  • apps/web/src/app/[locale]/(space)/account/components/sidebar.tsx
  • apps/web/src/features/navigation/command-menu/command-menu.tsx
  • apps/web/src/app/[locale]/(space)/account/loading.tsx
  • apps/web/src/app/[locale]/(space)/account/profile/page.tsx
  • apps/web/src/components/optimized-avatar-image.tsx
  • apps/web/src/app/[locale]/(space)/(dashboard)/layout.tsx
  • apps/web/src/app/[locale]/(optional-space)/poll/[urlId]/duplicate-dialog.tsx
  • apps/web/src/components/discussion/discussion.tsx
  • apps/web/src/components/user-dropdown.tsx
  • apps/web/src/app/[locale]/layout.tsx
  • apps/web/src/app/[locale]/(space)/account/layout.tsx
  • apps/web/src/components/layouts/poll-layout.tsx
  • apps/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.tsx
  • apps/web/src/app/[locale]/(optional-space)/new/page.tsx
  • apps/web/src/app/[locale]/(optional-space)/poll/[urlId]/guest-poll-alert.tsx
  • apps/web/src/app/[locale]/(space)/(dashboard)/members/page.tsx
  • apps/web/src/app/[locale]/poll/[urlId]/duplicate-dialog.tsx
  • apps/web/src/auth/client.tsx
  • apps/web/src/app/[locale]/(space)/(dashboard)/members/components/header.tsx
  • apps/web/src/features/space/components/space-dropdown.tsx
  • apps/web/src/components/forms/poll-settings.tsx
  • apps/web/src/components/poll/poll-header.tsx
  • apps/web/src/contexts/preferences.tsx
  • apps/web/src/app/components/logout-button.tsx
  • packages/ui/src/sidebar.tsx
  • apps/web/src/app/[locale]/(optional-space)/poll/[urlId]/page.tsx
  • apps/web/src/app/[locale]/(space)/account/profile/profile-picture.tsx
  • apps/web/src/app/[locale]/(space)/account/billing/page.tsx
  • apps/web/src/app/[locale]/(space)/account/profile/profile-email-address.tsx
  • apps/web/src/features/space/client.tsx
  • apps/web/src/app/[locale]/(space)/layout.tsx
  • apps/web/src/contexts/permissions.tsx
  • apps/web/src/app/[locale]/(optional-space)/layout.tsx
  • apps/web/src/components/new-participant-modal.tsx
  • apps/web/src/app/[locale]/(space)/account/components/sign-out-button.tsx
  • apps/web/src/components/create-poll.tsx
  • apps/web/src/components/poll/manage-poll.tsx
  • apps/web/src/app/[locale]/(space)/(dashboard)/components/sidebar/space-sidebar.tsx
  • apps/web/src/app/[locale]/(space)/account/preferences/page.tsx
  • packages/ui/src/avatar.tsx
  • packages/posthog/src/client.tsx
  • apps/web/src/components/poll/notifications-toggle.tsx
  • apps/web/src/app/[locale]/(space)/account/components/sidebar.tsx
  • apps/web/src/features/navigation/command-menu/command-menu.tsx
  • apps/web/src/app/[locale]/(space)/account/loading.tsx
  • apps/web/src/app/[locale]/(space)/account/profile/page.tsx
  • apps/web/src/components/optimized-avatar-image.tsx
  • apps/web/src/app/[locale]/(space)/(dashboard)/layout.tsx
  • apps/web/src/app/[locale]/(optional-space)/poll/[urlId]/duplicate-dialog.tsx
  • apps/web/src/components/discussion/discussion.tsx
  • apps/web/src/components/user-dropdown.tsx
  • apps/web/src/app/[locale]/layout.tsx
  • apps/web/src/app/[locale]/(space)/account/layout.tsx
  • apps/web/src/components/layouts/poll-layout.tsx
  • apps/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.tsx
  • apps/web/src/app/[locale]/(optional-space)/new/page.tsx
  • apps/web/src/app/[locale]/(optional-space)/poll/[urlId]/guest-poll-alert.tsx
  • apps/web/src/app/[locale]/(space)/(dashboard)/members/page.tsx
  • apps/web/src/app/[locale]/poll/[urlId]/duplicate-dialog.tsx
  • apps/web/src/auth/client.tsx
  • apps/web/src/app/[locale]/(space)/(dashboard)/members/components/header.tsx
  • apps/web/src/trpc/routers/user.ts
  • apps/web/src/features/space/constants.ts
  • apps/web/src/features/space/components/space-dropdown.tsx
  • packages/posthog/package.json
  • apps/web/src/components/forms/poll-settings.tsx
  • apps/web/src/components/poll/poll-header.tsx
  • apps/web/src/contexts/preferences.tsx
  • apps/web/src/trpc/routers/polls.ts
  • apps/web/src/app/components/logout-button.tsx
  • packages/ui/src/sidebar.tsx
  • apps/web/src/app/[locale]/(optional-space)/poll/[urlId]/page.tsx
  • apps/web/src/app/[locale]/(space)/account/profile/profile-picture.tsx
  • apps/web/src/auth/data.ts
  • apps/web/declarations/next-auth.d.ts
  • apps/web/src/app/[locale]/(space)/account/billing/page.tsx
  • apps/web/src/app/[locale]/(space)/account/profile/profile-email-address.tsx
  • apps/web/src/features/user/data.ts
  • apps/web/src/features/space/client.tsx
  • apps/web/src/app/[locale]/(space)/layout.tsx
  • apps/web/src/contexts/permissions.tsx
  • apps/web/src/app/[locale]/(optional-space)/layout.tsx
  • apps/web/src/components/new-participant-modal.tsx
  • apps/web/src/features/space/ability.ts
  • apps/web/src/features/user/schema.ts
  • apps/web/src/app/[locale]/(space)/account/components/sign-out-button.tsx
  • biome.json
  • apps/web/src/components/create-poll.tsx
  • apps/web/src/components/poll/manage-poll.tsx
  • apps/web/src/app/[locale]/(space)/(dashboard)/components/sidebar/space-sidebar.tsx
  • apps/web/src/app/[locale]/(space)/account/preferences/page.tsx
  • packages/ui/src/avatar.tsx
  • apps/web/src/next-auth.ts
  • packages/posthog/src/client.tsx
  • apps/web/src/components/poll/notifications-toggle.tsx
  • apps/web/src/features/space/member/ability.ts
  • apps/web/src/trpc/routers/polls/participants.ts
  • apps/web/src/app/[locale]/(space)/account/components/sidebar.tsx
  • apps/web/src/features/navigation/command-menu/command-menu.tsx
  • apps/web/src/app/[locale]/(space)/account/loading.tsx
  • apps/web/src/app/[locale]/(space)/account/profile/page.tsx
  • apps/web/src/components/optimized-avatar-image.tsx
  • apps/web/src/app/[locale]/(space)/(dashboard)/layout.tsx
  • apps/web/src/app/[locale]/(optional-space)/poll/[urlId]/duplicate-dialog.tsx
  • apps/web/src/components/discussion/discussion.tsx
  • apps/web/src/components/user-dropdown.tsx
  • apps/web/src/app/[locale]/layout.tsx
  • apps/web/src/app/[locale]/(space)/account/layout.tsx
  • apps/web/src/components/layouts/poll-layout.tsx
  • apps/web/src/features/user/ability.ts
  • CLAUDE.md
  • apps/web/src/components/user-provider.tsx
**/*.ts

📄 CodeRabbit Inference Engine (.windsurfrules)

On the server use the getTranslations function from @/i18n/server to get the translations.

Files:

  • apps/web/src/trpc/routers/user.ts
  • apps/web/src/features/space/constants.ts
  • apps/web/src/trpc/routers/polls.ts
  • apps/web/src/auth/data.ts
  • apps/web/declarations/next-auth.d.ts
  • apps/web/src/features/user/data.ts
  • apps/web/src/features/space/ability.ts
  • apps/web/src/features/user/schema.ts
  • apps/web/src/next-auth.ts
  • apps/web/src/features/space/member/ability.ts
  • apps/web/src/trpc/routers/polls/participants.ts
  • apps/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.tsx
  • packages/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 covered

Removing the previous explicit exclusion is safe because apps/landing/public/static/** is already outside the src/ 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 accurate

The 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.json to avoid confusing contributors.


120-126: Nice touch documenting code-style stack

Good 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 good

Switching to the @/app/components alias improves path stability and avoids brittle relative paths. No further action needed.

packages/ui/src/sidebar.tsx (1)

493-493: Visual-only tweak acknowledged

Reducing the vertical gap from gap-1.5 to gap-0.5 is a harmless style refinement; no logical impact.

apps/web/src/app/[locale]/(space)/(dashboard)/members/components/header.tsx (1)

18-18: Path change is correct

Local-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.all to fetch both isLoggedIn and instanceSettings concurrently 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.email to user directly 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 === false prevents potential null/undefined access errors that could occur with the previous !user.isGuest check. 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 isSpacesEnabled conditional 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 isGuest boolean 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 getEmailClient supports 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() to getEmailClient(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 createGuest function is well-implemented:

  • Properly uses "use client" directive for client-side functionality
  • Correctly calls signIn with 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.isGuest is 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 Spinner with PageSkeleton provides 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() to getEmailClient(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 getEmailClient function with locale parameter.

packages/posthog/src/client.tsx (1)

3-3: Well-implemented PostHog identification component.

The PostHogIdentify component 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 isGuest boolean property and the type refinement of timeFormat to use the specific TimeFormat enum 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 verified

Both concerns have been addressed:

  • SpaceContext default value and the required SpaceProvider prop ensure space.data is always defined (no null/undefined).
  • The tier union 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 cache wrapper around getUser is 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: false for database users in createUserDTO is 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 the defaults prop 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 getUser function centralizes user data access and eliminates code duplication. This change:

  1. Benefits from the caching optimization in getUser
  2. Maintains consistent return types (UserDTO)
  3. 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 useUser to useSpace hook 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.tier instead of user.tier for 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 useUser to useAuthenticatedUser hook and the addition of Next.js useRouter align 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 useAuthenticatedUser hook 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 removed refresh function 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, and PageContent components 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 (PageContainerPageHeaderPageTitlePageContent), 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 tier property 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 Icon component 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 SpaceProvider

We verified that SpaceProvider is declared in both

  • apps/web/src/app/[locale]/(optional-space)/layout.tsx
  • apps/web/src/app/[locale]/(space)/layout.tsx

and that all detected useSpace() calls occur within those providers:

  • apps/web/src/components/forms/poll-settings.tsx
  • apps/web/src/components/poll/manage-poll.tsx
  • apps/web/src/app/[locale]/(space)/(dashboard)/members/components/header.tsx

Defaults 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 useAuthenticatedUser is 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 useTransition for 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 SidebarMenuButton with 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 signOut and 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() to getEmailClient(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 PlusIcon for core functionality.

apps/web/src/components/discussion/discussion.tsx (4)

31-31: LGTM: Guest creation centralized in auth client.

The import of createGuest from 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 isGuest property 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 previous createGuestIfNeeded() 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.isGuest properly 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 PostHogIdentify to 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 getUser was 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 PostHogIdentify enables proper user identification for analytics, while the simplified UserProvider props 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 where user might 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 useAuthenticatedUser ensures 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 enforced

The PermissionGuard wrapper was removed from PollLayout, leaving only the global withAuth middleware—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 a canReadPoll (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 UserAbilityContext type is properly focused on authorization needs, containing only the essential role and id fields 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 GuestUser type with isGuest: true creates a clear discriminated union pattern with UserDTO, enabling proper type narrowing in TypeScript.


23-27: Context and hook implementation follows best practices.

Good use of useRequiredContext utility to ensure the context is properly provided and avoid null checks in consuming components.

Comment on lines +12 to +19
if (session?.user && !session.user.isGuest) {
const space = await requireSpace();
return (
<SpaceProvider data={space} userId={session.user.id}>
{children}
</SpaceProvider>
);
}
Copy link
Contributor

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.

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;
}
}
🤖 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.

@vercel vercel bot temporarily deployed to Preview – landing July 28, 2025 16:31 Inactive
@vercel vercel bot temporarily deployed to Preview – landing July 28, 2025 20:10 Inactive
@lukevella lukevella merged commit 7be4284 into main Jul 29, 2025
11 checks passed
@lukevella lukevella deleted the remove-unused-code branch July 29, 2025 09:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants