Skip to content

Conversation

@cyri113
Copy link
Contributor

@cyri113 cyri113 commented May 13, 2025

Summary by CodeRabbit

  • New Features

    • Added dashboard layout with authentication protection and context providers.
    • Introduced new dashboard pages: agent, community guardian, and settings.
    • Added MediaWiki platform management with create, edit, and list views including namespace selection and API path auto-detection.
    • Implemented authentication context with JWT token refresh and protected routes.
    • Added reusable form inputs: toggle switches, website URL input with validation, multi-checkbox selectors, and auto-detect path input.
    • Added sidebar and navbar components with dynamic navigation, nested menus, and responsive design including mobile backdrop.
    • Added loading screen component and refined loading indicators.
    • Introduced hooks for modules, platforms, sidebar navigation, admin role detection, and data sources.
    • Added module and platform list and item components with activation toggles and upvote buttons.
  • Enhancements

    • Refined layouts using Tailwind CSS and DaisyUI for consistent styling and responsive behavior.
    • Added logo images and improved page layouts for branding and user experience.
    • Simplified error and not-found pages for cleaner UI.
    • Updated chat and form styling for better consistency.
    • Redesigned sidebar with recursive nested menus and external data-driven items.
    • Improved handling of URL search parameters in platform integration components for accurate effect triggers.
  • Bug Fixes

    • Improved handling of authentication token expiration and storage clearing with updated redirect logic.
    • Fixed effect dependencies and query parameter handling in platform integration components.
  • Chores

    • Updated dependencies and build scripts, including Tailwind CSS plugins and Next.js configuration.
    • Removed deprecated components and pages such as the welcome page and legacy MediaWiki integration.
    • Cleaned up imports and reorganized code for maintainability.
    • Added CSS styles for tooltips and breadcrumbs.
    • Migrated Next.js config to CommonJS export and simplified configuration.

@coderabbitai
Copy link

coderabbitai bot commented May 13, 2025

Walkthrough

This update introduces a major refactor and feature expansion of the dashboard, platform, and module management systems. It adds new React components for platform and module lists, settings, and forms, implements new hooks for data fetching and mutations, and updates the sidebar and layout architecture. Several legacy pages and components are removed or replaced, and new UI state management is established using Jotai. Styling is enhanced with DaisyUI and typography plugins, and type definitions are expanded for modules, platforms, and JWT payloads.

Changes

File(s) / Group Change Summary
next.config.js, package.json, tailwind.config.js, tsconfig.json Updated Next.js configuration to comment out Cloudflare dev platform setup, removed output: 'export' and swcMinify options, adjusted export syntax, updated scripts, removed some dependencies, added Jotai, react-hook-form, DaisyUI, Tailwind typography plugin, and TypeScript plugins/includes.
src/app/layout.tsx, src/app/dashboard/layout.tsx, src/app/dashboard/settings/layout.tsx Added new layout components for dashboard and settings, integrating authentication, React Query, token context, protected routes, and breadcrumb navigation.
src/app/dashboard/page.tsx, src/app/dashboard/agent/page.tsx, src/app/dashboard/community-guardian/page.tsx, src/app/dashboard/settings/page.tsx, src/app/dashboard/settings/mediawiki/page.tsx, src/app/dashboard/settings/mediawiki/new/page.tsx, src/app/dashboard/settings/mediawiki/[id]/page.tsx, src/app/dashboard/settings/mediawiki/[id]/edit/page.tsx Added new dashboard pages including main dashboard, agent page, community guardian, settings, and MediaWiki platform management with client-side rendering and navigation guards.
src/atoms/authState.atom.ts, src/atoms/ui.atom.ts Introduced Jotai atoms for authentication token storage and UI state with persistent local storage.
src/axiosInstance.ts Modified 401 Unauthorized error handling and token refresh logic, adjusting local storage clearing order, toast notifications, and redirect behavior.
src/components/LoadingScreen.tsx Added a loading screen component with logo and animated spinner.
src/components/auth/ProtectedRoute.tsx Added a protected route component redirecting unauthenticated users and showing a loading screen during auth check.
src/components/centric/selectCommunity/TcSelectCommunity.tsx Updated to accept a loading callback prop, changed navigation route to dashboard, and removed unused imports.
src/components/centric/selectCommunity/TcCommunityItem.tsx, src/components/centric/selectCommunity/TcCommunityListItems.tsx Reorganized imports for clarity without functional changes.
src/components/chat/Chat.tsx, src/components/chat/ChatForm.tsx Adjusted chat container and form styling for improved layout and appearance.
src/components/communitySettings/HivemindSettings/TcHivemindMediaWiki.tsx, src/pages/centric/welcome.tsx, src/pages/_error.tsx Deleted legacy components/pages for MediaWiki settings UI, welcome page, and custom error page.
src/components/communitySettings/HivemindSettings/TcHivemindSettings.tsx Replaced MediaWiki form component import and updated props to new form interface.
src/components/communitySettings/communityPlatforms/TcCommunityPlatforms.tsx, src/components/communitySettings/communityPlatforms/TcDiscordIntgration.tsx, src/components/communitySettings/communityPlatforms/TcDiscourse.tsx, src/components/communitySettings/communityPlatforms/TcGithubIntegration.tsx, src/components/communitySettings/communityPlatforms/TcNotionIntegration.tsx, src/components/communitySettings/communityPlatforms/TcTelegram/TcTelegramIntegrationDialog.tsx, src/components/communitySettings/communityPlatforms/TcWebsite.tsx Refactored platform integration components to move query parameter extraction inside effect hooks and updated effect dependencies to track searchParams changes.
src/components/communitySettings/communityPlatforms/TcMediaWiki.tsx Removed full MediaWiki integration UI and logic; replaced with static message linking to new MediaWiki settings page; removed props and state.
src/components/home/modules/ModuleItem.tsx, src/components/home/modules/ModuleList.tsx, src/components/home/platforms/PlatformItem.tsx, src/components/home/platforms/PlatformList.tsx, src/components/home/platforms/UpvoteButton.tsx Added components for module and platform lists, individual items, and upvote button with event tracking.
src/components/inputs/AutoDetectPathInput.tsx, src/components/inputs/MultiCheckboxSelector.tsx, src/components/inputs/ToggleInput.tsx, src/components/inputs/WebsiteInput.tsx Added new form input components integrated with react-hook-form for path auto-detection, multi-checkbox selection, toggle inputs, and URL normalization/validation.
src/components/layouts/Breadcrumbs.tsx, src/components/layouts/DashboardLayout.tsx, src/components/layouts/Navbar.tsx, src/components/layouts/Sidebar.tsx, src/components/layouts/xs/SidebarXs.tsx Added and refactored layout/navigation components including a new sidebar with dynamic menu items from a hook, nested collapsible menus, and improved responsiveness and styling.
src/components/mediawiki/Form.tsx, src/components/mediawiki/List.tsx Added MediaWiki platform management form with namespace selection and paginated list/table components with detailed namespace tags and actions.
src/components/settings/modules/mediawiki/Form.tsx Added MediaWiki module form component for enabling/disabling the module with form state management.
src/constants/ModuleContext.ts, src/constants/PlatformContext.ts Added constants defining module and platform metadata, availability, routing paths, and admin-only flags.
src/context/AuthProvider.tsx Added authentication context provider and hook managing JWT tokens, decoding payloads, auto-refreshing tokens, and logout logic.
src/hooks/mediawiki/useNamespaces.ts, src/hooks/modules/useModuleActions.ts, src/hooks/modules/useModules.ts, src/hooks/platforms/usePlatformActions.ts, src/hooks/platforms/usePlatforms.ts, src/hooks/sidebar/useSidebar.ts, src/hooks/useAdmin.ts, src/hooks/useDatasources.ts Added custom hooks for fetching/mutating modules, platforms, namespaces, sidebar items, admin status, and data sources.
src/hooks/useApi.ts Updated to handle null or empty URL parameters safely by early return to avoid unnecessary requests.
src/layouts/centricLayout.tsx, src/layouts/defaultLayout.tsx Updated centric layout to remove logo and container; refactored default layout to use new dashboard layout component.
src/pages/_app.tsx, src/pages/index.tsx Minor whitespace and formatting changes.
src/pages/announcements/index.tsx, src/pages/community-settings/ai-assistant/index.tsx, src/pages/community-settings/index.tsx, src/pages/community-settings/violation-detection/index.tsx, src/pages/statistics.tsx Added or updated CSS classes for background color and rounded corners on container elements.
src/pages/callback.tsx Swapped loading indicator component to new LoadingScreen and added console logging in status handler.
src/pages/centric/create-new-community.tsx, src/pages/centric/index.tsx, src/pages/centric/select-community.tsx, src/pages/centric/tac.tsx Updated layout and loading indicators, added logo images, improved form structure, and managed loading state in community selection.
src/styles/globals.css Added global CSS styles for tooltips and breadcrumb navigation with accessibility and responsive design.
src/utils/JwtPayloadType.ts, src/utils/interfaces.ts Added and updated TypeScript type definitions for JWT payloads, modules, platforms, sidebar items, and MediaWiki-related types.
src/pages/_error.tsx Simplified error page component to a minimal functional component rendering a basic error message.
src/app/error.tsx Added simple client-side error component rendering an error heading.
src/app/global-error.tsx Added global error boundary component with retry button for error recovery.
src/app/not-found.tsx Added 404 not found page component with centered message and link to home, configured for edge runtime.
src/pages/404.tsx Added simple 404 page component rendering a heading.
src/pages/500.tsx Added simple 500 error page component rendering a heading.
src/app/dashboard/settings/layout.tsx Added client-side layout component for dashboard settings that renders children directly.
wrangler.toml Added Wrangler configuration file for Cloudflare Pages with project name, compatibility date, and build output directory.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant App
    participant AuthProvider
    participant API
    participant DashboardLayout
    participant Sidebar
    participant ModuleList
    participant PlatformList

    User->>App: Loads dashboard route
    App->>AuthProvider: Check authentication
    AuthProvider->>API: (If needed) Refresh token
    AuthProvider-->>App: Provide auth state
    App->>DashboardLayout: Render layout with Sidebar and Navbar
    DashboardLayout->>Sidebar: Render dynamic menu items
    DashboardLayout->>ModuleList: Fetch and render modules
    DashboardLayout->>PlatformList: Fetch and render platforms
    User->>Sidebar: Navigate to settings/module/platform
    Sidebar-->>App: Route change, update content
Loading
sequenceDiagram
    participant User
    participant MediaWikiForm
    participant API
    participant useNamespaces

    User->>MediaWikiForm: Enter MediaWiki base URL
    MediaWikiForm->>useNamespaces: Detect API path, fetch namespaces
    useNamespaces->>API: GET siteinfo/namespaces
    API-->>useNamespaces: Return namespaces
    useNamespaces-->>MediaWikiForm: Provide namespace options
    User->>MediaWikiForm: Select namespaces, submit form
    MediaWikiForm->>API: POST/PUT platform data
    API-->>MediaWikiForm: Confirm creation/update
Loading

Possibly related PRs

  • Development #392: Refactors and introduces components related to community selection, which aligns closely with the changes to TcSelectCommunity and related selection logic in this PR.
  • Development #405: Both PRs expand platform and module integration features, including UI for platform management and modular functionality.
  • Development #406: Adds the initial Chat component, which is further modified in this PR for improved layout and styling.

Poem

🐇
A dashboard reborn, with modules and flair,
Sidebars now smarter, and layouts with care.
MediaWiki managed, new forms on display,
Platforms and modules just clicks away!
With hooks and atoms, the state’s in control—
This rabbit’s quite proud of the code overhaul!
🌱✨

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

npm warn config production Use --omit=dev instead.
npm error Exit handler never called!
npm error This is an error with npm itself. Please report this error at:
npm error https://github.com/npm/cli/issues
npm error A complete log of this run can be found in: /.npm/_logs/2025-05-20T09_23_31_117Z-debug-0.log

Note

⚡️ AI Code Reviews for VS Code, Cursor, Windsurf

CodeRabbit now has a plugin for VS Code, Cursor and Windsurf. This brings AI code reviews directly in the code editor. Each commit is reviewed immediately, finding bugs before the PR is raised. Seamless context handoff to your AI code agent ensures that you can easily incorporate review feedback.
Learn more here.


Note

⚡️ Faster reviews with caching

CodeRabbit now supports caching for code and dependencies, helping speed up reviews. This means quicker feedback, reduced wait times, and a smoother review experience overall. Cached data is encrypted and stored securely. This feature will be automatically enabled for all accounts on May 16th. To opt out, configure Review - Disable Cache at either the organization or repository level. If you prefer to disable all data retention across your organization, simply turn off the Data Retention setting under your Organization Settings.
Enjoy the performance boost—your workflow just got faster.

✨ Finishing Touches
  • 📝 Generate Docstrings

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 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.

@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented May 13, 2025

Deploying frontend with  Cloudflare Pages  Cloudflare Pages

Latest commit: 5114387
Status: ✅  Deploy successful!
Preview URL: https://15f1cf77.frontend-28o.pages.dev
Branch Preview URL: https://mediawiki-settings.frontend-28o.pages.dev

View logs

Copy link

@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: 31

🔭 Outside diff range comments (2)
src/components/communitySettings/communityPlatforms/TcDiscordIntgration.tsx (1)

22-27: 💡 Verification agent

🧩 Analysis chain

Consider fixing the component name typo.

The component name has a typo: TcDiscordIntgration should be TcDiscordIntegration (missing an 'e'). This inconsistency can make the codebase harder to navigate.


🏁 Script executed:

#!/bin/bash
# Check for inconsistent naming of Discord integration component across the codebase

echo "Checking for instances of both TcDiscordIntgration and TcDiscordIntegration..."
echo "Files with TcDiscordIntgration:"
rg -l "TcDiscordIntgration" --type=tsx --type=ts

echo -e "\nFiles with TcDiscordIntegration:"
rg -l "TcDiscordIntegration" --type=tsx --type=ts

echo -e "\nChecking import statements to see where this component is used:"
rg "import.*TcDiscordIntgration" --type=tsx --type=ts

Length of output: 702


Let's retry the search without relying on ripgrep’s built-in file types and use globs instead:


🏁 Script executed:

#!/bin/bash
echo "Searching for 'TcDiscordIntgration' in .ts/.tsx files..."
rg -l "TcDiscordIntgration" -g '*.ts' -g '*.tsx'

echo -e "\nSearching for correct 'TcDiscordIntegration' in .ts/.tsx files..."
rg -l "TcDiscordIntegration" -g '*.ts' -g '*.tsx'

echo -e "\nChecking import statements for the typo variant..."
rg "import.*TcDiscordIntgration" -g '*.ts' -g '*.tsx'

Length of output: 1226


Fix component and filename typo from “Intgration” to “Integration”

Several files still use the misspelled TcDiscordIntgration. To avoid confusion, please rename the component, its props, the filename, and all imports:

• Rename

  • src/components/communitySettings/communityPlatforms/TcDiscordIntgration.tsxTcDiscordIntegration.tsx
  • TcDiscordIntgration.spec.tsxTcDiscordIntegration.spec.tsx

• Inside TcDiscordIntegration.tsx

-function TcDiscordIntgration({
-  platformType,
-  isLoading,
-  connectedPlatforms,
-  handleUpdateCommunityPlatform,
-}: TcDiscordIntgrationProps) {
+function TcDiscordIntegration({
+  platformType,
+  isLoading,
+  connectedPlatforms,
+  handleUpdateCommunityPlatform,
+}: TcDiscordIntegrationProps) {

• Update the props type name if declared in this file or a shared types file:

-type TcDiscordIntgrationProps = { … }
+type TcDiscordIntegrationProps = { … }

• Update imports in:

  • src/components/communitySettings/communityPlatforms/TcCommunityPlatforms.tsx
  • src/components/communitySettings/communityPlatforms/TcDiscordIntegration.spec.tsx

Example:

-import TcDiscordIntgration from "./TcDiscordIntgration";
+import TcDiscordIntegration from "./TcDiscordIntegration";

This ensures consistent naming and prevents import errors.

src/components/communitySettings/communityPlatforms/TcNotionIntegration.tsx (1)

74-74: 🛠️ Refactor suggestion

Improve error handling in the catch block.

The empty catch block swallows errors silently. Consider logging the error or showing a message to the user.

-    } catch (error) { }
+    } catch (error) {
+      showMessage(`Failed to disconnect platform: ${error instanceof Error ? error.message : 'Unknown error'}`, 'error');
+    }
🧹 Nitpick comments (71)
src/components/layouts/xs/SidebarXs.tsx (1)

