diff --git a/package.json b/package.json
index e6537d8..67b3b62 100644
--- a/package.json
+++ b/package.json
@@ -41,6 +41,7 @@
"cmdk": "^1.1.1",
"date-fns": "^3.6.0",
"embla-carousel-react": "^8.6.0",
+ "framer-motion": "^12.27.0",
"input-otp": "^1.4.2",
"lucide-react": "^0.511.0",
"next": "15.3.8",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index f1383c3..8033b56 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -104,6 +104,9 @@ importers:
embla-carousel-react:
specifier: ^8.6.0
version: 8.6.0(react@19.2.1)
+ framer-motion:
+ specifier: ^12.27.0
+ version: 12.27.0(react-dom@19.2.1(react@19.2.1))(react@19.2.1)
input-otp:
specifier: ^1.4.2
version: 1.4.2(react-dom@19.2.1(react@19.2.1))(react@19.2.1)
@@ -1451,6 +1454,20 @@ packages:
resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==}
engines: {node: '>=14'}
+ framer-motion@12.27.0:
+ resolution: {integrity: sha512-gJtqOKEDJH/jrn0PpsWp64gdOjBvGX8hY6TWstxjDot/85daIEtJHl1UsiwHSXiYmJF2QXUoXP6/3gGw5xY2YA==}
+ peerDependencies:
+ '@emotion/is-prop-valid': '*'
+ react: ^18.0.0 || ^19.0.0
+ react-dom: ^18.0.0 || ^19.0.0
+ peerDependenciesMeta:
+ '@emotion/is-prop-valid':
+ optional: true
+ react:
+ optional: true
+ react-dom:
+ optional: true
+
fsevents@2.3.3:
resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
@@ -1605,6 +1622,12 @@ packages:
resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==}
engines: {node: '>=16 || 14 >=14.17'}
+ motion-dom@12.27.0:
+ resolution: {integrity: sha512-oDjl0WoAsWIWKl3GCDxmh7GITrNjmLX+w5+jwk4+pzLu3VnFvsOv2E6+xCXeH72O65xlXsr84/otiOYQKW/nQA==}
+
+ motion-utils@12.24.10:
+ resolution: {integrity: sha512-x5TFgkCIP4pPsRLpKoI86jv/q8t8FQOiM/0E8QKBzfMozWHfkKap2gA1hOki+B5g3IsBNpxbUnfOum1+dgvYww==}
+
mz@2.7.0:
resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==}
@@ -3361,6 +3384,15 @@ snapshots:
cross-spawn: 7.0.6
signal-exit: 4.1.0
+ framer-motion@12.27.0(react-dom@19.2.1(react@19.2.1))(react@19.2.1):
+ dependencies:
+ motion-dom: 12.27.0
+ motion-utils: 12.24.10
+ tslib: 2.8.1
+ optionalDependencies:
+ react: 19.2.1
+ react-dom: 19.2.1(react@19.2.1)
+
fsevents@2.3.3:
optional: true
@@ -3488,6 +3520,12 @@ snapshots:
minipass@7.1.2: {}
+ motion-dom@12.27.0:
+ dependencies:
+ motion-utils: 12.24.10
+
+ motion-utils@12.24.10: {}
+
mz@2.7.0:
dependencies:
any-promise: 1.3.0
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
index 3769a1f..c61acbf 100644
--- a/src/app/layout.tsx
+++ b/src/app/layout.tsx
@@ -4,6 +4,7 @@ import "./globals.css";
import { ThemeProvider } from "@/components/theme-provider";
import { Toaster } from "@/components/ui/sonner";
import { Footer } from "@/components/footer";
+import { PageTransitionProvider } from "@/components/page-transition-provider";
const geistSans = Geist({
variable: "--font-geist-sans",
@@ -36,7 +37,9 @@ export default function RootLayout({
enableSystem
disableTransitionOnChange
>
- {children}
+
+ {children}
+
diff --git a/src/components/page-transition-provider.tsx b/src/components/page-transition-provider.tsx
new file mode 100644
index 0000000..dd83819
--- /dev/null
+++ b/src/components/page-transition-provider.tsx
@@ -0,0 +1,34 @@
+"use client";
+
+import { AnimatePresence, motion } from "framer-motion";
+import { usePathname } from "next/navigation";
+import React from "react";
+
+export function PageTransitionProvider({ children }: { children: React.ReactNode }) {
+ const pathname = usePathname();
+
+ return (
+
+
+ {children}
+
+ {/* Exit Animation Overlay */}
+
+
+ {/* Enter Animation Overlay */}
+
+
+
+ );
+}
\ No newline at end of file