♻️ Prefetch subscription data + Upgrade framer motion (#1647)

This commit is contained in:
Luke Vella 2025-03-29 10:30:05 +00:00 committed by GitHub
parent 4dd2e69481
commit 8953cecd40
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 749 additions and 1394 deletions

View file

@ -11,6 +11,7 @@ import {
} from "@rallly/ui/dropdown-menu"; } from "@rallly/ui/dropdown-menu";
import { Analytics } from "@vercel/analytics/react"; import { Analytics } from "@vercel/analytics/react";
import { ChevronRightIcon, MenuIcon } from "lucide-react"; import { ChevronRightIcon, MenuIcon } from "lucide-react";
import { domAnimation, LazyMotion } from "motion/react";
import type { Viewport } from "next"; import type { Viewport } from "next";
import Image from "next/image"; import Image from "next/image";
import Link from "next/link"; import Link from "next/link";
@ -44,112 +45,118 @@ export default async function Root({
return ( return (
<html lang={locale} className={sans.className}> <html lang={locale} className={sans.className}>
<body> <body>
<I18nProvider locale={locale}> <LazyMotion features={domAnimation}>
<div className="mx-auto flex min-h-full w-full max-w-7xl flex-col space-y-12 p-4 sm:p-8"> <I18nProvider locale={locale}>
<header className="flex w-full items-center"> <div className="mx-auto flex min-h-full w-full max-w-7xl flex-col space-y-12 p-4 sm:p-8">
<div className="flex grow items-center gap-x-12"> <header className="flex w-full items-center">
<Link className="inline-block rounded" href="/"> <div className="flex grow items-center gap-x-12">
<Image <Link className="inline-block rounded" href="/">
src="/logo.svg" <Image
width={130} src="/logo.svg"
height={30} width={130}
alt="rallly.co" height={30}
/> alt="rallly.co"
</Link> />
<nav className="hidden items-center space-x-8 lg:flex"> </Link>
<NavLink href="https://support.rallly.co/workflow/create"> <nav className="hidden items-center space-x-8 lg:flex">
<Trans t={t} i18nKey="howItWorks" defaults="How it Works" /> <NavLink href="https://support.rallly.co/workflow/create">
</NavLink> <Trans
<NavLink href="/pricing"> t={t}
<Trans t={t} i18nKey="pricing" /> i18nKey="howItWorks"
</NavLink> defaults="How it Works"
<NavLink href="/blog"> />
<Trans t={t} i18nKey="blog" /> </NavLink>
</NavLink> <NavLink href="/pricing">
<NavLink href="https://support.rallly.co"> <Trans t={t} i18nKey="pricing" />
<Trans t={t} i18nKey="support" /> </NavLink>
</NavLink> <NavLink href="/blog">
</nav> <Trans t={t} i18nKey="blog" />
</div> </NavLink>
<div className="flex items-center gap-4 sm:gap-8"> <NavLink href="https://support.rallly.co">
<Link <Trans t={t} i18nKey="support" />
href={linkToApp("/login")} </NavLink>
className="hover:text-primary text-muted-foreground hidden rounded text-sm font-medium hover:no-underline hover:underline-offset-2 lg:inline-flex" </nav>
>
<Trans t={t} i18nKey="login" defaults="Login" />
</Link>
<Link
href={linkToApp()}
className="bg-primary hover:bg-primary-500 active:bg-primary-700 group inline-flex items-center gap-1 rounded-full py-1.5 pl-4 pr-3 text-sm font-medium text-white shadow-sm transition-transform"
>
<span>
<Trans t={t} i18nKey="goToApp" defaults="Go to app" />
</span>
<ChevronRightIcon className="inline-block size-4 transition-all group-active:translate-x-1" />
</Link>
<div className="flex items-center justify-center lg:hidden">
<DropdownMenu>
<DropdownMenuTrigger>
<MenuIcon className="size-6" />
</DropdownMenuTrigger>
<DropdownMenuContent align="end" sideOffset={16}>
<DropdownMenuItem asChild>
<Link
className="flex items-center gap-3 p-2 text-lg"
href="https://support.rallly.co/workflow/create"
>
<Trans
t={t}
i18nKey="howItWorks"
defaults="How it Works"
/>
</Link>
</DropdownMenuItem>
<DropdownMenuItem asChild>
<Link
className="flex items-center gap-3 p-2 text-lg"
href="/pricing"
>
<Trans t={t} i18nKey="pricing" defaults="Pricing" />
</Link>
</DropdownMenuItem>
<DropdownMenuItem asChild>
<Link
className="flex items-center gap-3 p-2 text-lg"
href="/blog"
>
<Trans t={t} i18nKey="blog" />
</Link>
</DropdownMenuItem>
<DropdownMenuItem asChild>
<Link
className="flex items-center gap-3 p-2 text-lg"
href="https://support.rallly.co"
>
<Trans t={t} i18nKey="support" />
</Link>
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem asChild>
<Link
className="flex items-center gap-3 p-2 text-lg"
href={linkToApp("/login")}
>
<Trans t={t} i18nKey="login" defaults="Login" />
</Link>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</div> </div>
</div> <div className="flex items-center gap-4 sm:gap-8">
</header> <Link
<section className="relative grow">{children}</section> href={linkToApp("/login")}
<hr className="border-transparent" /> className="hover:text-primary text-muted-foreground hidden rounded text-sm font-medium hover:no-underline hover:underline-offset-2 lg:inline-flex"
<footer> >
<Footer /> <Trans t={t} i18nKey="login" defaults="Login" />
</footer> </Link>
</div> <Link
</I18nProvider> href={linkToApp()}
className="bg-primary hover:bg-primary-500 active:bg-primary-700 group inline-flex items-center gap-1 rounded-full py-1.5 pl-4 pr-3 text-sm font-medium text-white shadow-sm transition-transform"
>
<span>
<Trans t={t} i18nKey="goToApp" defaults="Go to app" />
</span>
<ChevronRightIcon className="inline-block size-4 transition-all group-active:translate-x-1" />
</Link>
<div className="flex items-center justify-center lg:hidden">
<DropdownMenu>
<DropdownMenuTrigger>
<MenuIcon className="size-6" />
</DropdownMenuTrigger>
<DropdownMenuContent align="end" sideOffset={16}>
<DropdownMenuItem asChild>
<Link
className="flex items-center gap-3 p-2 text-lg"
href="https://support.rallly.co/workflow/create"
>
<Trans
t={t}
i18nKey="howItWorks"
defaults="How it Works"
/>
</Link>
</DropdownMenuItem>
<DropdownMenuItem asChild>
<Link
className="flex items-center gap-3 p-2 text-lg"
href="/pricing"
>
<Trans t={t} i18nKey="pricing" defaults="Pricing" />
</Link>
</DropdownMenuItem>
<DropdownMenuItem asChild>
<Link
className="flex items-center gap-3 p-2 text-lg"
href="/blog"
>
<Trans t={t} i18nKey="blog" />
</Link>
</DropdownMenuItem>
<DropdownMenuItem asChild>
<Link
className="flex items-center gap-3 p-2 text-lg"
href="https://support.rallly.co"
>
<Trans t={t} i18nKey="support" />
</Link>
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem asChild>
<Link
className="flex items-center gap-3 p-2 text-lg"
href={linkToApp("/login")}
>
<Trans t={t} i18nKey="login" defaults="Login" />
</Link>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</div>
</div>
</header>
<section className="relative grow">{children}</section>
<hr className="border-transparent" />
<footer>
<Footer />
</footer>
</div>
</I18nProvider>
</LazyMotion>
<Analytics /> <Analytics />
</body> </body>
</html> </html>

View file

@ -1,6 +1,6 @@
"use client"; "use client";
import { cn } from "@rallly/ui"; import { cn } from "@rallly/ui";
import { motion } from "framer-motion"; import * as m from "motion/react-m";
export const BonusItem = ({ export const BonusItem = ({
className, className,
@ -13,7 +13,7 @@ export const BonusItem = ({
icon: React.ReactNode; icon: React.ReactNode;
}>) => { }>) => {
return ( return (
<motion.div <m.div
transition={{ transition={{
delay, delay,
type: "spring", type: "spring",
@ -32,6 +32,6 @@ export const BonusItem = ({
</span> </span>
<div className="text-sm font-semibold">{children}</div> <div className="text-sm font-semibold">{children}</div>
</div> </div>
</motion.div> </m.div>
); );
}; };

View file

@ -2,8 +2,8 @@
import { cn } from "@rallly/ui"; import { cn } from "@rallly/ui";
import { Badge } from "@rallly/ui/badge"; import { Badge } from "@rallly/ui/badge";
import { Button } from "@rallly/ui/button"; import { Button } from "@rallly/ui/button";
import { motion } from "framer-motion";
import { ChevronRightIcon } from "lucide-react"; import { ChevronRightIcon } from "lucide-react";
import * as m from "motion/react-m";
import Image from "next/image"; import Image from "next/image";
import Link from "next/link"; import Link from "next/link";
import * as React from "react"; import * as React from "react";
@ -17,7 +17,7 @@ const Screenshot = () => {
return ( return (
<> <>
<motion.div <m.div
transition={{ transition={{
delay: 0.5, delay: 0.5,
type: "spring", type: "spring",
@ -42,8 +42,8 @@ const Screenshot = () => {
<span className="absolute left-1/2 top-full z-10 h-8 w-px -translate-x-1/2 bg-gray-800" /> <span className="absolute left-1/2 top-full z-10 h-8 w-px -translate-x-1/2 bg-gray-800" />
<span className="absolute -bottom-12 left-1/2 z-10 inline-block size-3 origin-right -translate-x-1/2 rounded-full bg-gray-800 ring-1 ring-gray-800 ring-offset-2" /> <span className="absolute -bottom-12 left-1/2 z-10 inline-block size-3 origin-right -translate-x-1/2 rounded-full bg-gray-800 ring-1 ring-gray-800 ring-offset-2" />
<span className="absolute -bottom-12 left-1/2 z-10 inline-block size-3 origin-right -translate-x-1/2 animate-ping rounded-full bg-gray-800 ring-1 ring-gray-800 ring-offset-2" /> <span className="absolute -bottom-12 left-1/2 z-10 inline-block size-3 origin-right -translate-x-1/2 animate-ping rounded-full bg-gray-800 ring-1 ring-gray-800 ring-offset-2" />
</motion.div> </m.div>
<motion.div <m.div
transition={{ transition={{
type: "spring", type: "spring",
duration: 1, duration: 1,
@ -67,7 +67,7 @@ const Screenshot = () => {
setIsLoaded(true); setIsLoaded(true);
}} }}
/> />
</motion.div> </m.div>
</> </>
); );
}; };

View file

@ -1,6 +1,6 @@
"use client"; "use client";
import { motion } from "framer-motion";
import { ArrowUpRight } from "lucide-react"; import { ArrowUpRight } from "lucide-react";
import * as m from "motion/react-m";
import Image from "next/image"; import Image from "next/image";
import Link from "next/link"; import Link from "next/link";
import React from "react"; import React from "react";
@ -157,7 +157,7 @@ const Mention = ({
delay?: number; delay?: number;
}>) => { }>) => {
return ( return (
<motion.div <m.div
transition={{ transition={{
delay, delay,
type: "spring", type: "spring",
@ -170,7 +170,7 @@ const Mention = ({
> >
<div className="flex items-start justify-between">{logo}</div> <div className="flex items-start justify-between">{logo}</div>
<p className="grow text-center text-base">{children}</p> <p className="grow text-center text-base">{children}</p>
</motion.div> </m.div>
); );
}; };
@ -257,7 +257,7 @@ export const MentionedBy = () => {
export const BigTestimonial = () => { export const BigTestimonial = () => {
return ( return (
<motion.div <m.div
transition={{ transition={{
duration: 1, duration: 1,
type: "spring", type: "spring",
@ -310,7 +310,7 @@ export const BigTestimonial = () => {
</div> </div>
</div> </div>
</div> </div>
</motion.div> </m.div>
); );
}; };

View file

@ -68,6 +68,7 @@
"lodash": "^4.17.21", "lodash": "^4.17.21",
"lucide-react": "^0.387.0", "lucide-react": "^0.387.0",
"micro": "^10.0.1", "micro": "^10.0.1",
"motion": "^12.6.2",
"nanoid": "^5.0.9", "nanoid": "^5.0.9",
"next-auth": "^5.0.0-beta.25", "next-auth": "^5.0.0-beta.25",
"php-serialize": "^4.1.1", "php-serialize": "^4.1.1",

View file

@ -1,15 +1,25 @@
import "tailwindcss/tailwind.css"; import "tailwindcss/tailwind.css";
import "../../style.css"; import "../../style.css";
import { PostHogProvider } from "@rallly/posthog/client";
import { Toaster } from "@rallly/ui/toaster"; import { Toaster } from "@rallly/ui/toaster";
import type { Metadata, Viewport } from "next"; import { TooltipProvider } from "@rallly/ui/tooltip";
import { dehydrate, Hydrate } from "@tanstack/react-query";
import { domAnimation, LazyMotion } from "motion/react";
import type { Viewport } from "next";
import { Inter } from "next/font/google"; import { Inter } from "next/font/google";
import { SessionProvider } from "next-auth/react"; import { SessionProvider } from "next-auth/react";
import React from "react"; import React from "react";
import { TimeZoneChangeDetector } from "@/app/[locale]/timezone-change-detector"; import { TimeZoneChangeDetector } from "@/app/[locale]/timezone-change-detector";
import { Providers } from "@/app/providers"; import { UserProvider } from "@/components/user-provider";
import { I18nProvider } from "@/i18n/client";
import { auth } from "@/next-auth"; import { auth } from "@/next-auth";
import { TRPCProvider } from "@/trpc/client/provider";
import { createSSRHelper } from "@/trpc/server/create-ssr-helper";
import { ConnectedDayjsProvider } from "@/utils/dayjs";
import { PostHogPageView } from "../posthog-page-view";
const inter = Inter({ const inter = Inter({
subsets: ["latin"], subsets: ["latin"],
@ -29,25 +39,35 @@ export default async function Root({
params: { locale: string }; params: { locale: string };
}) { }) {
const session = await auth(); const session = await auth();
const trpc = await createSSRHelper();
await trpc.user.subscription.prefetch();
return ( return (
<html lang={locale} className={inter.className}> <html lang={locale} className={inter.className}>
<body> <body>
<Toaster /> <Toaster />
<SessionProvider session={session}> <I18nProvider>
<Providers> <TRPCProvider>
{children} <Hydrate state={dehydrate(trpc.queryClient)}>
<TimeZoneChangeDetector /> <LazyMotion features={domAnimation}>
</Providers> <SessionProvider session={session}>
</SessionProvider> <PostHogProvider>
<PostHogPageView />
<TooltipProvider>
<UserProvider>
<ConnectedDayjsProvider>
{children}
<TimeZoneChangeDetector />
</ConnectedDayjsProvider>
</UserProvider>
</TooltipProvider>
</PostHogProvider>
</SessionProvider>
</LazyMotion>
</Hydrate>
</TRPCProvider>
</I18nProvider>
</body> </body>
</html> </html>
); );
} }
export const metadata: Metadata = {
title: {
template: "%s | Rallly",
default: "Rallly",
},
};

View file

@ -1,32 +0,0 @@
"use client";
import { PostHogProvider } from "@rallly/posthog/client";
import { TooltipProvider } from "@rallly/ui/tooltip";
import { domMax, LazyMotion } from "framer-motion";
import { UserProvider } from "@/components/user-provider";
import { I18nProvider } from "@/i18n/client";
import { TRPCProvider } from "@/trpc/client/provider";
import { ConnectedDayjsProvider } from "@/utils/dayjs";
import { PostHogPageView } from "./posthog-page-view";
export function Providers(props: { children: React.ReactNode }) {
return (
<LazyMotion features={domMax}>
<I18nProvider>
<PostHogProvider>
<PostHogPageView />
<TRPCProvider>
<TooltipProvider>
<UserProvider>
<ConnectedDayjsProvider>
{props.children}
</ConnectedDayjsProvider>
</UserProvider>
</TooltipProvider>
</TRPCProvider>
</PostHogProvider>
</I18nProvider>
</LazyMotion>
);
}

View file

@ -1,5 +1,6 @@
import { AnimatePresence, m } from "framer-motion";
import Cookies from "js-cookie"; import Cookies from "js-cookie";
import { AnimatePresence } from "motion/react";
import * as m from "motion/react-m";
import Link from "next/link"; import Link from "next/link";
import * as React from "react"; import * as React from "react";
import { createPortal } from "react-dom"; import { createPortal } from "react-dom";

View file

@ -5,8 +5,8 @@ import { Badge } from "@rallly/ui/badge";
import type { DialogProps } from "@rallly/ui/dialog"; import type { DialogProps } from "@rallly/ui/dialog";
import { Dialog, DialogContent, useDialog } from "@rallly/ui/dialog"; import { Dialog, DialogContent, useDialog } from "@rallly/ui/dialog";
import { RadioGroup, RadioGroupItem } from "@rallly/ui/radio-group"; import { RadioGroup, RadioGroupItem } from "@rallly/ui/radio-group";
import { m } from "framer-motion";
import { CheckIcon } from "lucide-react"; import { CheckIcon } from "lucide-react";
import * as m from "motion/react-m";
import Link from "next/link"; import Link from "next/link";
import React from "react"; import React from "react";

View file

@ -9,8 +9,9 @@ import {
SelectTrigger, SelectTrigger,
SelectValue, SelectValue,
} from "@rallly/ui/select"; } from "@rallly/ui/select";
import { AnimatePresence, m } from "framer-motion";
import { MoreHorizontalIcon, PlusIcon, UsersIcon } from "lucide-react"; import { MoreHorizontalIcon, PlusIcon, UsersIcon } from "lucide-react";
import { AnimatePresence } from "motion/react";
import * as m from "motion/react-m";
import * as React from "react"; import * as React from "react";
import smoothscroll from "smoothscroll-polyfill"; import smoothscroll from "smoothscroll-polyfill";

View file

@ -1,6 +1,7 @@
import { cn } from "@rallly/ui"; import { cn } from "@rallly/ui";
import { AnimatePresence, m } from "framer-motion";
import { User2Icon } from "lucide-react"; import { User2Icon } from "lucide-react";
import { AnimatePresence } from "motion/react";
import * as m from "motion/react-m";
import * as React from "react"; import * as React from "react";
import { usePrevious } from "react-use"; import { usePrevious } from "react-use";

View file

@ -1,3 +1,5 @@
"use client";
import type { TimeFormat } from "@rallly/database"; import type { TimeFormat } from "@rallly/database";
import dayjs from "dayjs"; import dayjs from "dayjs";
import advancedFormat from "dayjs/plugin/advancedFormat"; import advancedFormat from "dayjs/plugin/advancedFormat";

View file

@ -43,7 +43,6 @@
"@types/react": "^18.2.48", "@types/react": "^18.2.48",
"@types/react-dom": "^18.2.18", "@types/react-dom": "^18.2.18",
"dotenv-cli": "^7.1.0", "dotenv-cli": "^7.1.0",
"framer-motion": "^10.16.4",
"next": "^14.2.25", "next": "^14.2.25",
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"prettier": "^3.3.3", "prettier": "^3.3.3",

View file

@ -19,7 +19,7 @@
"@react-email/render": "^0.0.12", "@react-email/render": "^0.0.12",
"@vercel/functions": "*", "@vercel/functions": "*",
"nodemailer": "^6.9.9", "nodemailer": "^6.9.9",
"react-email": "^2.0.0" "react-email": "^4.0.2"
}, },
"devDependencies": { "devDependencies": {
"@rallly/tailwind-config": "*", "@rallly/tailwind-config": "*",

View file

@ -1,2 +1,4 @@
"use client";
export { PostHogProvider } from "./provider"; export { PostHogProvider } from "./provider";
export { usePostHog } from "posthog-js/react"; export { usePostHog } from "posthog-js/react";

1799
yarn.lock

File diff suppressed because it is too large Load diff