54-62: Update Home navigation path
Changing the "Home" menu item's path to /dashboard ensures the mobile sidebar routes users into the new dashboard layout instead of the legacy welcome page.

Consider centralizing route definitions in a shared constants file (e.g., src/constants/routes.ts) to avoid hard-coding paths throughout components.

src/layouts/centricLayout.tsx (1)

1-17: Clean up commented-out Container and remove unused import
The Container wrapper has been commented out but the import remains. For clarity and maintainability, remove the commented code and drop the unused Container import.

-import React from 'react';
-import { Box, Container } from '@mui/material';
+import React from 'react';
+import { Box } from '@mui/material';
 
 interface ICentricLayout {
   children: React.ReactNode;
 }
 
 function centricLayout({ children }: ICentricLayout) {
   return (
     <Box className='min-h-screen w-screen' bgcolor='grey.100'>
-      {/* <Container
-        sx={{ textAlign: 'center', paddingY: '2rem' }}
-        className='space-y-6'
-      > */}
+      {children}
-      {/* </Container> */}
     </Box>
   );
 }
src/components/communitySettings/communityPlatforms/TcCommunityPlatforms.tsx (1)

52-52: Consider cleaning up commented code

There's a commented-out entry for the gdrive platform configuration. According to the AI summary, the import for TcGdriveIntegration was removed, but this config entry was left commented out. Consider either removing it completely or adding a comment explaining why it's kept.

-	// { name: "gdrive", component: TcGdriveIntegration, tabIndex: 7 },
+	// Removed gdrive integration temporarily - will be reimplemented in future release
src/components/communitySettings/communityPlatforms/TcDiscordIntgration.tsx (1)

4-4: Remove unused import.

The useRouter import is not being used anywhere in this component.

-import { useRouter } from "next/router";
src/hooks/platforms/usePlatformActions.ts (2)

28-28: Fix error message for createPlatform.

The error message for createPlatform incorrectly says "Failed to update platform" instead of "Failed to create platform".

-      showMessage(`Failed to update platform: ${error.message}`, "error");
+      showMessage(`Failed to create platform: ${error.message}`, "error");

10-19: Consider adding stronger typing for mutation parameters.

The type for the update and platform parameters is any, which isn't type-safe. Consider defining TypeScript interfaces for these parameters.

+interface PlatformUpdate {
+  name?: string;
+  displayName?: string;
+  description?: string;
+  // Add other platform properties as needed
+}

