Files
Reactive-Resume/src/routes/__root.tsx
T
Amruth Pillai 192880e416 use vite+
2026-03-18 22:03:24 +01:00

146 lines
5.0 KiB
TypeScript

import "@fontsource-variable/ibm-plex-sans";
import "@phosphor-icons/web/regular/style.css";
import type { QueryClient } from "@tanstack/react-query";
import { i18n } from "@lingui/core";
import { I18nProvider } from "@lingui/react";
import { IconContext } from "@phosphor-icons/react";
import { createRootRouteWithContext, HeadContent, Scripts } from "@tanstack/react-router";
import { MotionConfig } from "motion/react";
import type { AuthSession } from "@/integrations/auth/types";
import type { FeatureFlags } from "@/integrations/orpc/services/flags";
import { CommandPalette } from "@/components/command-palette";
import { BreakpointIndicator } from "@/components/layout/breakpoint-indicator";
import { ThemeProvider } from "@/components/theme/provider";
import { Toaster } from "@/components/ui/sonner";
import { TooltipProvider } from "@/components/ui/tooltip";
import { DialogManager } from "@/dialogs/manager";
import { ConfirmDialogProvider } from "@/hooks/use-confirm";
import { PromptDialogProvider } from "@/hooks/use-prompt";
import { getSession } from "@/integrations/auth/functions";
import { client, type orpc } from "@/integrations/orpc/client";
import { getLocale, isRTL, type Locale, loadLocale } from "@/utils/locale";
import { getTheme, type Theme } from "@/utils/theme";
import appCss from "../styles/globals.css?url";
type RouterContext = {
theme: Theme;
locale: Locale;
orpc: typeof orpc;
queryClient: QueryClient;
session: AuthSession | null;
flags: FeatureFlags;
};
const appName = "Reactive Resume";
const tagline = "A free and open-source resume builder";
const title = `${appName}${tagline}`;
const description =
"Reactive Resume is a free and open-source resume builder that simplifies the process of creating, updating, and sharing your resume.";
await loadLocale(await getLocale());
export const Route = createRootRouteWithContext<RouterContext>()({
shellComponent: RootDocument,
head: () => {
const appUrl = process.env.APP_URL ?? "https://rxresu.me/";
return {
links: [
{ rel: "stylesheet", href: appCss },
// Icons
{ rel: "icon", href: "/favicon.ico", type: "image/x-icon", sizes: "128x128" },
{ rel: "icon", href: "/favicon.svg", type: "image/svg+xml", sizes: "256x256 any" },
{ rel: "apple-touch-icon", href: "/apple-touch-icon-180x180.png", type: "image/png", sizes: "180x180 any" },
// Manifest
{ rel: "manifest", href: "/manifest.webmanifest", crossOrigin: "use-credentials" },
],
meta: [
{ title },
{ charSet: "UTF-8" },
{ name: "description", content: description },
{ name: "viewport", content: "width=device-width, initial-scale=1" },
// Twitter Tags
{ property: "twitter:image", content: `${appUrl}/opengraph/banner.jpg` },
{ property: "twitter:card", content: "summary_large_image" },
{ property: "twitter:title", content: title },
{ property: "twitter:description", content: description },
// OpenGraph Tags
{ property: "og:image", content: `${appUrl}/opengraph/banner.jpg` },
{ property: "og:site_name", content: appName },
{ property: "og:title", content: title },
{ property: "og:description", content: description },
{ property: "og:url", content: appUrl },
],
// Register service worker via script tag
scripts: [
{
children: `
if('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('/sw.js', { scope: '/' })
})
}
`,
},
],
};
},
beforeLoad: async () => {
const [theme, locale, session, flags] = await Promise.all([
getTheme(),
getLocale(),
getSession(),
client.flags.get(),
]);
return { theme, locale, session, flags };
},
});
type Props = {
children: React.ReactNode;
};
function RootDocument({ children }: Props) {
const { theme, locale } = Route.useRouteContext();
const dir = isRTL(locale) ? "rtl" : "ltr";
return (
<html suppressHydrationWarning dir={dir} lang={locale} className={theme}>
<head>
<HeadContent />
</head>
<body>
<MotionConfig reducedMotion="user">
<I18nProvider i18n={i18n}>
<IconContext.Provider value={{ size: 16, weight: "regular" }}>
<ThemeProvider theme={theme}>
<TooltipProvider>
<ConfirmDialogProvider>
<PromptDialogProvider>
{children}
<DialogManager />
<CommandPalette />
<Toaster richColors position="bottom-right" />
{import.meta.env.DEV && <BreakpointIndicator />}
</PromptDialogProvider>
</ConfirmDialogProvider>
</TooltipProvider>
</ThemeProvider>
</IconContext.Provider>
</I18nProvider>
</MotionConfig>
<Scripts />
</body>
</html>
);
}