diff --git a/apps/remix/app/entry.client.tsx b/apps/remix/app/entry.client.tsx
index a60ac5063..42996b5ec 100644
--- a/apps/remix/app/entry.client.tsx
+++ b/apps/remix/app/entry.client.tsx
@@ -5,10 +5,17 @@ import { detect, fromHtmlTag } from '@lingui/detect-locale';
import { I18nProvider } from '@lingui/react';
import { hydrateRoot } from 'react-dom/client';
import { HydratedRouter } from 'react-router/dom';
+import { Theme, ThemeProvider } from 'remix-themes';
+import { match } from 'ts-pattern';
import { dynamicActivate } from '@documenso/lib/utils/i18n';
async function main() {
+ const theme = match(document.documentElement.getAttribute('data-theme'))
+ .with('dark', () => Theme.DARK)
+ .with('light', () => Theme.LIGHT)
+ .otherwise(() => null);
+
const locale = detect(fromHtmlTag('lang')) || 'en';
await dynamicActivate(locale);
@@ -18,7 +25,9 @@ async function main() {
document,
-
+
+
+
,
);
diff --git a/apps/remix/app/entry.server.tsx b/apps/remix/app/entry.server.tsx
index 6caeba746..6250bff85 100644
--- a/apps/remix/app/entry.server.tsx
+++ b/apps/remix/app/entry.server.tsx
@@ -7,11 +7,13 @@ import type { RenderToPipeableStreamOptions } from 'react-dom/server';
import { renderToPipeableStream } from 'react-dom/server';
import type { AppLoadContext, EntryContext } from 'react-router';
import { ServerRouter } from 'react-router';
+import { ThemeProvider } from 'remix-themes';
import { APP_I18N_OPTIONS } from '@documenso/lib/constants/i18n';
import { dynamicActivate, extractLocaleData } from '@documenso/lib/utils/i18n';
import { langCookie } from './storage/lang-cookie.server';
+import { themeSessionResolver } from './storage/theme-session.server';
export const streamTimeout = 5_000;
@@ -30,6 +32,10 @@ export default async function handleRequest(
await dynamicActivate(language);
+ const { getTheme } = await themeSessionResolver(request);
+
+ const theme = getTheme();
+
return new Promise((resolve, reject) => {
let shellRendered = false;
const userAgent = request.headers.get('user-agent');
@@ -41,7 +47,9 @@ export default async function handleRequest(
const { pipe, abort } = renderToPipeableStream(
-
+
+
+
,
{
[readyOption]() {
diff --git a/apps/remix/app/root.tsx b/apps/remix/app/root.tsx
index 2f1fc07d2..a741ee00a 100644
--- a/apps/remix/app/root.tsx
+++ b/apps/remix/app/root.tsx
@@ -12,7 +12,7 @@ import {
useLoaderData,
useLocation,
} from 'react-router';
-import { PreventFlashOnWrongTheme, ThemeProvider, useTheme } from 'remix-themes';
+import { PreventFlashOnWrongTheme, useTheme } from 'remix-themes';
import { getOptionalSession } from '@documenso/auth/server/lib/utils/get-session';
import { SessionProvider } from '@documenso/lib/client-only/providers/session';
@@ -105,13 +105,21 @@ export async function loader({ request }: Route.LoaderArgs) {
);
}
-export function App() {
+export function Layout({ children }: { children: React.ReactNode }) {
const { publicEnv, lang, session, ...data } = useLoaderData() || {};
const [theme] = useTheme();
+ const location = useLocation();
+
+ useEffect(() => {
+ if (env('NODE_ENV') === 'production') {
+ trackPageview();
+ }
+ }, [location.pathname]);
+
return (
-
+
@@ -136,7 +144,8 @@ export function App() {
-
+ {children}
+
@@ -157,27 +166,8 @@ export function App() {
);
}
-/**
- * We have this weird setup with:
- * - No root layout
- * - AppWithTheme
- *
- * To handle remix-themes.
- */
-export default function AppWithTheme({ loaderData }: Route.ComponentProps) {
- const location = useLocation();
-
- useEffect(() => {
- if (env('NODE_ENV') === 'production') {
- trackPageview();
- }
- }, [location.pathname]);
-
- return (
-
-
-
- );
+export default function App() {
+ return ;
}
export function ErrorBoundary({ error }: Route.ErrorBoundaryProps) {
diff --git a/packages/lib/utils/env.ts b/packages/lib/utils/env.ts
index 0a9179c5a..26f90f0cc 100644
--- a/packages/lib/utils/env.ts
+++ b/packages/lib/utils/env.ts
@@ -13,7 +13,7 @@ export const env = (variable: EnvironmentVariable | (string & object)): string |
return window.__ENV__[variable];
}
- return process?.env?.[variable];
+ return typeof process !== 'undefined' ? process?.env?.[variable] : undefined;
};
export const createPublicEnv = () =>