+interface PlatformCreate {
+  name: string;
+  displayName: string;
+  description?: string;
+  // Add other platform properties as needed
+}

 export const usePlatformActions = () => {
   const queryClient = useQueryClient();
   const { showMessage } = useSnackbar();

   const updatePlatform = useMutation({
-    mutationFn: ({ platformId, update }: { platformId: string, update: any }) => axiosInstance.patch(`/platforms/${platformId}`, update),
+    mutationFn: ({ platformId, update }: { platformId: string, update: PlatformUpdate }) => axiosInstance.patch(`/platforms/${platformId}`, update),
     // Rest of the code remains the same
   })

   const createPlatform = useMutation({
-    mutationFn: ({ platform }: { platform: any }) => axiosInstance.post(`/platforms`, platform),
+    mutationFn: ({ platform }: { platform: PlatformCreate }) => axiosInstance.post(`/platforms`, platform),
     // Rest of the code remains the same
   })

Also applies to: 21-30, 32-41

src/components/communitySettings/communityPlatforms/TcNotionIntegration.tsx (1)

54-54: Remove console.log statement.

Remove the console.log statement before pushing to production.

-      console.log("userProfile", userProfile);
src/hooks/useDatasources.ts (1)

28-29: Consider adding stronger typing for platforms

The current implementation uses any type for the platform objects, which could lead to type safety issues.

Consider using a more specific interface for platforms:

- community?.platforms?.map((platform: any) => platform.name) || [];
+ community?.platforms?.map((platform: { name: string }) => platform.name) || [];
src/hooks/modules/useModuleActions.ts (2)

1-22: Consider adding stronger typing for mutation parameters.

The hook is well-structured and follows React Query best practices. However, using any for the update and module parameters reduces type safety.

- mutationFn: ({ moduleId, update }: { moduleId: string, update: any }) => axiosInstance.patch(`/modules/${moduleId}`, update),
+ mutationFn: ({ moduleId, update }: { moduleId: string, update: Record<string, unknown> }) => axiosInstance.patch(`/modules/${moduleId}`, update),

- mutationFn: ({ module }: { module: any }) => axiosInstance.post(`/modules`, module),
+ mutationFn: ({ module }: { module: Record<string, unknown> }) => axiosInstance.post(`/modules`, module),

Even better would be to define specific module interfaces for stronger typing.


7-12: Consider adding error handling.

There's no error handling in the mutation callbacks. Adding onError handlers would help with logging errors and providing user feedback.

mutationFn: ({ moduleId, update }: { moduleId: string, update: any }) => axiosInstance.patch(`/modules/${moduleId}`, update),
onSuccess: () => {
  queryClient.invalidateQueries({ queryKey: ["modules"] });
},
+ onError: (error) => {
+   console.error('Failed to update module:', error);
+   // Handle error notification if needed
+ },
src/atoms/authState.atom.ts (2)

13-14: TODO comment is inconsistent with implemented code

The TODO comment suggests renaming to authState, but the atom is already named authState. This creates confusion about what action is needed.

-// TODO: rename to authState
+// Atom for storing authentication tokens in browser storage
 export const authState = atomWithStorage<AuthStateType>("TC_user", defaultValue);

14-14: Consider updating storage key name for consistency

The storage key "TC_user" appears to be a legacy name and doesn't match the atom name. For better maintainability, consider aligning the storage key with the atom name.

-export const authState = atomWithStorage<AuthStateType>("TC_user", defaultValue);
+export const authState = atomWithStorage<AuthStateType>("auth_state", defaultValue);
src/components/communitySettings/communityPlatforms/TcWebsite.tsx (1)

110-110: Use a consistent URL format in router navigation

The URL path used for redirection after closing the dialog doesn't follow a consistent format (has a trailing slash before the query parameter).

-		router.push('/community-settings/?managePlatform=website')
+		router.push('/community-settings?managePlatform=website')
src/hooks/modules/useModules.ts (1)

8-12: Add error handling for API requests

The hook doesn't include any error handling logic. Consider adding try/catch blocks or leveraging React Query's retry and onError capabilities for more robust error handling.

     enabled: !!communityId,
     queryFn: async () => {
-      const res = await axiosInstance.get(`/modules?community=${communityId}`);
-      return res.data;
+      try {
+        const res = await axiosInstance.get(`/modules?community=${communityId}`);
+        return res.data;
+      } catch (error) {
+        console.error("Error fetching modules:", error);
+        throw error;
+      }
     },
+    retry: 1,
src/app/dashboard/settings/mediawiki/[id]/edit/page.tsx (1)

26-26: Verify data structure before type casting.

The unsafe type casting from unknown to IPlatformProps could lead to runtime errors if the API response structure changes.

-        {data && <MediaWikiForm edit={data.data as unknown as IPlatformProps} />}
+        {data && data.data && <MediaWikiForm edit={data.data as IPlatformProps} />}
src/components/auth/ProtectedRoute.tsx (1)

18-20: Add a more descriptive message for unauthenticated users.

Currently, unauthenticated users only see a loading screen, which might be confusing. Consider adding a message that clearly indicates authentication is required.

   if (!isAuthenticated) {
-    return <LoadingScreen />;
+    return (
+      <div className="flex flex-col items-center justify-center h-screen">
+        <LoadingScreen />
+        <p className="mt-4 text-center text-gray-600">Verifying authentication...</p>
+      </div>
+    );
   }
src/pages/callback.tsx (2)

180-181: Fix typos in user-facing messages.

There are several typos in the error messages:

  • "Authorizion" should be "Authorization"
  • "faield" should be "failed"
      case StatusCode.DISCORD_AUTHORIZATION_FAILURE:
        setMessage('Authorization failed. Please try again.');
        router.push('/centric');
        break;

      case StatusCode.DISCORD_AUTHORIZATION_FROM_SETTINGS:
-       setMessage('Authorizion complete from settings page.');
+       setMessage('Authorization complete from settings page.');
        handleCreateNewPlatform(params);
        break;

      // ... other cases ...

      case StatusCode.DISCORD_AUTHORIZATION_FAILURE_FROM_SETTINGS:
-       setMessage('Discord Authorization during setup on setting faield.');
+       setMessage('Discord Authorization during setup on setting failed.');
        router.push('/community-settings');
        break;

      case StatusCode.ANNOUNCEMENTS_PERMISSION_FAILURE:
-       setMessage('Announcements grant write permissions faield.');
+       setMessage('Announcements grant write permissions failed.');
        router.push('/announcements');
        break;

Also applies to: 185-186, 211-211, 215-216


275-275: Consider reusing LoadingScreen with a message parameter.

Since you're replacing SimpleBackdrop with LoadingScreen, consider enhancing LoadingScreen to accept a message parameter to display the status messages you're setting.

-  return <LoadingScreen />
+  return <LoadingScreen message={message} />

This would require updating the LoadingScreen component to accept and display a message prop.

src/components/home/platforms/PlatformList.tsx (2)

16-18: Avoid potential errors when the data is undefined.

The platformExists function assumes that data?.results exists and is an array. Adding a defensive check would make the code more robust.

   const platformExists = (name: string) => {
-    return data?.results?.some((platform: IPlatformProps) => platform.name === name);
+    return Array.isArray(data?.results) && data.results.some((platform: IPlatformProps) => platform.name === name);
   }

24-33: Add a refresh mechanism for platforms data.

Consider adding a refresh button or pull-to-refresh mechanism to allow users to manually refresh the platforms data.

   return (
     <div className=" bg-white rounded-2xl divide-y divide-gray-100 text-slate-700">
       <div className="p-4">
-        <div className="text-xs font-semibold bg-gray-100 px-4 py-2 rounded-full w-fit">Data sources</div>
+        <div className="flex justify-between items-center">
+          <div className="text-xs font-semibold bg-gray-100 px-4 py-2 rounded-full w-fit">Data sources</div>
+          <button 
+            className="btn btn-sm btn-ghost btn-circle" 
+            onClick={() => refetch()}
+            title="Refresh data sources"
+          >
+            <svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
+              <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15" />
+            </svg>
+          </button>
+        </div>
       </div>
       <ul role="list" className="divide-y divide-gray-100 overflow-y-auto max-h-[385px]">
         {PLATFORM_CONTEXT.map((context, index) => <PlatformItem key={index} context={context} exists={platformExists(context.name)} />)}
       </ul>
     </div>
   );

This would require updating the query hook usage to include the refetch function:

-  const { data, isLoading, error } = usePlatforms(community?.id || undefined);
+  const { data, isLoading, error, refetch } = usePlatforms(community?.id || undefined);
src/components/home/platforms/UpvoteButton.tsx (2)

7-8: Consider using a more specific type for the community prop.

The community prop is typed as any, which loses type safety. Consider defining a specific interface or type for the community object to improve type safety and code quality.

-export function UpvoteButton({ community, name }: { community: any, name: string }) {
+interface CommunityProps {
+  id: string;
+  name: string;
+  // Add other required properties
+}
+
+export function UpvoteButton({ community, name }: { community: CommunityProps, name: string }) {

11-35: Add user feedback for error cases.

The error handling currently logs to console but doesn't show user-facing errors. Consider adding a user-facing error message through the snackbar when an upvote action fails.

 } catch (e) {
   console.error(e);
   setLoading(false);
+  showMessage(
+    'Failed to record your vote. Please try again.',
+    'error',
+  );
 }
src/constants/PlatformContext.ts (2)

20-23: Fix capitalization of "GitHub".

The standard spelling is "GitHub" (with a capital "H"), not "Github".

-    name: "github", title: "Github", available: true,
+    name: "github", title: "GitHub", available: true,

28-31: Consider standardizing MediaWiki name and path pattern.

Two issues to address:

  1. The standard spelling is "MediaWiki" (capital "W"), not "Mediawiki"
  2. This platform uses a different configPath pattern than other platforms (/dashboard/settings/mediawiki/ vs /community-settings?managePlatform=...)

Is this difference intentional? If so, consider adding a comment explaining why. If not, consider standardizing.

-    name: "mediaWiki", title: "Mediawiki", available: true,
+    name: "mediaWiki", title: "MediaWiki", available: true,

If the path pattern should be standardized:

-    configPath: "/dashboard/settings/mediawiki/"
+    configPath: "/community-settings?managePlatform=mediaWiki"
src/hooks/platforms/usePlatforms.ts (2)

4-5: Add return type for better type safety.

Consider adding a specific return type to the hook for improved type safety and better IDE support.

- export const usePlatforms = (communityId: string | undefined, name?: string, page?: number, limit?: number) => {
+ export const usePlatforms = (communityId: string | undefined, name?: string, page?: number, limit?: number): UseQueryResult<PlatformResponse> => {

You'll need to import UseQueryResult from '@tanstack/react-query' and define a PlatformResponse interface that matches the API response structure.


4-6: Remove unnecessary empty line.

There's an unnecessary empty line that can be removed for cleaner code.

export const usePlatforms = (communityId: string | undefined, name?: string, page?: number, limit?: number) => {
-
  return useQuery({
src/app/layout.tsx (2)

24-24: Consider syncing the theme with the uiAtom state.

The theme is hardcoded to "light" in the HTML data-theme attribute, but there's a theme value stored in the uiAtom. These should be synchronized to ensure consistent theme management across the application.

-    <html lang="en" data-theme="light">
+    <html lang="en" data-theme={ui.theme}>

You would need to add:

import { useAtom } from "jotai/react";
import { uiAtom } from "@/atoms/ui.atom";

// Inside the component
const [ui] = useAtom(uiAtom);

24-32: Consider adding meta viewport tag for better responsive design.

For proper mobile display and responsive design, it's recommended to add a viewport meta tag to the HTML head.

   <html lang="en" data-theme="light">
+    <head>
+      <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+    </head>
     <body className={`${inter.variable} ${roboto_mono.variable} antialiased`}>
src/components/layouts/DashboardLayout.tsx (2)

10-15: Rename toggle function for clarity.

The setIsSidebarOpen function name suggests it sets the sidebar to a specific state, but it's actually toggling the current state. Consider renaming for clarity.

-  const setIsSidebarOpen = () => {
+  const toggleSidebar = () => {
     setUi({ ...ui, isSidebarOpen: !ui.isSidebarOpen });
   }

And update the references:

-      <Sidebar isSidebarOpen={ui.isSidebarOpen} setIsSidebarOpen={setIsSidebarOpen} />
+      <Sidebar isSidebarOpen={ui.isSidebarOpen} setIsSidebarOpen={toggleSidebar} />
-      <Navbar isSidebarOpen={ui.isSidebarOpen} setIsSidebarOpen={setIsSidebarOpen} />
+      <Navbar isSidebarOpen={ui.isSidebarOpen} setIsSidebarOpen={toggleSidebar} />

20-22: Consider using semantic HTML for the main content area.

For better accessibility and semantic structure, consider using a <main> element for the primary content area instead of a <div>.

-      <div className={`flex-1 flex flex-col transition-all duration-300 overflow-y-hidden ${ui.isSidebarOpen ? 'lg:ml-16' : ''}`}>
+      <main className={`flex-1 flex flex-col transition-all duration-300 overflow-y-hidden ${ui.isSidebarOpen ? 'lg:ml-16' : ''}`}>
         <Navbar isSidebarOpen={ui.isSidebarOpen} setIsSidebarOpen={setIsSidebarOpen} />
         <div className="p-6 overflow-y-auto">
           {children}
         </div>
-      </div>
+      </main>
src/components/centric/selectCommunity/TcSelectCommunity.tsx (2)

74-74: Remove console.log statement.

There's a console.log statement that should be removed before production deployment.

-		console.log('community', community)

86-88: Consider showing feedback during loading.

When community loading is in progress, the component returns null. Consider showing a loading indicator or message to provide better user feedback.

if (communityLoading) {
-	return null;
+	return <div className="flex justify-center items-center py-4">
+		<span className="loading loading-spinner loading-md"></span>
+	</div>;
}
src/hooks/mediawiki/useNamespaces.ts (2)

1-3: Remove unused imports.

The file imports useEffect, useMemo, useState, and axios related types, but none of these are actually used in the implementation.

-import { useEffect, useMemo, useState } from "react";
+import { useQuery } from "@tanstack/react-query";
-import axios, { AxiosError, AxiosResponse } from 'axios';

17-18: Consider adding error handling for fetch operations.

The current implementation doesn't handle HTTP error responses (non-2xx status codes). The fetch API doesn't reject on HTTP error status codes by default.

-      const res = await fetch(url!.concat("?", params.toString()));
-      return res.json();
+      const res = await fetch(url!.concat("?", params.toString()));
+      if (!res.ok) {
+        throw new Error(`MediaWiki API error: ${res.status} ${res.statusText}`);
+      }
+      return res.json();
src/components/layouts/Breadcrumbs.tsx (4)

1-1: Fix spacing in import statement.

There's a missing space after the comma in the import.

-import { useEffect,useState } from "react";
+import { useEffect, useState } from "react";

18-23: Consider a more robust approach to building breadcrumb paths.

The current implementation of generating breadcrumb hrefs by slicing the pathname could be brittle for complex paths. Also, using a type assertion is unnecessary when the object literal already matches the interface.

    const breadcrumbs: Breadcrumb[] = paths.slice(1).map((path, index) => {
      return {
        label: path.charAt(0).toUpperCase() + path.slice(1),
-        href: pathname?.slice(0, pathname?.indexOf(path) + path.length) || '',
-      } as Breadcrumb;
+        href: '/' + paths.slice(1, index + 2).join('/'),
+      };
    });

33-41: Avoid using array indices as React keys when possible.

Using array indices as keys can cause issues if items are reordered. Consider using a more stable identifier, or in this case, the breadcrumb href which should be unique.

-        {breadcrumbs.map((breadcrumb, idx) => (
-          <li key={idx}>
+        {breadcrumbs.map((breadcrumb, idx) => (
+          <li key={breadcrumb.href}>

13-28: Handle edge cases for empty paths.

The current implementation might not handle certain edge cases correctly, such as when pathname is undefined or when there are multiple consecutive slashes in the path.

  useEffect(() => {
-    const paths = pathname?.split("/") || [];
+    if (!pathname) {
+      setBreadcrumbs([]);
+      return;
+    }
+    
+    // Handle multiple consecutive slashes and remove empty segments
+    const paths = pathname.split("/").filter(Boolean);
    const breadcrumbs: Breadcrumb[] = paths.slice(1).map((path) => {
      return {
        label: path.charAt(0).toUpperCase() + path.slice(1),
        href: pathname?.slice(0, pathname?.indexOf(path) + path.length) || '',
      } as Breadcrumb;
    });
    if (pathname?.endsWith('/')) {
      breadcrumbs.pop();
    }
    setBreadcrumbs(breadcrumbs);
  }, [pathname]);
src/app/dashboard/layout.tsx (1)

13-16: Remove unnecessary blank lines.

There are extra blank lines that should be removed for cleaner code.

export default function RootLayout({ children }: { children: React.ReactNode }) {
-

-
  return (
src/components/communitySettings/HivemindSettings/TcHivemindSettings.tsx (2)

547-549: Consider adding more type safety for the metadata conversion.

The code uses a type assertion (as IMediaWikiModuleFormPayload) which bypasses TypeScript's type checking. Consider adding runtime validation of the data shape.

payload={hivemindModule?.options?.platforms.find(
  (platform) => platform.name === 'mediaWiki'
-)?.metadata as IMediaWikiModuleFormPayload || { activated: false }}
+)?.metadata?.hasOwnProperty('activated') 
+  ? hivemindModule?.options?.platforms.find(p => p.name === 'mediaWiki')?.metadata as IMediaWikiModuleFormPayload 
+  : { activated: false }}

320-320: Remove console.log statement.

There's a console.log statement that should be removed before committing.

-      console.log(data);
src/components/settings/modules/mediawiki/Form.tsx (1)

24-41: Consider adding form validation feedback

The form UI looks good with the toggle input and properly disabled submit button during loading. However, there's no visual feedback for users after form submission (success or error states).

You could add a success message after successful submission:

  const onSubmit = (data: IMediaWikiModuleFormPayload) => {
    patch(data);
+   methods.reset(data); // Reset form with new values
  };

+  // Add this state
+  const [showSuccess, setShowSuccess] = useState(false);
+
+  // Update the patch function to show success
+  const handlePatch = (data: IMediaWikiModuleFormPayload) => {
+    patch(data);
+    setShowSuccess(true);
+    setTimeout(() => setShowSuccess(false), 3000);
+  };

And then display a success message in your UI when showSuccess is true.

src/components/communitySettings/communityPlatforms/TcMediaWiki.tsx (2)

1-7: Fix code formatting inconsistency

The code uses inconsistent indentation with a mix of tabs and spaces. This can cause readability issues and potential problems with some code editors.

function TcMediaWiki() {
-	return (
-		<div className="flex flex-col gap-4">
-			<h2 className="text-2xl font-bold">MediaWiki</h2>
-			<p className="text-sm text-gray-500">We are improving our app. Head over to <a href="/dashboard/settings/mediawiki" className="text-blue-500">MediaWiki Settings</a> to manage your settings.</p>
-		</div>
-	)
+  return (
+    <div className="flex flex-col gap-4">
+      <h2 className="text-2xl font-bold">MediaWiki</h2>
+      <p className="text-sm text-gray-500">We are improving our app. Head over to <a href="/dashboard/settings/mediawiki" className="text-blue-500">MediaWiki Settings</a> to manage your settings.</p>
+    </div>
+  )
}

5-5: Consider using Next.js Link component for internal navigation

The implementation uses a standard HTML anchor tag for internal navigation. For Next.js applications, using the Link component is preferred for client-side navigation.

- <p className="text-sm text-gray-500">We are improving our app. Head over to <a href="/dashboard/settings/mediawiki" className="text-blue-500">MediaWiki Settings</a> to manage your settings.</p>
+ import Link from 'next/link';
+ <p className="text-sm text-gray-500">We are improving our app. Head over to <Link href="/dashboard/settings/mediawiki" className="text-blue-500">MediaWiki Settings</Link> to manage your settings.</p>
src/components/home/platforms/PlatformItem.tsx (3)

28-43: Remove unnecessary fragment wrapper

There's an unnecessary empty fragment wrapper (<></>) that can be removed to simplify the component structure.

        {!context.available ? (
          <UpvoteButton community={community} name={context.name} />
        ) : (
-          <>
            <div className="flex items-center gap-4">
              {exists ? (
                <div className="w-2 h-2 bg-success rounded-full"></div>
              ) : (
                <div className="w-2 h-2 bg-base-300 rounded-full"></div>
              )}
              {isAdmin && (
                <a href={context.configPath} className="btn btn-sm btn-square">
                  <FaCog />
                </a>
              )}

            </div>
-          </>
        )}

35-39: Consider using Next.js Link component for config path navigation

For internal navigation to the config path, it's better to use the Next.js Link component instead of a standard anchor tag to enable client-side navigation.

+ import Link from 'next/link';

// Then in the component:
              {isAdmin && (
-                <a href={context.configPath} className="btn btn-sm btn-square">
+                <Link href={context.configPath} className="btn btn-sm btn-square">
                  <FaCog />
-                </a>
+                </Link>
              )}

29-34: Add accessibility improvements for status indicators

The status indicators (green and gray dots) lack accessibility features that would help users with screen readers understand their meaning.

              {exists ? (
-                <div className="w-2 h-2 bg-success rounded-full"></div>
+                <div 
+                  className="w-2 h-2 bg-success rounded-full" 
+                  aria-label="Platform active" 
+                  role="status"
+                  title="Platform active"
+                ></div>
              ) : (
-                <div className="w-2 h-2 bg-base-300 rounded-full"></div>
+                <div 
+                  className="w-2 h-2 bg-base-300 rounded-full" 
+                  aria-label="Platform inactive" 
+                  role="status"
+                  title="Platform inactive"
+                ></div>
              )}
src/components/inputs/AutoDetectPathInput.tsx (1)

45-71: Add retry mechanism for failed detection

The component doesn't provide a way to retry auto-detection if it fails initially. Adding a retry button would improve user experience.

  return (
    <div className="form-control w-full">
      <label className="label">
        <span className="label-text font-semibold text-xs">{label}</span>
        {status === "loading" && <span className="loading loading-spinner loading-xs ml-2" />}
        {status === "success" && <span className="text-success text-xs ml-2">Detected</span>}
-        {status === "fail" && <span className="text-error text-xs ml-2">Failed</span>}
+        {status === "fail" && (
+          <div className="flex items-center">
+            <span className="text-error text-xs ml-2">Failed</span>
+            <button 
+              type="button" 
+              className="btn btn-xs btn-ghost ml-2" 
+              onClick={() => baseUrl && tryDetect()}
+            >
+              Retry
+            </button>
+          </div>
+        )}
      </label>
      
      {/* Rest of the component remains the same */}

You'll need to extract the tryDetect function outside of the useEffect to make this work:

+  const tryDetect = async () => {
+    if (!baseUrl) return;
+    
+    setStatus("loading");
+    // ... rest of the function
+  };

  useEffect(() => {
-    if (!baseUrl) return;
-
-    const tryDetect = async () => {
-      // ... function body
-    };
-
    tryDetect();
  }, [baseUrl, guessPaths, detectTest, setValue, name]);
src/components/inputs/MultiCheckboxSelector.tsx (2)

1-15: The component interface is well-defined but consider enhancing with additional props

The component has a clean interface defining Option and MultiCheckboxSelectorProps types. Consider extending the component's flexibility by adding:

  • A disabled prop to disable the entire selector
  • An error prop to display validation errors from react-hook-form
  • A required prop to visually indicate required fields
interface MultiCheckboxSelectorProps {
  name: string;
  options: Option[];
  label?: string;
  helperText?: string;
+ disabled?: boolean;
+ error?: string;
+ required?: boolean;
}

17-26: Enhancement opportunity: Add type safety for the selected values array

The component assumes selected is always an array but doesn't handle cases when it might be undefined or not an array. Adding a default empty array with explicit typing would improve robustness.

export function MultiCheckboxSelector({ name, options, label, helperText }: MultiCheckboxSelectorProps) {
  const { watch, setValue } = useFormContext();
- const selected = watch(name) || [];
+ const selected: (string | number)[] = watch(name) || [];

  const toggle = (value: string | number) => {
    const newValue = selected.includes(value)
      ? selected.filter((v: string | number) => v !== value)
      : [...selected, value];
    setValue(name, newValue, { shouldValidate: true });
  };
src/components/layouts/Navbar.tsx (3)

9-10: Remove commented-out imports

These commented-out imports should either be removed entirely or uncommented if they're needed.

-// import ThemeToggle from "../ui/toggle/ThemeToggle";
-// import { ProfileDropdown } from "../ui/dropdown/ProfileDropdown";

18-25: Add error handling to logout function

The handleLogout function doesn't handle potential errors when clearing localStorage or during navigation. Consider adding try/catch and ensuring all state is properly cleaned up.

const handleLogout = () => {
+  try {
    StorageService.removeLocalStorage('community');
    StorageService.removeLocalStorage('TC_SELECTED_PLATFORM');
    StorageService.removeLocalStorage('user');
    router.push('/centric');
+  } catch (error) {
+    console.error('Error during logout:', error);
+    // Consider showing an error message to the user
+  }
}

33-35: Add fallback for missing community name

The component doesn't handle the case where community?.name might be undefined. Add a fallback text to avoid rendering an empty div.

-<div className="ml-4 text-lg font-bold">{community?.name}</div>
+<div className="ml-4 text-lg font-bold">{community?.name || 'No Community Selected'}</div>
src/pages/centric/create-new-community.tsx (1)

77-92: Consider extracting hardcoded URLs as constants

The privacy policy and terms of service URLs are hardcoded in multiple places. Consider extracting them as constants to ensure consistency and easier maintenance.

// At the top of the file or in a separate constants file
+const PRIVACY_POLICY_URL = 'https://www.togethercrew.com/privacy-and-terms';
+const TERMS_OF_SERVICE_URL = 'https://www.togethercrew.com/privacy-and-terms';

// Then in the JSX
<TcLink
-  to='https://www.togethercrew.com/privacy-and-terms'
+  to={PRIVACY_POLICY_URL}
  color='primary'
  fontWeight='bold'
>
  Privacy Policy
</TcLink>
{' and '}
<TcLink
-  to='https://www.togethercrew.com/privacy-and-terms'
+  to={TERMS_OF_SERVICE_URL}
  color='primary'
  fontWeight='bold'
>
  Terms of Service.
</TcLink>
src/axiosInstance.ts (2)

131-133: Remove console.log statement

There's a debugging console.log statement that should be removed before deploying to production.

if (window.location.pathname !== '/centric/') {
- console.log(window.location.pathname);
  toast.error('Token expired...', {

127-143: Consider using Next.js Router for redirects

The code uses direct window.location manipulation which bypasses Next.js routing. Consider using the Next.js Router for a more consistent navigation experience.

+ import { useRouter } from 'next/router';

// In the response interceptor setup
+ const router = typeof window !== 'undefined' ? require('next/router').default : null;

// Later in the code
StorageService.removeLocalStorage('community');
StorageService.removeLocalStorage('TC_SELECTED_PLATFORM');
StorageService.removeLocalStorage('analysis_state');
StorageService.removeLocalStorage('user');
if (window.location.pathname !== '/centric/') {
  toast.error('Token expired...', {
    position: 'bottom-left',
    autoClose: 5000,
    hideProgressBar: false,
    closeOnClick: true,
    pauseOnHover: true,
    draggable: true,
    progress: 0,
  });
- window.location.href = '/centric';
+ router?.push('/centric');
}
src/hooks/sidebar/useSidebar.ts (1)

51-51: Remove unnecessary blank line.

There's an extra blank line here that could be removed for cleaner code.

  }, [isAdmin]);
-
  return {
    sidebarItems,
  };
src/constants/ModuleContext.ts (1)

23-23: Consider expanding the Community Health description.

The description for the Community Health module is significantly shorter than other modules. Consider expanding it to provide more context about its purpose and benefits, similar to other module descriptions.

src/components/inputs/ToggleInput.tsx (2)

18-18: Consider destructuring more form context properties.

You're currently only using register and errors from useFormContext(). If you plan to add features like controlled inputs or watch values, consider destructuring more properties.


46-46: Remove trailing whitespace.

There's a trailing whitespace at the end of line 46 that should be removed.

-} 
+}
src/components/inputs/WebsiteInput.tsx (2)

24-47: URL normalization logic could be optimized

The URL normalization logic in this useEffect is well-implemented, but has a minor inefficiency. The function continues execution after the if (!rawValue) return; check, which could be restructured for better readability and performance.

Consider refactoring to make the logic flow more explicit:

  useEffect(() => {
    if (!rawValue) return;

    let normalized = rawValue.trim();

    if (!/^https?:\/\//i.test(normalized)) {
      normalized = `https://${normalized}`;
    }

    try {
      const url = new URL(normalized);

      if (!allowPath) {
        url.pathname = "/";
        url.search = "";
        url.hash = "";
      }

      const clean = url.toString().replace(/\/$/, ""); // remove trailing slash
-     setValue(name, clean, { shouldValidate: true });
+     if (clean !== rawValue) {
+       setValue(name, clean, { shouldValidate: true });
+     }
    } catch {
      // leave it alone if not valid
    }
  }, [rawValue, name, setValue, allowPath]);

49-59: Consider DRYing up validation and normalization logic

There's duplication between the URL validation in validate() and the normalization logic in the useEffect. Both contain similar code for URL parsing and checking paths.

Extract the common URL validation logic into a shared utility function:

+ const isValidUrl = (value: string, checkPath = true): { isValid: boolean; message?: string; url?: URL } => {
+   try {
+     const url = new URL(/^https?:\/\//i.test(value) ? value : `https://${value}`);
+     if (checkPath && !allowPath && (url.pathname !== "/" || url.search || url.hash)) {
+       return { isValid: false, message: "Please enter a root domain only (no path, query, or hash)", url };
+     }
+     return { isValid: true, url };
+   } catch {
+     return { isValid: false, message: "Invalid URL format" };
+   }
+ };

  const validate = (value: string): ValidateResult | Promise<ValidateResult> => {
-   try {
-     const url = new URL(/^https?:\/\//i.test(value) ? value : `https://${value}`);
-     if (!allowPath && (url.pathname !== "/" || url.search || url.hash)) {
-       return "Please enter a root domain only (no path, query, or hash)";
-     }
-     return true;
-   } catch {
-     return "Invalid URL format";
-   }
+   const result = isValidUrl(value, true);
+   return result.isValid ? true : result.message;
  }

This would make the code more maintainable and consistent.

src/utils/JwtPayloadType.ts (1)

1-19: Add JSDoc comments to improve documentation

The JWT type definitions are well-structured, but lack documentation that explains the purpose and usage of each field.

Consider adding JSDoc comments to improve code documentation:

+/**
+ * Represents a user identity from an authentication provider
+ */
export type JwtIdentityType = {
  _id: string;
  provider: string;
  id: string;
}

+/**
+ * Represents the decoded JWT payload structure
+ * Contains user subject information, token metadata, and standard JWT claims
+ */
export type JwtPayloadType = {
  sub: {
    communities: string[];
    createdAt: string;
    updatedAt: string;
    tcaAt: string;
    identities: JwtIdentityType[];
    id: string;
  },
  iat: number;  // Issued at timestamp
  exp: number;  // Expiration timestamp
  type: string;
}
src/components/communitySettings/communityPlatforms/TcTelegram/TcTelegramIntegrationDialog.tsx (1)

64-94: Consider adding error feedback for community data fetching

The implementation polls for community data every 5 seconds, which is good for real-time updates. However, while errors are logged to console, there's no user-facing feedback when an error occurs.

Consider adding user feedback for fetch errors using the existing snackbar:

  try {
    const community = await retrieveCommunityById(storedCommunity.id);
    const hasTelegramPlatform = community.platforms.some(
      (platform: { name: string }) => platform.name === "telegram",
    );

    setHasActiveTelegram(hasTelegramPlatform);
  } catch (error) {
    console.error("Error fetching community data:", error);
+   // Only show error message if dialog still open after multiple failures
+   if (isOpen && interval) {
+     const attemptCount = interval.toString().split('_')[1] || '0';
+     if (parseInt(attemptCount) > 3) {
+       showMessage("Error verifying Telegram connection status. Please try again.", "error");
+       clearInterval(interval);
+     }
+   }
  }
src/context/AuthProvider.tsx (2)

69-69: Remove console.log statement

There's a debug console.log statement that should be removed before deploying to production.

const refreshAccessToken = async () => {
-  console.log("refreshAccessToken")
  if (!auth.refreshToken) {
    logout();
    return;
  }

75-83: Use auth state from closure in the token refresh

The refreshAccessToken function uses the refreshToken from closure rather than directly from the current auth state. While this works for the initial implementation, it could lead to issues if the refreshToken changes during this function's execution.

try {
-  const response = await axios.post(`${conf.API_BASE_URL}/auth/refresh-tokens`, { refreshToken })
+  const response = await axios.post(`${conf.API_BASE_URL}/auth/refresh-tokens`, { 
+    refreshToken: auth.refreshToken 
+  })
  const { access, refresh } = response.data
  setAuth({ accessToken: access.token, refreshToken: refresh.token });
} catch (error) {
  console.error("Error refreshing token:", error);
  logout();
}
src/components/mediawiki/Form.tsx (1)

43-45: Avoid any – give namespaces a proper type

-  const [namespaces, setNamespaces] = useState<any[]>([]);
+  const [namespaces, setNamespaces] = useState<Array<{label:string; value:number}>>([]);

Typed state improves auto-completion and prevents accidental shape changes.

src/components/home/modules/ModuleItem.tsx (1)

40-50: Toast message picks the wrong text when both mutations are idle
The effect fires only when a flag flips to true, but the message string is evaluated every render, leading to an empty toast if race conditions occur. Cache the message inside the effect:

  useEffect(() => {
-    if (updateModule.isSuccess || createModule.isSuccess) {
-      toast.success(`${updateModule.isSuccess ? "Module updated" : createModule.isSuccess ? "Module created" : ""}`, { ... });
+    if (updateModule.isSuccess) {
+      toast.success("Module updated", { ... });
+    } else if (createModule.isSuccess) {
+      toast.success("Module created", { ... });
     }
   }, [updateModule.isSuccess, createModule.isSuccess]);
src/components/mediawiki/List.tsx (2)

199-206: Skeleton row has only 3 cells but the table has 4 columns
The mismatch causes the loading layout to jump horizontally when data arrive.

-                <LoadingCell />
-                <LoadingCell />
-                <LoadingCell />
+                {Array.from({ length: 4 }).map((_, i) => (
+                  <LoadingCell key={i} />
+                ))}

147-160: Pagination “next” button is enabled when totalPages is 0
Initial render allows page to increment into oblivion. Add an extra guard:

-  disabled={page === totalPages}
+  disabled={totalPages === 0 || page === totalPages}
src/components/layouts/Sidebar.tsx (1)

2-2: Remove unused useEffect import
The hook is imported but never used, producing a linter warning.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between ea91472 and 587b08f.

⛔ Files ignored due to path filters (2)
  • package-lock.json is excluded by !**/package-lock.json
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (81)
  • next.config.js (1 hunks)
  • package.json (6 hunks)
  • src/app/dashboard/agent/page.tsx (2 hunks)
  • src/app/dashboard/community-guardian/page.tsx (1 hunks)
  • src/app/dashboard/layout.tsx (1 hunks)
  • src/app/dashboard/page.tsx (1 hunks)
  • src/app/dashboard/settings/mediawiki/[id]/edit/page.tsx (1 hunks)
  • src/app/dashboard/settings/mediawiki/[id]/page.tsx (1 hunks)
  • src/app/dashboard/settings/mediawiki/new/page.tsx (1 hunks)
  • src/app/dashboard/settings/mediawiki/page.tsx (1 hunks)
  • src/app/dashboard/settings/page.tsx (1 hunks)
  • src/app/layout.tsx (1 hunks)
  • src/atoms/authState.atom.ts (1 hunks)
  • src/atoms/ui.atom.ts (1 hunks)
  • src/axiosInstance.ts (3 hunks)
  • src/components/LoadingScreen.tsx (1 hunks)
  • src/components/auth/ProtectedRoute.tsx (1 hunks)
  • src/components/centric/selectCommunity/TcCommunityItem.tsx (1 hunks)
  • src/components/centric/selectCommunity/TcCommunityListItems.tsx (1 hunks)
  • src/components/centric/selectCommunity/TcSelectCommunity.tsx (3 hunks)
  • src/components/chat/Chat.tsx (1 hunks)
  • src/components/chat/ChatForm.tsx (1 hunks)
  • src/components/communitySettings/HivemindSettings/TcHivemindMediaWiki.tsx (0 hunks)
  • src/components/communitySettings/HivemindSettings/TcHivemindSettings.tsx (3 hunks)
  • src/components/communitySettings/communityPlatforms/TcCommunityPlatforms.tsx (1 hunks)
  • src/components/communitySettings/communityPlatforms/TcDiscordIntgration.tsx (1 hunks)
  • src/components/communitySettings/communityPlatforms/TcDiscourse.tsx (1 hunks)
  • src/components/communitySettings/communityPlatforms/TcGithubIntegration.tsx (1 hunks)
  • src/components/communitySettings/communityPlatforms/TcMediaWiki.tsx (1 hunks)
  • src/components/communitySettings/communityPlatforms/TcNotionIntegration.tsx (1 hunks)
  • src/components/communitySettings/communityPlatforms/TcTelegram/TcTelegramIntegrationDialog.tsx (1 hunks)
  • src/components/communitySettings/communityPlatforms/TcWebsite.tsx (1 hunks)
  • src/components/home/modules/ModuleItem.tsx (1 hunks)
  • src/components/home/modules/ModuleList.tsx (1 hunks)
  • src/components/home/platforms/PlatformItem.tsx (1 hunks)
  • src/components/home/platforms/PlatformList.tsx (1 hunks)
  • src/components/home/platforms/UpvoteButton.tsx (1 hunks)
  • src/components/inputs/AutoDetectPathInput.tsx (1 hunks)
  • src/components/inputs/MultiCheckboxSelector.tsx (1 hunks)
  • src/components/inputs/ToggleInput.tsx (1 hunks)
  • src/components/inputs/WebsiteInput.tsx (1 hunks)
  • src/components/layouts/Breadcrumbs.tsx (1 hunks)
  • src/components/layouts/DashboardLayout.tsx (1 hunks)
  • src/components/layouts/Navbar.tsx (1 hunks)
  • src/components/layouts/Sidebar.tsx (1 hunks)
  • src/components/layouts/xs/SidebarXs.tsx (1 hunks)
  • src/components/mediawiki/Form.tsx (1 hunks)
  • src/components/mediawiki/List.tsx (1 hunks)
  • src/components/settings/modules/mediawiki/Form.tsx (1 hunks)
  • src/constants/ModuleContext.ts (1 hunks)
  • src/constants/PlatformContext.ts (1 hunks)
  • src/context/AuthProvider.tsx (1 hunks)
  • src/hooks/mediawiki/useNamespaces.ts (1 hunks)
  • src/hooks/modules/useModuleActions.ts (1 hunks)
  • src/hooks/modules/useModules.ts (1 hunks)
  • src/hooks/platforms/usePlatformActions.ts (1 hunks)
  • src/hooks/platforms/usePlatforms.ts (1 hunks)
  • src/hooks/sidebar/useSidebar.ts (1 hunks)
  • src/hooks/useAdmin.ts (1 hunks)
  • src/hooks/useApi.ts (1 hunks)
  • src/hooks/useDatasources.ts (1 hunks)
  • src/layouts/centricLayout.tsx (1 hunks)
  • src/layouts/defaultLayout.tsx (1 hunks)
  • src/pages/_app.tsx (1 hunks)
  • src/pages/announcements/index.tsx (3 hunks)
  • src/pages/callback.tsx (4 hunks)
  • src/pages/centric/create-new-community.tsx (2 hunks)
  • src/pages/centric/index.tsx (2 hunks)
  • src/pages/centric/select-community.tsx (1 hunks)
  • src/pages/centric/tac.tsx (2 hunks)
  • src/pages/centric/welcome.tsx (0 hunks)
  • src/pages/community-settings/ai-assistant/index.tsx (1 hunks)
  • src/pages/community-settings/index.tsx (1 hunks)
  • src/pages/community-settings/violation-detection/index.tsx (1 hunks)
  • src/pages/index.tsx (1 hunks)
  • src/pages/statistics.tsx (6 hunks)
  • src/styles/globals.css (2 hunks)
  • src/utils/JwtPayloadType.ts (1 hunks)
  • src/utils/interfaces.ts (1 hunks)
  • tailwind.config.js (1 hunks)
  • tsconfig.json (2 hunks)
💤 Files with no reviewable changes (2)
  • src/components/communitySettings/HivemindSettings/TcHivemindMediaWiki.tsx
  • src/pages/centric/welcome.tsx
🧰 Additional context used
🧬 Code Graph Analysis (30)
src/app/dashboard/layout.tsx (4)
src/components/auth/ProtectedRoute.tsx (1)
  • ProtectedRoute (8-23)
src/context/TokenContext.tsx (1)
  • TokenProvider (33-167)
src/components/layouts/DashboardLayout.tsx (1)
  • DashboardLayout (10-28)
src/components/layouts/Breadcrumbs.tsx (1)
  • Breadcrumbs (10-45)
src/components/auth/ProtectedRoute.tsx (2)
src/context/AuthProvider.tsx (1)
  • useAuth (103-109)
src/components/LoadingScreen.tsx (1)
  • LoadingScreen (5-14)
src/pages/centric/tac.tsx (1)
src/components/LoadingScreen.tsx (1)
  • LoadingScreen (5-14)
src/app/dashboard/page.tsx (2)
src/components/home/platforms/PlatformList.tsx (1)
  • PlatformList (10-34)
src/components/home/modules/ModuleList.tsx (1)
  • ModuleList (9-32)
src/app/dashboard/community-guardian/page.tsx (1)
src/constants/ModuleContext.ts (1)
  • MODULE_CONTEXT (7-69)
src/app/dashboard/settings/mediawiki/[id]/page.tsx (1)
src/axiosInstance.ts (1)
  • axiosInstance (11-13)
src/layouts/defaultLayout.tsx (1)
src/components/layouts/DashboardLayout.tsx (1)
  • DashboardLayout (10-28)
src/hooks/modules/useModuleActions.ts (1)
src/axiosInstance.ts (1)
  • axiosInstance (11-13)
src/pages/centric/select-community.tsx (1)
src/components/LoadingScreen.tsx (1)
  • LoadingScreen (5-14)
src/components/home/platforms/PlatformList.tsx (5)
src/context/TokenContext.tsx (1)
  • useToken (169-175)
src/hooks/platforms/usePlatforms.ts (1)
  • usePlatforms (4-19)
src/utils/interfaces.ts (1)
  • IPlatformProps (142-152)
src/constants/PlatformContext.ts (1)
  • PLATFORM_CONTEXT (3-48)
src/components/home/platforms/PlatformItem.tsx (1)
  • PlatformItem (12-47)
src/constants/PlatformContext.ts (1)
src/utils/interfaces.ts (1)
  • IPlatformContext (255-260)
src/hooks/modules/useModules.ts (1)
src/axiosInstance.ts (1)
  • axiosInstance (11-13)
src/hooks/useDatasources.ts (1)
src/context/TokenContext.tsx (1)
  • useToken (169-175)
src/app/dashboard/settings/mediawiki/[id]/edit/page.tsx (3)
src/axiosInstance.ts (1)
  • axiosInstance (11-13)
src/components/mediawiki/Form.tsx (1)
  • MediaWikiForm (25-136)
src/utils/interfaces.ts (1)
  • IPlatformProps (142-152)
src/app/dashboard/settings/mediawiki/new/page.tsx (2)
src/components/layouts/Breadcrumbs.tsx (1)
  • Breadcrumbs (10-45)
src/components/mediawiki/Form.tsx (1)
  • MediaWikiForm (25-136)
src/components/layouts/DashboardLayout.tsx (2)
src/atoms/ui.atom.ts (1)
  • uiAtom (5-8)
src/components/layouts/Navbar.tsx (1)
  • Navbar (16-51)
src/components/settings/modules/mediawiki/Form.tsx (2)
src/utils/interfaces.ts (1)
  • IMediaWikiModuleFormPayload (275-277)
src/components/inputs/ToggleInput.tsx (1)
  • ToggleInput (11-46)
src/axiosInstance.ts (1)
src/services/StorageService.ts (1)
  • StorageService (4-61)
src/components/layouts/Navbar.tsx (2)
src/context/TokenContext.tsx (1)
  • useToken (169-175)
src/services/StorageService.ts (1)
  • StorageService (4-61)
src/hooks/platforms/usePlatforms.ts (1)
src/axiosInstance.ts (1)
  • axiosInstance (11-13)
src/constants/ModuleContext.ts (1)
src/utils/interfaces.ts (1)
  • IModuleContext (244-253)
src/pages/centric/create-new-community.tsx (1)
src/components/LoadingScreen.tsx (1)
  • LoadingScreen (5-14)
src/components/home/modules/ModuleItem.tsx (6)
src/utils/interfaces.ts (2)
  • IModuleContext (244-253)
  • IModuleProps (234-242)
src/context/TokenContext.tsx (1)
  • useToken (169-175)
src/hooks/useAdmin.ts (1)
  • useAdmin (5-13)
src/hooks/modules/useModuleActions.ts (1)
  • useModuleActions (5-22)
src/hooks/modules/useModules.ts (1)
  • useModules (4-14)
src/components/home/platforms/UpvoteButton.tsx (1)
  • UpvoteButton (7-44)
src/hooks/sidebar/useSidebar.ts (3)
src/utils/interfaces.ts (1)
  • ISidebarItem (262-267)
src/hooks/useAdmin.ts (1)
  • useAdmin (5-13)
src/constants/ModuleContext.ts (1)
  • MODULE_CONTEXT (7-69)
src/components/communitySettings/HivemindSettings/TcHivemindSettings.tsx (2)
src/components/settings/modules/mediawiki/Form.tsx (1)
  • MediaWikiModuleForm (15-43)
src/utils/interfaces.ts (1)
  • IMediaWikiModuleFormPayload (275-277)
src/pages/callback.tsx (1)
src/components/LoadingScreen.tsx (1)
  • LoadingScreen (5-14)
src/components/home/platforms/UpvoteButton.tsx (2)
src/context/SnackbarContext.tsx (1)
  • useSnackbar (59-65)
src/helpers/amplitudeHelper.tsx (2)
  • setAmplitudeUserIdFromToken (13-24)
  • trackAmplitudeEvent (26-49)
src/context/AuthProvider.tsx (4)
src/utils/JwtPayloadType.ts (1)
  • JwtPayloadType (7-19)
src/atoms/authState.atom.ts (1)
  • authState (14-14)
src/configs/index.ts (1)
  • conf (1-17)
src/components/LoadingScreen.tsx (1)
  • LoadingScreen (5-14)
src/components/layouts/Sidebar.tsx (2)
src/utils/interfaces.ts (1)
  • ISidebarItem (262-267)
src/hooks/sidebar/useSidebar.ts (1)
  • useSidebar (27-55)
src/components/mediawiki/List.tsx (4)
src/utils/interfaces.ts (1)
  • IPlatformProps (142-152)
src/hooks/mediawiki/useNamespaces.ts (1)
  • useNamespaces (5-21)
src/context/TokenContext.tsx (1)
  • useToken (169-175)
src/hooks/platforms/usePlatforms.ts (1)
  • usePlatforms (4-19)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (87)
src/pages/_app.tsx (1)

42-42: Formatting Adjustment Approved

The added blank line improves readability and aligns with existing code style. No functional impact.

src/pages/index.tsx (1)

20-20: No-op: whitespace only change
This insertion of a blank line does not affect functionality or readability.

src/pages/statistics.tsx (2)

310-310: No-op: trailing space removal
Whitespace cleanup in scrollToHash is purely stylistic and safe.


383-384: UI Enhancement: standardized container background
Adding bg-base-100 (with existing rounded-* and shadow-lg) to each <Box> aligns the page styling with the updated design system.

Also applies to: 398-399, 413-414, 429-430, 444-445

next.config.js (1)

4-4: Disable static export mode
Commenting out output: 'export' is required to support dynamic React client components, server-side data fetching, and authentication context.

src/pages/community-settings/ai-assistant/index.tsx (1)

30-32: Apply consistent styling to AI Assistant settings
Adding bg-base-100 and rounded-lg to TcBoxContainer matches the styling conventions used across other community settings pages.

src/pages/community-settings/violation-detection/index.tsx (1)

164-166: Consistent styling applied to violation detection container
The addition of className="bg-base-100 rounded-lg" on the TcBoxContainer aligns the UI with other community settings pages and maintains a coherent look and feel.

src/pages/community-settings/index.tsx (1)

67-69: Apply consistent background and border-radius to settings container
Adding bg-base-100 rounded-lg to TcBoxContainer ensures the community settings page matches the updated design system. No logic changes here.

src/components/chat/ChatForm.tsx (1)

15-17: Update ChatForm styling to match design tokens
Replacing the top border with rounded-lg mb-4 bg-base-100 w-full max-w-3xl brings the input form in line with the rest of the dashboard’s containers. Verify that the new max-w-3xl constraint doesn’t introduce unwanted horizontal scrolling in narrower layouts.

src/pages/announcements/index.tsx (3)

193-196: Add background styling to announcements section
Introducing bg-base-100 on the inner wrapper div provides the same light background used elsewhere. This change is purely cosmetic and keeps the announcements UI consistent with other modules.


242-244: This indentation adjustment for the conditional rendering of announcements is purely formatting-related and does not affect behavior.


277-280: Verify pagination itemsPerPage calculation
The itemsPerPage prop is derived via Math.ceil(totalResults / totalPages). Please confirm this always matches the intended page size (e.g., limit) and handles edge cases (like totalPages === 0).

src/components/centric/selectCommunity/TcCommunityItem.tsx (1)

1-10: Import organization looks good!

The imports have been neatly reorganized and grouped by category (React, MUI, custom components, configurations, interfaces). This improves code readability and maintainability.

src/components/communitySettings/communityPlatforms/TcCommunityPlatforms.tsx (1)

109-114: Good defensive coding with optional chaining

Adding the optional chaining operator (?.) when accessing searchParams.get() is a good practice to safely handle cases where searchParams might be undefined. Also, updating the dependency array to depend on the full searchParams object ensures the effect reruns correctly when any search parameter changes.

src/components/LoadingScreen.tsx (1)

1-14: Well-implemented loading component

This new LoadingScreen component follows best practices:

  • Uses Next.js Image component for optimized image loading
  • Implements proper alt text for accessibility
  • Uses flexbox for responsive centering
  • Keeps the component simple and focused on a single responsibility

The component will provide consistent loading UX across the application.

src/pages/centric/tac.tsx (3)

3-8: Good import organization

The imports are well-organized with proper spacing between different import categories.


47-47: Improved loading experience

Replacing the previous loading indicator with the new LoadingScreen component provides a more consistent and branded loading experience across the application.


51-52: Enhanced layout with logo

Adding flexbox styling and the centered logo improves the visual hierarchy and branding of the page. The mx-auto class ensures the logo is properly centered horizontally.

tailwind.config.js (1)

144-147: Adding DaisyUI and Typography plugins enhances UI capabilities

The addition of these two plugins expands the styling capabilities of the application with typography styles and DaisyUI components. The DaisyUI configuration restricts the theme to "light" only.

Just to note, restricting DaisyUI to the "light" theme only means dark mode won't be supported through DaisyUI. Is this restriction intentional, or would you like to support both light and dark themes in the future?

src/app/dashboard/settings/mediawiki/[id]/page.tsx (1)

12-15: Data is fetched but not displayed in the UI

You're correctly fetching the platform data using React Query, but the fetched data isn't being utilized in the component's rendered output.

Consider displaying the fetched MediaWiki platform details in the empty div at line 23:

<div className="bg-base-100 p-8 rounded-lg">
+  {data?.data && (
+    <div className="flex flex-col gap-2">
+      <h2 className="text-xl font-semibold">{data.data.name}</h2>
+      <p>URL: {data.data.metadata?.url}</p>
+      <p>Connected: {new Date(data.data.connectedAt).toLocaleDateString()}</p>
+    </div>
+  )}
</div>
src/hooks/useAdmin.ts (1)

1-13: Well-structured hook for admin privilege check

The hook is concise and follows React best practices. It effectively abstracts the admin permission check logic which can be reused across the application.

src/components/communitySettings/communityPlatforms/TcGithubIntegration.tsx (1)

37-42: Improved useEffect dependency handling

Good change to properly handle the searchParams dependency in the useEffect hook. Moving the parameter extraction inside the hook and updating the dependency array ensures that the effect runs correctly when URL parameters change.

tsconfig.json (1)

4-8: Great improvements to the TypeScript configuration!

The changes enhance readability with multi-line arrays and add important Next.js-specific configurations:

  1. Adding the Next.js plugin enables proper type checking for Next.js features
  2. Including .next/types/**/*.ts ensures TypeScript recognizes Next.js generated types
  3. Adding Jest setup file to the include array supports proper testing configuration

These changes provide better type safety and developer experience when working with Next.js features, which aligns well with the dashboard enhancements in this PR.

Also applies to: 23-31, 38-43

src/components/centric/selectCommunity/TcCommunityListItems.tsx (1)

2-5: Import organization looks good.

The reorganized imports improve readability by grouping related imports together and adding appropriate spacing. This makes the file's dependencies clearer while keeping the component's functionality unchanged.

src/hooks/useApi.ts (1)

5-5: Good defensive programming addition.

Making the url parameter nullable and adding a guard clause to prevent API calls when the URL is not available is an excellent improvement. This change:

  1. Makes the hook more flexible for components where the URL might not be available initially
  2. Prevents unnecessary loading state changes and API calls with invalid URLs
  3. Follows defensive programming best practices to avoid runtime errors

This aligns well with the PR's focus on enhancing data fetching and state management.

Also applies to: 13-13

src/atoms/ui.atom.ts (1)

1-8: Good addition of persistent UI state management.

Using Jotai with atomWithStorage for managing sidebar visibility and theme preferences is an excellent approach:

  1. Provides a centralized, type-safe way to manage UI state
  2. Persists user preferences across sessions
  3. Creates a solid foundation for the sidebar refactoring mentioned in the PR summary

This clean implementation will make it easier to maintain UI consistency across the application and improve user experience.

src/pages/centric/index.tsx (2)

3-3: Improved UI with logo and better layout structure.

The addition of the logo component and flexbox styling enhances the visual presentation of the login page while maintaining a consistent UI pattern with other centric pages.

Also applies to: 7-7, 18-19


24-24: Well-structured content layout using flex column.

The change to use flex column with consistent spacing improves the organization and readability of the content elements.

src/components/communitySettings/communityPlatforms/TcDiscordIntgration.tsx (1)

41-46: Improved effect dependency management.

Moving the extraction of addPlatform inside the useEffect and updating the dependency array to [searchParams] is a good practice. This ensures the effect reruns properly when search parameters change.

src/hooks/platforms/usePlatformActions.ts (1)

1-44: Good implementation of platform mutation hooks.

The implementation of the platform action hooks follows best practices for React Query mutations, with proper error handling and cache invalidation.

src/components/communitySettings/communityPlatforms/TcNotionIntegration.tsx (1)

42-47: Improved effect dependency management.

Moving the extraction of addPlatform inside the useEffect and updating the dependency array to [searchParams, userId] is a good practice. This ensures the effect reruns properly when search parameters change.

src/layouts/defaultLayout.tsx (1)

3-4: Well-structured refactoring using DashboardLayout!

Nice job refactoring the layout to leverage the new DashboardLayout component. This change effectively centralizes the sidebar and layout management, improving code organization and separation of concerns.

Also applies to: 13-18

src/app/dashboard/settings/mediawiki/page.tsx (1)

8-20: Clean implementation of MediaWiki settings page

The component is well-structured with clear separation of header and content areas. Good use of flexbox layout and appropriate styling elements, consistent with the application's design patterns.

src/hooks/useDatasources.ts (1)

3-37: Well-structured hook for managing datasource availability and activation status

The hook is cleanly implemented with good separation of concerns. It efficiently derives the activation status from the community context and follows React hook patterns appropriately.

src/components/chat/Chat.tsx (1)

131-131: Good contrast improvement for user messages

The darker background for user messages improves visual distinction and readability.

src/app/dashboard/settings/mediawiki/new/page.tsx (1)

1-18: Well-structured new page component.

The component follows good organization patterns with clear separation of concerns - breadcrumb navigation, page header, and the form container. The use of flex layout and spacing utilities creates a consistent UI aligned with other dashboard pages.

src/components/communitySettings/communityPlatforms/TcDiscourse.tsx (1)

57-62: Improved useEffect dependency handling.

Moving the addPlatform extraction inside the effect and changing the dependency array from [addPlatform] to [searchParams] is a good refactoring that follows React best practices. This ensures the effect correctly reacts to all changes in search parameters, not just stale extracted values.

package.json (4)

19-19: Appropriate move of 3d-force-graph-vr to dependencies.

Moving this package from devDependencies to dependencies is correct since it's needed at runtime.


51-51: Good addition of state management and form libraries.

The addition of jotai and react-hook-form supports the new features for MediaWiki management and form handling throughout the application.

Also applies to: 65-65


80-80: Appropriate UI enhancement libraries added.

The addition of @tailwindcss/typography and daisyui aligns with the UI improvements seen throughout the application's new components.

Also applies to: 92-92


74-74:

Details

✅ Verification successful

TypeScript version downgrade may need verification.

The TypeScript version was downgraded from ^5.6.3 to ^5.6.0, which is unusual. Verify that this doesn't cause compatibility issues with other dependencies.


🏁 Script executed:

#!/bin/bash
# Check compatibility between TypeScript and other dependencies
npm info typescript@^5.6.0 peerDependencies
npm info typescript@^5.6.0 compatibleWith

# List any TypeScript-related dependency conflicts
npm ls typescript

Length of output: 65766


No TypeScript downgrade detected
The change from ^5.6.3 to ^5.6.0 does not lock you back to 5.6.0—caret ranges still pull in the latest 5.x (your install is 5.8.3). TypeScript itself has no peerDependencies, and common consumers (e.g. @typescript-eslint/parser @7.18.0 with peer "typescript": "^3.9.5 || >=4.0.0") are happy with 5.8.3. No compatibility issues found; no action required.

src/atoms/authState.atom.ts (1)

1-14: Well-structured implementation of auth state management

The implementation using atomWithStorage correctly provides persistent storage for authentication tokens with proper typing.

src/components/home/modules/ModuleList.tsx (1)

9-32: Well-structured component with good separation of concerns

The component is well organized with clear data fetching, loading state handling, and rendering logic.

src/components/communitySettings/communityPlatforms/TcWebsite.tsx (1)

48-53: Improved useEffect implementation for query parameter handling

Moving the extraction of the addPlatform query parameter inside the useEffect and updating the dependency array to [searchParams] is a good practice that ensures the effect properly reacts to URL changes.

src/hooks/modules/useModules.ts (1)

1-14: Well-implemented React Query hook with conditional fetching

The hook correctly utilizes React Query's capabilities and enables the query only when a community ID is provided, which is an efficient approach.

src/styles/globals.css (4)

5-8: Good use of standardized font sizing for tooltips.

The tooltip font size is standardized to 0.75rem, ensuring consistency with text-xs in Tailwind. This is good for maintaining uniform typography across the application.


90-113: Well-structured breadcrumb styling with proper accessibility consideration.

The breadcrumbs styling effectively uses Tailwind's @apply directive and includes proper focus states for accessibility. The arrow styling using border and rotation is elegant and maintainable.


115-118: Good RTL language support for breadcrumbs.

The CSS correctly handles right-to-left language support for breadcrumbs by adjusting the rotation angle, which is essential for internationalization.


120-147: Comprehensive breadcrumb layout styling with responsive hover effects.

The CSS provides a complete set of layout styles for breadcrumbs, including flexbox alignment, overflow handling, and responsive hover effects. The white-space handling ensures breadcrumbs display correctly with long text.

src/app/dashboard/page.tsx (1)

1-8: Clean import organization following best practices.

The imports are well-organized with React/third-party imports followed by local component imports, making the code more readable and maintainable.

src/components/home/platforms/UpvoteButton.tsx (1)

37-43: Good use of loading state and accessible tooltips.

The button implementation correctly handles loading states with a spinner and includes an accessible tooltip. The disabled state during loading prevents multiple submissions.

src/app/dashboard/community-guardian/page.tsx (2)

45-49: External links correctly use security attributes.

The external links to Twitter and Telegram correctly use target="_blank" with rel="noreferrer" to prevent security vulnerabilities when opening links in new tabs.

Also applies to: 51-55


39-43:

Details

❓ Verification inconclusive

Ensure Discord invitation link is permanent.

The Discord invitation link (https://discord.gg/QNJGeZeT) appears to be a temporary invite link that could expire. Consider using a permanent invitation link to avoid broken links in the future.


🏁 Script executed:

#!/bin/bash
# Check if there are other Discord links in the codebase that might be permanent
rg "discord.gg" --type tsx --type jsx

Length of output: 65


I’ll broaden the search to match .tsx and .jsx files by glob patterns.


🏁 Script executed:

#!/bin/bash
# Search for all Discord invite links in TSX and JSX files
rg "discord\.gg" -g "*.tsx" -g "*.jsx"

Length of output: 256


Check Discord invite link expiration

We found a single Discord invite URL in the codebase:

  • File: src/app/dashboard/community-guardian/page.tsx
    Lines: 39–43

Discord’s default invites expire after 7 days. To avoid broken links, please verify in your server settings that this invite is set to never expire, then update the href accordingly.

src/app/dashboard/agent/page.tsx (1)

1-24: Good improvements to component structure and behavior.

The changes to this component are well-implemented:

  1. Adding the 'use client' directive appropriately marks this as a client component
  2. Updating to FaRobot from FA6 uses the newer icon library
  3. Renaming to AgentPage and using default export follows better React component naming conventions
  4. Replacing fixed height with overflow-y-auto improves content scrolling behavior
  5. The changes align well with the new centralized layout system
src/constants/PlatformContext.ts (1)

1-48: Well-structured platform configuration with good type safety.

Creating a centralized, typed definition of platforms is a good approach for consistency across the application.

src/hooks/platforms/usePlatforms.ts (1)

1-19: Good implementation of a data fetching hook with React Query.

This hook is well structured and follows React Query best practices for fetching platform data.

src/app/dashboard/settings/page.tsx (1)

1-23: Well-structured settings gateway page with good UX considerations.

This component is nicely implemented:

  • Good use of semantic HTML with appropriate heading levels
  • Clear warning to users about the development status
  • Helpful navigation between different settings sections
  • Clean and minimal code with proper imports
  • Responsive layout using utility classes
src/app/layout.tsx (3)

3-7: Good import organization and global styles setup.

The imports are well-structured with appropriate spacing, and the global CSS import will ensure consistent styling throughout the application.


9-19: Font configuration looks good.

The Next.js font optimization is properly implemented with both Inter and Roboto Mono fonts. The configuration includes appropriate subsets, display settings, and CSS variable names that can be referenced throughout the application.


25-30: Well-structured layout with proper authentication context.

The body is appropriately configured with font variables and the AuthProvider ensures authentication context is available throughout the application. The flex container provides a good base layout with proper height and background styling.

src/components/layouts/DashboardLayout.tsx (1)

17-26: Well-designed responsive layout with smooth transitions.

The layout effectively uses flexbox and conditional classes based on the sidebar state. The transitions are appropriately defined with smooth duration, and the overflow handling is properly configured.

src/pages/centric/select-community.tsx (2)

11-15: Good implementation of loading state management.

The loading state is well-implemented with a clear handler function that can be passed down to child components.


17-19: Clean conditional rendering of LoadingScreen.

Using a separate LoadingScreen component provides a consistent loading experience across the application and is appropriately shown conditionally based on the loading state.

src/components/centric/selectCommunity/TcSelectCommunity.tsx (3)

25-25: Good type definition for the new prop.

The component properly defines the type for the new handleCommunityLoading prop, making it clear what type of function is expected.


42-44: Well-implemented useEffect to sync loading state.

The useEffect hook properly syncs the local loading state with the parent component through the callback function.


82-82: Route change from "/centric/welcome" to "/dashboard" is appropriate.

The navigation target has been changed from "/centric/welcome" to "/dashboard", which aligns with the PR objective of restructuring the application's dashboard and navigation.

src/hooks/mediawiki/useNamespaces.ts (1)

5-21: Well-structured React Query hook.

The hook is properly implemented using React Query with appropriate query key structure, enabling/disabling based on URL availability, and clean parameter handling. Good job!

src/components/layouts/Breadcrumbs.tsx (1)

30-44: Clean and accessible breadcrumb implementation.

The breadcrumb UI is well-structured and follows common patterns for breadcrumb navigation. The conditional rendering for the last item is a good practice.

src/app/dashboard/layout.tsx (2)

3-11: Well-organized imports and client setup.

The imports are well-organized and grouped by their purpose. The QueryClient instantiation at the module level follows best practices for Next.js client components.


16-27: Well-structured component provider nesting.

The layout correctly sets up the necessary providers for authentication protection, React Query caching, token management, and consistent UI layout. The component hierarchy is properly organized.

src/components/communitySettings/HivemindSettings/TcHivemindSettings.tsx (1)

545-551: Good integration of MediaWikiModuleForm.

The MediaWiki tab panel now correctly uses the new MediaWikiModuleForm component. The implementation properly handles loading state, payload derivation (with fallback), and update callback.

src/components/settings/modules/mediawiki/Form.tsx (1)

16-22: Form implementation with react-hook-form looks good

The form implementation using react-hook-form is clean and follows best practices. Good use of the useForm hook with defaultValues from the passed payload and the straightforward submission handler.

src/components/inputs/MultiCheckboxSelector.tsx (1)

28-64: LGTM! The component render structure is well-organized

The component has a clean, semantic HTML structure with appropriate classes for styling. The grid layout for checkboxes with responsive columns is a good approach for displaying multiple options.

src/pages/centric/create-new-community.tsx (3)

42-42: LGTM! Replaced SimpleBackdrop with LoadingScreen component

The change from the previous loading indicator to the standardized LoadingScreen component improves consistency across the application.


37-37: LGTM! Updated navigation path to /dashboard

Changing the navigation target from /centric/welcome to /dashboard aligns with the updated routing structure.


117-119: LGTM! Added Back button for improved navigation

The addition of the Back button improves the user experience by providing an easy way to navigate to the previous page.

src/axiosInstance.ts (1)

79-79: LGTM! Simplified token destructuring

The change to destructure only the refreshToken from the user object is cleaner as that's the only value needed in this context.

src/hooks/sidebar/useSidebar.ts (1)

27-55: The sidebar hook implementation looks good.

The useSidebar hook is well-structured with:

  • Proper use of useMemo for computing sidebar items based on admin status
  • Clear filtering of admin-only modules for non-admin users
  • Good type safety using the ISidebarItem interface
src/constants/ModuleContext.ts (1)

7-69: Module context definition is comprehensive and well-structured.

The MODULE_CONTEXT array provides a clear structure for each module with consistent properties including icons, paths, descriptions, and admin flags.

src/components/inputs/ToggleInput.tsx (1)

11-46: Well-implemented toggle component with form integration.

The ToggleInput component is well-structured with:

  • Proper integration with react-hook-form
  • Error handling and display
  • Accessibility considerations (labels and helper text)
  • Good use of Tailwind/DaisyUI styling for consistency
src/utils/interfaces.ts (2)

241-241: Good addition of the activated property.

Adding the activated boolean property to the IModuleProps interface provides clear typing for module activation state.


244-253: Module context interface is well-defined.

The IModuleContext interface provides comprehensive type definitions for module metadata, including icons, paths, and admin flags.

src/components/inputs/WebsiteInput.tsx (1)

61-85: Nice UI implementation with clear error feedback

The UI implementation includes proper labeling, error states, and helper text. The form control follows accessibility best practices with proper label association and error message handling.

src/components/communitySettings/communityPlatforms/TcTelegram/TcTelegramIntegrationDialog.tsx (1)

57-62: Good improvement in dependency tracking

Moving the addPlatform extraction inside the useEffect and changing the dependency from [addPlatform] to [searchParams] ensures the effect runs whenever search parameters change. This is more reliable for reacting to URL parameter changes.

src/context/AuthProvider.tsx (1)

103-109: Well-designed custom hook with error handling

The useAuth custom hook is well implemented with proper error handling for cases when it's used outside the AuthProvider context.

src/components/mediawiki/Form.tsx (1)

82-89: detectTest always succeeds on HTTP 200—even if the payload is invalid
getNamespaces never throws when the request succeeds but returns garbage, therefore detectTest resolves true in those cases.

Add a minimal sanity-check (e.g. expect at least namespace 0) and throw otherwise:

   const detectTest = useCallback(async (url: string) => {
     try {
-      await getNamespaces(url)
-      return true;
+      const ok = await getNamespaces(url)
+      if (!ok?.query?.namespaces?.[0]) throw new Error("No main namespace");
+      return true;
     } catch (error) {
       return false;
     }
   }, []);

Alternatively make getNamespaces return a boolean instead of mutating state for a pure probe.

src/components/mediawiki/List.tsx (1)

98-105: useEffect runs even when data is undefined
Accessing data.query.namespaces before the request resolves throws. Short-circuit first:

-    const tags = platform.metadata.namespace.map((key: number) => {
+    if (!data) return;
+    const tags = platform.metadata.namespace.map((key: number) => {
       ...
     })

Comment on lines +12 to +15
const { data } = useQuery({
queryKey: ["platform", id],
queryFn: () => axiosInstance.get(`/platforms/${id}`),
})
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Missing error and loading states for query

The component doesn't handle loading or error states from the React Query hook, which could lead to a poor user experience if the API request fails or takes time to load.

Consider adding error and loading states:

- const { data } = useQuery({
+ const { data, isLoading, error } = useQuery({
  queryKey: ["platform", id],
  queryFn: () => axiosInstance.get(`/platforms/${id}`),
})

// Then in the return statement:
<div className="bg-base-100 p-8 rounded-lg">
+  {isLoading && <p>Loading...</p>}
+  {error && <p className="text-error">Error loading platform details</p>}
+  {data?.data && (
+    // Display data here
+  )}
</div>
📝 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
const { data } = useQuery({
queryKey: ["platform", id],
queryFn: () => axiosInstance.get(`/platforms/${id}`),
})
// Before:
- const { data } = useQuery({
+ const { data, isLoading, error } = useQuery({
queryKey: ["platform", id],
queryFn: () => axiosInstance.get(`/platforms/${id}`),
})
return (
<div className="bg-base-100 p-8 rounded-lg">
+ {isLoading && <p>Loading...</p>}
+ {error && <p className="text-error">Error loading platform details</p>}
+ {data?.data && (
+ // Display data here
+ )}
</div>
)

<div className="flex flex-col bg-white h-[800px] rounded-lg shadow-lg">
<div className="flex-1 overflow-y-auto p-8 space-y-4 text-sm">
<div className="flex flex-col">
<div className="flex-1 overflow-y-hidden space-y-4 text-sm max-h-screen">
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider enabling scrolling for chat messages

Using overflow-y-hidden with max-h-screen could prevent users from scrolling through chat history when it exceeds the screen height.

Consider enabling scrolling with auto scrollbars:

- <div className="flex-1 overflow-y-hidden space-y-4 text-sm max-h-screen">
+ <div className="flex-1 overflow-y-auto space-y-4 text-sm max-h-[80vh]">

This would allow users to scroll through message history while still maintaining a reasonable height constraint.

📝 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
<div className="flex-1 overflow-y-hidden space-y-4 text-sm max-h-screen">
<div className="flex-1 overflow-y-auto space-y-4 text-sm max-h-[80vh]">

<div className="text-xs font-semibold bg-gray-100 px-4 py-2 rounded-full w-fit">Applications</div>
</div>
<ul role="list" className="divide-y divide-gray-100 overflow-y-auto max-h-[385px]">
{MODULE_CONTEXT.map((context: IModuleContext, index: number) => <ModuleItem key={index} context={context} module={getModule(context.name)} />)}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Use stable keys for list items instead of array indices

Using array indices as React keys can lead to unexpected behavior when the list items change. Consider using a more stable identifier from the context or module data.

-{MODULE_CONTEXT.map((context: IModuleContext, index: number) => <ModuleItem key={index} context={context} module={getModule(context.name)} />)}
+{MODULE_CONTEXT.map((context: IModuleContext) => <ModuleItem key={context.name} context={context} module={getModule(context.name)} />)}
📝 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
{MODULE_CONTEXT.map((context: IModuleContext, index: number) => <ModuleItem key={index} context={context} module={getModule(context.name)} />)}
{MODULE_CONTEXT.map((context: IModuleContext) => <ModuleItem key={context.name} context={context} module={getModule(context.name)} />)}

Comment on lines +12 to +16
const { data, isLoading } = useModules(community?.id);

const getModule = (name: string) => {
return data?.results?.find((module: IModuleProps) => module.name === name);
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add error handling for the API request

The component doesn't handle potential errors from the useModules hook. This could lead to a poor user experience if the API request fails.

-  const { data, isLoading } = useModules(community?.id);
+  const { data, isLoading, error } = useModules(community?.id);

   const getModule = (name: string) => {
     return data?.results?.find((module: IModuleProps) => module.name === name);
   }
+
+  if (error) {
+    return <div className="p-4 text-red-500">Failed to load modules. Please try again later.</div>;
+  }
📝 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
const { data, isLoading } = useModules(community?.id);
const getModule = (name: string) => {
return data?.results?.find((module: IModuleProps) => module.name === name);
}
const { data, isLoading, error } = useModules(community?.id);
const getModule = (name: string) => {
return data?.results?.find((module: IModuleProps) => module.name === name);
}
if (error) {
return <div className="p-4 text-red-500">Failed to load modules. Please try again later.</div>;
}

export const useModules = (communityId: string | undefined) => {

return useQuery({
queryKey: ["modules"],
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Include communityId in the queryKey for proper cache management

The current queryKey doesn't include the communityId, which could lead to cache conflicts if the hook is used with different community IDs in the same app.

-    queryKey: ["modules"],
+    queryKey: ["modules", communityId],

Comment on lines +61 to +80
const getNamespaces = useCallback(async (url: string) => {
const params = new URLSearchParams({
action: "query",
meta: "siteinfo",
siprop: "namespaces",
format: "json",
origin: "*",
})
const res = await fetch(url.concat("?", params.toString()))
const data = await res.json()
setNamespaces([])
Object.values(data?.query?.namespaces || {}).forEach((value: unknown) => {
const namespace = value as MediaWikiNamespace;
let obj = { label: namespace.canonical, value: namespace.id }
if (namespace.id === 0) {
obj = { label: "Articles", value: namespace.id };
}
setNamespaces((prev) => [...prev, obj]);
});
}, [])
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Batch state updates to avoid dozens of unnecessary re-renders
setNamespaces is called inside a loop, which schedules a React state update on every namespace returned by the API. With ±20 namespaces that is 20 renders instead of one.

-    setNamespaces([])
-    Object.values(data?.query?.namespaces || {}).forEach((value: unknown) => {
-      const namespace = value as MediaWikiNamespace;
-      let obj = { label: namespace.canonical, value: namespace.id }
-      if (namespace.id === 0) {
-        obj = { label: "Articles", value: namespace.id };
-      }
-      setNamespaces((prev) => [...prev, obj]);
-    });
+    const opts: { label: string; value: number }[] = [];
+    Object.values(data?.query?.namespaces || {}).forEach((value: unknown) => {
+      const ns = value as MediaWikiNamespace;
+      opts.push({
+        label: ns.id === 0 ? "Articles" : ns.canonical ?? "Unknown",
+        value: ns.id,
+      });
+    });
+    setNamespaces(opts);

This single‐shot update removes the render-storm.

📝 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
const getNamespaces = useCallback(async (url: string) => {
const params = new URLSearchParams({
action: "query",
meta: "siteinfo",
siprop: "namespaces",
format: "json",
origin: "*",
})
const res = await fetch(url.concat("?", params.toString()))
const data = await res.json()
setNamespaces([])
Object.values(data?.query?.namespaces || {}).forEach((value: unknown) => {
const namespace = value as MediaWikiNamespace;
let obj = { label: namespace.canonical, value: namespace.id }
if (namespace.id === 0) {
obj = { label: "Articles", value: namespace.id };
}
setNamespaces((prev) => [...prev, obj]);
});
}, [])
const getNamespaces = useCallback(async (url: string) => {
const params = new URLSearchParams({
action: "query",
meta: "siteinfo",
siprop: "namespaces",
format: "json",
origin: "*",
})
const res = await fetch(url.concat("?", params.toString()))
const data = await res.json()
const opts: { label: string; value: number }[] = [];
Object.values(data?.query?.namespaces || {}).forEach((value: unknown) => {
const ns = value as MediaWikiNamespace;
opts.push({
label: ns.id === 0 ? "Articles" : ns.canonical ?? "Unknown",
value: ns.id,
});
});
setNamespaces(opts);
}, [])

Comment on lines +91 to +97
useEffect(() => {
if (path) {
const url = new URL(path, getValues("baseURL"))
getNamespaces(url.toString())
}
}, [path])

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Guard against empty baseURL before constructing new URL
If the user edits the API path before entering a base URL, new URL(path, "") throws and breaks the form.

-    if (path) {
-      const url = new URL(path, getValues("baseURL"))
-      getNamespaces(url.toString())
+    const base = getValues("baseURL");
+    if (path && base) {
+      try {
+        const url = new URL(path, base);
+        getNamespaces(url.toString());
+      } catch { /* silently ignore invalid URL until user fixes input */ }
     }
📝 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
useEffect(() => {
if (path) {
const url = new URL(path, getValues("baseURL"))
getNamespaces(url.toString())
}
}, [path])
useEffect(() => {
const base = getValues("baseURL");
if (path && base) {
try {
const url = new URL(path, base);
getNamespaces(url.toString());
} catch { /* silently ignore invalid URL until user fixes input */ }
}
}, [path])

Comment on lines +22 to +28
if (!module?.id) {
await createModule.mutateAsync({
module: {
name: context.name,
activated: checked
}
})
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

community is missing when creating a new module
POST /modules is invoked with only name and activated. The backend very likely expects the community ID (all other module calls in the codebase include it).

-      await createModule.mutateAsync({
-        module: {
-          name: context.name,
-          activated: checked
-        }
-      })
+      await createModule.mutateAsync({
+        module: {
+          name: context.name,
+          community: community?.id,
+          activated: checked,
+        },
+      });

Without this property the request may fail or create orphaned records.

Comment on lines +20 to +24
const TableHeaderCell = ({ item }: { item: TableItem }) => {
return (
<th scope="col" className={`px-6 py-3 text-xs font-mono text-gray-500 uppercase tracking-wider text-${item.align} cursor-default`}>
{item.value}
</th>
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Dynamic Tailwind class names are purged – header alignment breaks
Tailwind’s purge step removes text-${item.align} because it cannot statically see the class. The headers will therefore always render with no text-alignment utility.

Replace with a map or conditional classes:

- className={`px-6 py-3 text-xs ... text-${item.align} ...`}
+ className={`px-6 py-3 text-xs ... ${
+   item.align === "left"
+     ? "text-left"
+     : item.align === "right"
+     ? "text-right"
+     : "text-center"
+ } ...`}
📝 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
const TableHeaderCell = ({ item }: { item: TableItem }) => {
return (
<th scope="col" className={`px-6 py-3 text-xs font-mono text-gray-500 uppercase tracking-wider text-${item.align} cursor-default`}>
{item.value}
</th>
const TableHeaderCell = ({ item }: { item: TableItem }) => {
return (
<th
scope="col"
className={`px-6 py-3 text-xs font-mono text-gray-500 uppercase tracking-wider ${
item.align === "left"
? "text-left"
: item.align === "right"
? "text-right"
: "text-center"
} cursor-default`}
>
{item.value}
</th>
);
};

Comment on lines +35 to +38
<li>
<Link href={item.href || ''} className={`py-3 lg:hidden ${item.href === window.location.pathname ? 'text-secondary' : ''}`}><SidebarLabel item={item} /></Link>
<Link href={item.href || ''} className={`hidden lg:flex tooltip tooltip-right btn btn-square btn-ghost ${item.href === window.location.pathname ? 'text-secondary bg-base-200' : ''}`} data-tip={item.label}><SidebarLabel item={item} /></Link>
</li>
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Avoid direct window.location access – use Next.js router instead
window is undefined during Server Components rendering (the file is client-only now, but direct access prevents future reuse and doesn’t react to route changes). Use usePathname() from next/navigation.

-import Link from "next/link";
+import Link from "next/link";
+import { usePathname } from "next/navigation";
...
 function SidebarItem({ item }: { item: ISidebarItem }) {
-  if (item.children && item.children.length > 0) { ... }
+  const pathname = usePathname();
...
-  <Link ... className={`${item.href === window.location.pathname ? 'text-secondary' : ''}`} >
+  <Link ... className={`${item.href === pathname ? 'text-secondary' : ''}`} >

This keeps the highlight in sync on client-side navigations.

Committable suggestion skipped: line range outside the PR's diff.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
src/app/_error.tsx (2)

18-23: Enhance error UI with better styling and accessibility.

The current error UI is very minimalistic and lacks proper styling and accessibility attributes. This can impact user experience and accessibility for screen readers.

Consider enhancing the error UI with better styling and accessibility support:

  return (
-    <div>
-      <h2>Something went wrong!</h2>
-      <button onClick={() => reset()}>Try again</button>
+    <div className="flex flex-col items-center justify-center min-h-[400px] p-4 text-center" role="alert" aria-live="assertive">
+      <h2 className="text-2xl font-bold text-red-600 mb-4">Something went wrong!</h2>
+      {process.env.NODE_ENV !== 'production' && (
+        <p className="text-gray-600 mb-4">{error.message || String(error)}</p>
+      )}
+      <button 
+        onClick={() => reset()} 
+        className="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500"
+        aria-label="Try again"
+      >
+        Try again
+      </button>
    </div>
  );

This implementation:

  • Adds proper styling using utility classes (assuming Tailwind CSS is used in the project)
  • Shows the error message in development mode to help with debugging
  • Improves accessibility with appropriate ARIA attributes
  • Enhances the button with proper styling and focus states

14-16: Consider adding more comprehensive error logging.

The current implementation only logs the error to the console, which might not be sufficient for tracking and resolving issues in production.

Consider enhancing the error logging to capture more context or integrate with an error tracking service:

  useEffect(() => {
    console.error(error);
+    // If you have an error tracking service like Sentry, you might want to log the error there
+    // Example: captureException(error);
+    
+    // You might also want to log additional context information
+    console.error('Error occurred at:', new Date().toISOString());
+    console.error('Error digest:', error.digest);
  }, [error]);
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 67af038 and bb25d2e.

📒 Files selected for processing (2)
  • next.config.cloudflare.js (1 hunks)
  • src/app/_error.tsx (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • next.config.cloudflare.js
🧰 Additional context used
🪛 Biome (1.9.4)
src/app/_error.tsx

[error] 7-7: Do not shadow the global "Error" property.

Consider renaming this variable. It's easy to confuse the origin of variables when they're named after a known global.

(lint/suspicious/noShadowRestrictedNames)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (1)
src/app/_error.tsx (1)

3-3: LGTM: Edge runtime configuration.

Setting the runtime to 'edge' for the error component is appropriate for ensuring fast performance and global distribution. This aligns well with the overall architecture mentioned in the PR summary.

Comment on lines 7 to 13
export default function Error({
error,
reset,
}: {
error: Error & { digest?: string };
reset: () => void;
}) {
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Avoid shadowing the global Error object name.

The component name Error shadows the global Error constructor. This could lead to potential confusion and bugs when trying to reference the global Error object within the component.

Consider renaming the component to something more specific like ErrorBoundary or AppError:

-export default function Error({
+export default function ErrorBoundary({
  error,
  reset,
}: {
  error: Error & { digest?: string };
  reset: () => void;
}) {
📝 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
export default function Error({
error,
reset,
}: {
error: Error & { digest?: string };
reset: () => void;
}) {
export default function ErrorBoundary({
error,
reset,
}: {
error: Error & { digest?: string };
reset: () => void;
}) {
🧰 Tools
🪛 Biome (1.9.4)

[error] 7-7: Do not shadow the global "Error" property.

Consider renaming this variable. It's easy to confuse the origin of variables when they're named after a known global.

(lint/suspicious/noShadowRestrictedNames)

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
src/app/error.tsx (2)

14-16: Consider more robust error logging

The current implementation only logs errors to the console, which is helpful during development but insufficient for production environments.

Consider implementing a more comprehensive error logging solution:

useEffect(() => {
  console.error(error);
+ // Consider sending errors to a monitoring service
+ // Example: reportErrorToMonitoringService(error);
}, [error]);

18-23: Enhance the error UI for better user experience

The current error UI is minimal and doesn't provide enough context or visual feedback to users.

Consider implementing a more user-friendly error UI:

return (
- <div>
-   <h2>Something went wrong!</h2>
-   <button onClick={() => reset()}>Try again</button>
- </div>
+ <div className="flex flex-col items-center justify-center min-h-[400px] p-6 text-center">
+   <h2 className="text-2xl font-bold text-red-600 mb-4">Something went wrong!</h2>
+   <p className="mb-6 text-gray-600">
+     We encountered an error while processing your request. 
+     {error.message && <span className="font-medium"> Error details: {error.message}</span>}
+   </p>
+   <button 
+     onClick={() => reset()} 
+     className="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700 transition-colors"
+   >
+     Try again
+   </button>
+ </div>
);
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between bb25d2e and 8426666.

📒 Files selected for processing (4)
  • next.config.js (1 hunks)
  • src/app/error.tsx (1 hunks)
  • src/pages/_error.tsx (0 hunks)
  • tsconfig.json (2 hunks)
💤 Files with no reviewable changes (1)
  • src/pages/_error.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • next.config.js
  • tsconfig.json
🧰 Additional context used
🪛 Biome (1.9.4)
src/app/error.tsx

[error] 7-7: Do not shadow the global "Error" property.

Consider renaming this variable. It's easy to confuse the origin of variables when they're named after a known global.

(lint/suspicious/noShadowRestrictedNames)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (1)
src/app/error.tsx (1)

1-3:

Details

❓ Verification inconclusive

Verify client component with edge runtime compatibility

The component is marked as a client component running on the edge runtime. While this setup can work, be aware that the edge runtime has certain limitations compared to Node.js environments.


🌐 Web query:

What are the limitations of Next.js edge runtime for client components?

💡 Result:

Limitations of Next.js Edge Runtime for Client Components

The Next.js Edge Runtime offers performance and scalability advantages, but it imposes several significant limitations, especially when building or relying on client components. These constraints are rooted in the underlying architecture and the browser-like environment of the Edge Runtime.

Key Limitations:

  • No Access to Native Node.js APIs: The Edge Runtime explicitly excludes all native Node.js APIs such as fs (filesystem), net, and crypto. This means you cannot read or write to the filesystem, manage sockets, or use certain cryptographic functionalities directly in the Edge Runtime[2][7]. Many npm packages that expect these APIs will fail or throw errors such as “Module not found: Can't resolve 'fs'”[1][3].

  • Limited npm Package Compatibility: While you can use node_modules, all packages must be implemented as ES Modules and must not depend on native Node.js APIs[3]. Packages designed specifically for the Node.js environment (like popular database drivers or session managers) often do not work[7]. If an essential library expects Node APIs, an alternative solution (such as HTTP-based APIs for database access) is required[4][7].

  • No require Statement Support: The Edge Runtime only supports ES Modules; the use of require statements is not allowed. You must use import/export syntax everywhere[3].

  • Prohibited JavaScript Features: Certain dynamic code evaluation features are not supported, including:

    • eval
    • new Function(evalString)
    • WebAssembly.compile
    • WebAssembly.instantiate
      Attempting to use these features will throw runtime errors[3].
  • Bundle Size Limitations: Code executed in the Edge Runtime has strict size limits, typically between 1 MB and 4 MB depending on deployment infrastructure. This includes all imported packages, fonts, and files. Large or complex dependencies can quickly exceed this threshold[1].

  • Incremental Static Regeneration (ISR) Not Supported: ISR, a feature that allows static pages to be updated after deployment, is not available in the Edge Runtime[2].

  • Performance and Reliability Issues: Some users report performance drawbacks, such as slower response times for certain dynamic or AI-driven features, both locally and in production[6]. Debugging and performance tuning may be more challenging.

  • Database and Session Management Limitations: Direct connections to databases using traditional Node.js drivers are not possible. Any operation requiring TCP or proprietary Node libraries is blocked, necessitating an architecture shift (e.g., using HTTP APIs to proxy database access)[4][7].

  • Middleware and Routing Constraints: Middleware functions running in the Edge Runtime are confined by the same restrictions, and certain Next.js features (like custom authentication or advanced routing logic) may encounter compatibility issues[7].

  • Error Handling and Debugging Challenges: Issues such as unexplained 500 errors on initial load have been noted when using Edge Runtime[9]. Disabling Edge Runtime often resolves these issues, suggesting incomplete parity with the Node.js runtime for some scenarios.

Summary Table: Edge Runtime Limitations

Limitation Description/Impact
No Node.js APIs Cannot use fs, net, crypto, etc.
Limited package compatibility Only ES Modules, with no native Node API dependencies
No require Must use ES Modules (import/export)
Disabled JS features eval, new Function, WebAssembly not supported
Bundle size capped 1–4 MB per function (code, packages, assets)
No ISR Cannot perform Incremental Static Regeneration
Database/session issues No direct DB connections, session management often blocked
Possible performance issues Reports of slower response times or inconsistent performance
Error/debugging overhead Difficult debugging, unexplained 500 errors in some cases

Conclusion:
When working with Next.js client components or building features intended for the Edge Runtime, it is essential to design within these constraints. Many server-side patterns common to traditional Node.js must be re-architected—either by interfacing via HTTP APIs, switching to compatible packages, or opting for the standard Node.js runtime in segments that require full Node.js capabilities[1][2][7].

Citations:


Ensure Edge Runtime Compatibility in src/app/error.tsx

The component is marked as a client component with the Edge Runtime (export const runtime = 'edge'). The Edge Runtime does not support all Node.js features—please verify that neither this file nor any of its dependencies rely on:

  • Native Node.js APIs (fs, net, crypto, etc.)
  • CommonJS require (Edge only supports ES Modules)
  • Dynamic code evaluation (eval, new Function, WebAssembly)
  • Large bundles (Edge functions typically cap around 1–4 MB total)
  • Incremental Static Regeneration (ISR) or direct DB drivers over TCP

If you need full Node.js capabilities or unsupported packages, consider switching to the default Node.js runtime or isolating that logic in a server-side API.

Copy link

@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: 2

🧹 Nitpick comments (1)
src/app/error.tsx (1)

7-9: Improve accessibility of the error page.

Error pages should be fully accessible to all users. Consider enhancing the HTML structure with proper semantic elements and ARIA attributes.

-  return (
-    <div>
-      <h1>Error - Something went wrong</h1>
-    </div>
-  )
+  return (
+    <main role="alert" aria-labelledby="error-heading" className="p-4 max-w-2xl mx-auto text-center my-8">
+      <h1 id="error-heading" className="text-2xl font-bold mb-4">Error - Something went wrong</h1>
+    </main>
+  )
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 8426666 and d1ab37b.

📒 Files selected for processing (8)
  • next.config.js (1 hunks)
  • package.json (6 hunks)
  • src/app/_not-found/page.tsx (1 hunks)
  • src/app/dashboard/settings/mediawiki/[id]/edit/page.tsx (1 hunks)
  • src/app/dashboard/settings/mediawiki/[id]/page.tsx (1 hunks)
  • src/app/error.tsx (1 hunks)
  • src/app/layout.tsx (1 hunks)
  • tsconfig.json (2 hunks)
✅ Files skipped from review due to trivial changes (1)
  • src/app/_not-found/page.tsx
🚧 Files skipped from review as they are similar to previous changes (6)
  • next.config.js
  • src/app/layout.tsx
  • tsconfig.json
  • src/app/dashboard/settings/mediawiki/[id]/page.tsx
  • package.json
  • src/app/dashboard/settings/mediawiki/[id]/edit/page.tsx
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (1)
src/app/error.tsx (1)

5-5: Good use of a descriptive component name.

The component name ErrorPage is clear and descriptive, avoiding the issue of shadowing the global Error object that was mentioned in previous reviews.

Comment on lines 5 to 11
export default function ErrorPage() {
return (
<div>
<h1>Error - Something went wrong</h1>
</div>
)
} No newline at end of file
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider enhancing the error page with more details and recovery options.

The current error page is very minimal, only displaying a generic error message. Users won't receive any specific information about what went wrong or how to recover. Consider enhancing this component to:

  1. Accept and display specific error information via props
  2. Include a "Try Again" button or other recovery mechanisms
  3. Provide navigation options to help users get back to a working state
-export default function ErrorPage() {
+export default function ErrorPage({ 
+  error,
+  reset,
+}: {
+  error: Error & { digest?: string }
+  reset: () => void
+}) {
   return (
     <div>
       <h1>Error - Something went wrong</h1>
+      <p>
+        {process.env.NODE_ENV === 'development' && error.message}
+        {error.digest && <span>Error ID: {error.digest}</span>}
+      </p>
+      <button
+        onClick={reset}
+        className="mt-4 px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600"
+      >
+        Try Again
+      </button>
     </div>
   )
 }
📝 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
export default function ErrorPage() {
return (
<div>
<h1>Error - Something went wrong</h1>
</div>
)
}
export default function ErrorPage({
error,
reset,
}: {
error: Error & { digest?: string }
reset: () => void
}) {
return (
<div>
<h1>Error - Something went wrong</h1>
<p>
{process.env.NODE_ENV === 'development' && error.message}
{error.digest && <span>Error ID: {error.digest}</span>}
</p>
<button
onClick={reset}
className="mt-4 px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600"
>
Try Again
</button>
</div>
)
}

@@ -0,0 +1,11 @@
'use client';

export const runtime = 'edge';
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Verify edge runtime compatibility with error handling.

Using the edge runtime for the error page may limit access to certain APIs that might be needed for comprehensive error handling. Ensure that all functionality required for error reporting and recovery is available in the edge runtime.


🌐 Web query:

What limitations exist for Next.js error pages when using edge runtime?

💡 Result:

When deploying Next.js applications with custom error pages (e.g., 404.js, 500.js) on the Edge Runtime, it's important to be aware of certain limitations:

  1. Unsupported Node.js APIs: The Edge Runtime does not support native Node.js APIs, such as file system access (fs), which are typically used in custom error pages for server-side rendering. (nextjs.org)

  2. Dynamic Code Execution Restrictions: Features like eval(), new Function(), and dynamic WebAssembly instantiation are disabled in the Edge Runtime for security reasons. This means that any code relying on these features will not function as expected. (nextjs.org)

  3. Limited API Support: The Edge Runtime provides a subset of Web APIs, including fetch, Request, and Response. However, it lacks support for certain APIs that might be utilized in custom error pages, such as those for file system operations or other Node.js-specific functionalities. (nextjs.org)

Given these constraints, it's advisable to implement custom error pages using the Node.js Runtime, which offers full support for Node.js APIs and dynamic code execution. This approach ensures compatibility and functionality for your error handling pages. (nextjs.org)

Citations:


Enforce Node.js Runtime for Custom Error Page

The Edge Runtime restricts several APIs commonly used in error handling:

  • No access to native Node.js modules (e.g. fs, path)
  • Dynamic code evaluation disabled (eval, new Function, WebAssembly instantiation)
  • Only a limited set of Web APIs (fetch, Request, Response); no filesystem or other Node-only features

If your src/app/error.tsx relies on any of these (e.g. logging to disk, dynamic code, advanced error-reporting libraries), switch the runtime:

- export const runtime = 'edge';
+ export const runtime = 'nodejs';

Otherwise, ensure your error page implementation uses only the supported Web APIs in the Edge Runtime.

📝 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
export const runtime = 'edge';
export const runtime = 'nodejs';

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
next.config.js (1)

3-5: Bundle analyzer integration looks good but consider ESLint warnings.

The addition of @next/bundle-analyzer is a good practice for monitoring bundle sizes. The conditional enablement via the ANALYZE environment variable is a clean approach.

Note that ESLint flags a warning about using require() instead of import statements. This is a false positive since Next.js config files commonly use CommonJS module system.

If you want to silence the ESLint warning, you can add an ESLint disable comment:

/** @type {import('next').NextConfig} */

+// eslint-disable-next-line @typescript-eslint/no-var-requires
const withBundleAnalyzer = require('@next/bundle-analyzer')({
  enabled: process.env.ANALYZE === 'true',
})
🧰 Tools
🪛 ESLint

[error] 3-3: Require statement not part of import statement.

(@typescript-eslint/no-var-requires)

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between a405478 and 894e1d0.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (4)
  • next.config.js (1 hunks)
  • package.json (4 hunks)
  • src/components/layouts/xs/SidebarXs.tsx (2 hunks)
  • src/pages/_app.tsx (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/pages/_app.tsx
  • src/components/layouts/xs/SidebarXs.tsx
  • package.json
🧰 Additional context used
🪛 ESLint
next.config.js

[error] 3-3: Require statement not part of import statement.

(@typescript-eslint/no-var-requires)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (2)
next.config.js (2)

15-15: LGTM!

The closing bracket formatting change is necessary to support the bundle analyzer wrapper.


7-8:

Details

❓ Verification inconclusive

Verify the build output configuration change.

The configuration now uses distDir: 'out' instead of the previously removed output: 'export'. This is a significant change that affects how the application is built and deployed:

  1. output: 'export' generated a static site that could be deployed to any static hosting
  2. distDir: 'out' only changes the build directory but retains Next.js's standard build output

Ensure this aligns with your deployment strategy, as this might require changes to your deployment pipeline.


🏁 Script executed:

#!/bin/bash
# Check package.json for related build/export scripts that might need updating
cat package.json | grep -E '"(build|export|start)":'

Length of output: 108


Verify build output configuration change

I checked your next.config.js—you’ve removed the static export option (output: 'export') and now use:

const nextConfig = withBundleAnalyzer({
  distDir: 'out',
  // no `output: 'export'`
})

I also confirmed your package.json only has:

"build": "next build",
"start": "next start"

(there’s no "export" script defined).

• This setup produces a standard Next.js (SSR) build in the out folder, served via next start.
• If you intended a fully static export, you’ll need to re-introduce an export step (e.g. add an export script or restore output: 'export') and adjust your deployment pipeline.
• Otherwise, ensure your hosting environment supports running the Next.js server for SSR.

Please confirm this aligns with your deployment strategy.

Copy link

@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: 2

♻️ Duplicate comments (2)
src/app/error.tsx (2)

5-11: Rename component to avoid shadowing the global Error object

The component name Error shadows the built-in JavaScript Error object, which could lead to confusion and potential bugs.

-export default function Error() {
+export default function ErrorPage() {
  return (
    <div>
      <h1>Error</h1>
    </div>
  );
}
🧰 Tools
🪛 Biome (1.9.4)

[error] 5-5: Do not shadow the global "Error" property.

Consider renaming this variable. It's easy to confuse the origin of variables when they're named after a known global.

(lint/suspicious/noShadowRestrictedNames)


5-11: 🛠️ Refactor suggestion

Consider enhancing the error page with more details and recovery options

The current error page is very minimal, only displaying a generic error message. Users won't receive any specific information about what went wrong or how to recover.

-export default function Error() {
+export default function ErrorPage({ 
+  error,
+  reset,
+}: {
+  error: Error & { digest?: string }
+  reset: () => void
+}) {
   return (
     <div>
       <h1>Error</h1>
+      <p>
+        {process.env.NODE_ENV === 'development' && error.message}
+        {error.digest && <span>Error ID: {error.digest}</span>}
+      </p>
+      <button
+        onClick={reset}
+        className="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600"
+      >
+        Try Again
+      </button>
     </div>
   )
 }
🧰 Tools
🪛 Biome (1.9.4)

[error] 5-5: Do not shadow the global "Error" property.

Consider renaming this variable. It's easy to confuse the origin of variables when they're named after a known global.

(lint/suspicious/noShadowRestrictedNames)

🧹 Nitpick comments (3)
next.config.js (1)

18-35: Simplified configuration by removing unused options

The commented-out code shows this PR is moving away from:

  1. Bundle analyzer integration
  2. Static exports (output: 'export')
  3. Explicit SWC minification settings

This simplification is good, but consider removing commented code entirely once the changes are verified in production.

-// module.exports = nextConfig;
-
-// const withBundleAnalyzer = require('@next/bundle-analyzer')({
-//   enabled: process.env.ANALYZE === 'true',
-// })
-
-// const nextConfig = withBundleAnalyzer({
-//   // distDir: 'out',
-//   output: 'export',
-//   reactStrictMode: false,
-//   swcMinify: true,
-//   trailingSlash: true,
-//   images: {
-//     unoptimized: true,
-//   },
-// })
-
-// module.exports = nextConfig;
src/app/global-error.tsx (1)

12-18: Consider enhancing the error display with more information

The error page could be improved by showing more details about the error, especially in development mode.

  return (
    <html>
      <body>
        <h2>Something went wrong!</h2>
+       {process.env.NODE_ENV === 'development' && (
+         <div>
+           <p>{error.message}</p>
+           {error.stack && <pre>{error.stack}</pre>}
+           {error.digest && <p>Error ID: {error.digest}</p>}
+         </div>
+       )}
        <button onClick={() => reset()}>Try again</button>
      </body>
    </html>
  )
src/pages/_error.tsx (1)

11-14: Update getInitialProps to use Next.js types

The current implementation uses custom type annotations. Consider using Next.js provided types for better type safety and maintainability.

-Error.getInitialProps = ({ res, err }: { res?: { statusCode: number }, err?: { statusCode: number } }) => {
+ErrorPage.getInitialProps = ({ res, err }: NextPageContext) => {
  const statusCode = res ? res.statusCode : err ? err.statusCode : 404
  return { statusCode }
}

Don't forget to add the import for NextPageContext:

+import type { NextPageContext } from 'next';

function ErrorPage({ statusCode }: { statusCode: number }) {
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge Base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between 894e1d0 and 1152b84.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (10)
  • next.config.js (1 hunks)
  • package.json (5 hunks)
  • src/app/error.tsx (1 hunks)
  • src/app/global-error.tsx (1 hunks)
  • src/app/layout.tsx (1 hunks)
  • src/app/not-found.tsx (1 hunks)
  • src/pages/404.tsx (1 hunks)
  • src/pages/500.tsx (1 hunks)
  • src/pages/_error.tsx (1 hunks)
  • wrangler.toml (1 hunks)
✅ Files skipped from review due to trivial changes (4)
  • wrangler.toml
  • src/pages/404.tsx
  • src/pages/500.tsx
  • src/app/not-found.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/app/layout.tsx
  • package.json
🧰 Additional context used
🧬 Code Graph Analysis (2)
src/app/global-error.tsx (3)
src/app/error.tsx (2)
  • runtime (3-3)
  • Error (5-11)
src/app/layout.tsx (1)
  • runtime (3-3)
src/app/not-found.tsx (1)
  • runtime (5-5)
src/app/error.tsx (3)
src/app/global-error.tsx (1)
  • runtime (3-3)
src/app/layout.tsx (1)
  • runtime (3-3)
src/app/not-found.tsx (1)
  • runtime (5-5)
🪛 Biome (1.9.4)
src/pages/_error.tsx

[error] 1-1: Do not shadow the global "Error" property.

Consider renaming this variable. It's easy to confuse the origin of variables when they're named after a known global.

(lint/suspicious/noShadowRestrictedNames)

src/app/error.tsx

[error] 5-5: Do not shadow the global "Error" property.

Consider renaming this variable. It's easy to confuse the origin of variables when they're named after a known global.

(lint/suspicious/noShadowRestrictedNames)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (6)
next.config.js (3)

1-1: Integration with Cloudflare Pages development environment

The import of setupDevPlatform indicates a shift to using Cloudflare Pages for deployment. This is a significant architectural change that aligns with modern serverless deployment approaches.


10-16: Good transition to ES module syntax

The configuration now uses ES module syntax (export default) instead of CommonJS (module.exports), which aligns with modern JavaScript practices. The code also properly applies Cloudflare's development platform setup only in development environments.


1-16: Verify Cloudflare Pages compatibility

This configuration updates the project for Cloudflare Pages deployment. Make sure your CI/CD pipeline and deployment workflows have been updated accordingly.

Are there corresponding changes to the deployment scripts in package.json or CI config files that reflect this architectural change? You should have commands like wrangler pages dev for local development and wrangler pages deploy for production.

src/app/error.tsx (1)

3-3: Ensure edge runtime compatibility with error handling

The edge runtime has limitations that might impact error handling functionality. If your error component needs access to Node.js APIs or relies on any libraries that aren't edge-compatible, consider using the Node.js runtime instead.

-export const runtime = 'edge';
+export const runtime = 'nodejs';

See the Next.js documentation on Edge and Node.js runtimes for more details on the limitations.

src/app/global-error.tsx (2)

5-20: Good implementation of the global error page with reset functionality

The implementation includes both error handling and a reset button, which provides users with a way to recover from errors.


3-3: Ensure edge runtime compatibility with global error handling

Similar to the regular error page, the global error boundary may have limitations when using the edge runtime. If you need access to Node.js-specific APIs for error reporting or logging, consider using the Node.js runtime.

-export const runtime = 'edge';
+export const runtime = 'nodejs';

}

export default ErrorPage;
export default Error
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Update the default export name

If you rename the component as suggested above, make sure to update the export as well.

-export default Error
+export default ErrorPage
📝 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
export default Error
export default ErrorPage
🤖 Prompt for AI Agents
In src/pages/_error.tsx at line 16, the default export name should match the
renamed component. Update the export statement to export the component using its
new name instead of "Error" to maintain consistency and avoid reference errors.

Comment on lines +1 to +9
return (
<div className='container'>
<div className='mx-auto flex px-3 py-4 md:w-8/12 md:px-0 md:py-4'>
<Image alt='Image Alt' src={tcLogo} />
</div>{' '}
<div className='flex flex-col items-center justify-center p-3 md:mt-8 md:flex-row md:space-x-8 md:p-0'>
<div className='hidden md:relative md:block md:h-[214px] md:w-[248px]'>
<Image
alt='Image Alt'
src={notFounded}
layout='fill'
objectFit='contain'
/>
</div>
<div className='space-y-8'>
<h1 className='text-3xl font-bold'>
Oops! We’re sorry, we couldn’t find <br /> the page you’re looking
for.{' '}
</h1>
<div className='space-y-3'>
<p className='text-md font-bold'>What could have caused this?</p>
<div className='space-y-2'>
<p className='text-base'>
The link you clicked might be old and does not work anymore.
</p>
<p className='text-sm'>
Or you might have accidentally typed the wrong URL in the
address bar.
</p>
</div>
</div>
<div className='space-y-3'>
<p className='text-md font-bold'>What you can do</p>
<p className='text-sm'>
You might retype the URL or try some helpful links instead:
</p>
</div>
<div className='flex flex-col justify-between space-y-2 md:flex-row md:space-y-0 md:space-x-2'>
<TcButton
text='Community Insights'
variant='outlined'
onClick={() => router.push('/')}
className='py-2 md:w-1/2'
/>
<TcButton
onClick={() => router.push('/centric')}
variant='outlined'
text='Connect your community'
className='py-2 md:w-1/2'
/>
</div>
</div>
</div>
</div>
);
};
<p>
{statusCode
? `An error ${statusCode} occurred on server`
: 'An error occurred on client'}
</p>
)
}

Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Rename component to avoid shadowing the global Error object

The component name Error shadows the built-in JavaScript Error object, which could lead to confusion and potential bugs.

-function Error({ statusCode }: { statusCode: number }) {
+function ErrorPage({ statusCode }: { statusCode: number }) {
  return (
    <p>
      {statusCode
        ? `An error ${statusCode} occurred on server`
        : 'An error occurred on client'}
    </p>
  )
}
🧰 Tools
🪛 Biome (1.9.4)

[error] 1-1: Do not shadow the global "Error" property.

Consider renaming this variable. It's easy to confuse the origin of variables when they're named after a known global.

(lint/suspicious/noShadowRestrictedNames)

🤖 Prompt for AI Agents
In src/pages/_error.tsx lines 1 to 9, the component is named Error, which
shadows the global JavaScript Error object. Rename the component to a different
name such as CustomError or ErrorPage to avoid this shadowing and potential
confusion or bugs.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
Cache: Disabled due to data retention organization setting
Knowledge Base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between 3fede2d and 0780b83.

📒 Files selected for processing (3)
  • src/app/layout.tsx (1 hunks)
  • src/configs/index.ts (1 hunks)
  • src/rainbowKitConfig.ts (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • src/rainbowKitConfig.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/app/layout.tsx
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Cloudflare Pages

Comment on lines +19 to +20
console.log(`conf: ${JSON.stringify(conf)}`);

Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Remove or conditionally enable debug logging in production code.

Logging configuration values to the console could potentially expose sensitive information (such as API tokens or addresses) and is not recommended for production code. Consider either:

  1. Removing this statement before deploying to production
  2. Adding a conditional check to only log in development environments:
-console.log(`conf: ${JSON.stringify(conf)}`);
+if (process.env.NODE_ENV === 'development') {
+  console.log(`conf: ${JSON.stringify(conf)}`);
+}
📝 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
console.log(`conf: ${JSON.stringify(conf)}`);
// ... other code ...
if (process.env.NODE_ENV === 'development') {
console.log(`conf: ${JSON.stringify(conf)}`);
}
// ... other code ...
🤖 Prompt for AI Agents
In src/configs/index.ts around lines 19 to 20, the console.log statement outputs
configuration values which may expose sensitive information in production.
Remove this console.log statement or wrap it in a conditional that checks if the
environment is development before logging, ensuring sensitive data is not
exposed in production environments.

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