{canExecuteOrganisationAction('MANAGE_ORGANISATION', row.original.currentOrganisationRole) && (
@@ -117,7 +97,7 @@ export const UserOrganisationsTable = () => {
),
},
] satisfies DataTableColumnDef<(typeof results)['data'][number]>[];
- }, [isPersonalLayoutMode]);
+ }, []);
return (
@@ -130,9 +110,6 @@ export const UserOrganisationsTable = () => {
error={{
enable: isLoadingError,
}}
- columnVisibility={{
- actions: !isPersonalLayoutMode,
- }}
skeleton={{
enable: isLoading,
rows: 3,
@@ -154,14 +131,12 @@ export const UserOrganisationsTable = () => {
- {!isPersonalLayoutMode && (
-
-
-
-
-
-
- )}
+
+
+
+
+
+
>
),
}}
diff --git a/apps/remix/app/entry.client.tsx b/apps/remix/app/entry.client.tsx
index 0ffb3602e..f76430676 100644
--- a/apps/remix/app/entry.client.tsx
+++ b/apps/remix/app/entry.client.tsx
@@ -31,6 +31,26 @@ function initPosthog() {
}
}
+/**
+ * Surfaces hydration recoveries (React 19 discards the server HTML and
+ * re-renders on the client instead of dying) so we can track how often
+ * extensions/early clicks interfere with hydration in the wild.
+ */
+function onRecoverableError(error: unknown, errorInfo: { componentStack?: string }) {
+ console.error('[hydration] recovered from error', error, errorInfo.componentStack);
+
+ if (extractPostHogConfig()) {
+ void import('posthog-js').then(({ default: posthog }) => {
+ if (posthog.__loaded) {
+ posthog.capture('$hydration_recoverable_error', {
+ message: error instanceof Error ? error.message : String(error),
+ componentStack: errorInfo.componentStack,
+ });
+ }
+ });
+ }
+}
+
async function main() {
const locale = detect(fromHtmlTag('lang')) || 'en';
@@ -44,6 +64,7 @@ async function main() {
,
+ { onRecoverableError },
);
});
diff --git a/apps/remix/app/root.tsx b/apps/remix/app/root.tsx
index a7c29b4be..75b37495c 100644
--- a/apps/remix/app/root.tsx
+++ b/apps/remix/app/root.tsx
@@ -1,5 +1,6 @@
import { getOptionalSession } from '@documenso/auth/server/lib/utils/get-session';
import { SessionProvider } from '@documenso/lib/client-only/providers/session';
+import { getBasePath } from '@documenso/lib/constants/app';
import { APP_I18N_OPTIONS, type SupportedLanguageCodes } from '@documenso/lib/constants/i18n';
import { createPublicEnv } from '@documenso/lib/utils/env';
import { extractLocaleData } from '@documenso/lib/utils/i18n';
@@ -20,7 +21,6 @@ import {
useMatches,
} from 'react-router';
import { PreventFlashOnWrongTheme, ThemeProvider, useTheme } from 'remix-themes';
-
import type { Route } from './+types/root';
import stylesheet from './app.css?url';
import { GenericErrorLayout } from './components/general/generic-error-layout';
@@ -68,6 +68,7 @@ export async function loader({ context, request }: Route.LoaderArgs) {
lang,
theme: getTheme(),
disableAnimations,
+ basePath: getBasePath(),
// Surface the per-request CSP nonce produced by `securityHeadersMiddleware` so all
// SSR-rendered