diff --git a/next-env.d.ts b/next-env.d.ts
index ce4e94a..a419cbe 100644
--- a/next-env.d.ts
+++ b/next-env.d.ts
@@ -1,7 +1,7 @@
///
///
-import "./.next/types/routes.d.ts";
-import "./.next/types/root-params.d.ts";
+import "./.next/dev/types/routes.d.ts";
+import "./.next/dev/types/root-params.d.ts";
// NOTE: This file should not be edited
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
diff --git a/src/app/HomePage.tsx b/src/app/HomePage.tsx
index 9aba633..649f526 100644
--- a/src/app/HomePage.tsx
+++ b/src/app/HomePage.tsx
@@ -1,23 +1,33 @@
-'use client';
-import { Suspense } from 'react';
-import dynamic from 'next/dynamic';
-import { Hero } from '../sections/Hero';
-import { Problem } from '../sections/Problem';
-import { Machinery } from '../sections/Machinery';
-import { Showcase } from '../sections/Showcase';
-import { PlatformAdvantage } from '../sections/PlatformAdvantage';
-import { Services } from '../sections/Services';
-import { Testimonial } from '../sections/Testimonial';
-import { Anatomy } from '../sections/Anatomy';
-import { Process } from '../sections/Process';
-import { Principles } from '../sections/Principles';
-import { FAQ } from '../sections/FAQ';
-import { CtaBanner } from '../sections/CtaBanner';
-import { ContactSection } from '../sections/ContactSection';
+"use client";
+import { Suspense } from "react";
+import dynamic from "next/dynamic";
+import { Hero } from "../sections/Hero";
+import { Problem } from "../sections/Problem";
+import { Machinery } from "../sections/Machinery";
+import { Showcase } from "../sections/Showcase";
+import { PlatformAdvantage } from "../sections/PlatformAdvantage";
+import { Services } from "../sections/Services";
+import { Testimonial } from "../sections/Testimonial";
+import { Anatomy } from "../sections/Anatomy";
+import { Process } from "../sections/Process";
+import { Principles } from "../sections/Principles";
+import { FAQ } from "../sections/FAQ";
+import { CtaBanner } from "../sections/CtaBanner";
+import { ContactSection } from "../sections/ContactSection";
const Clients = dynamic(
- () => import('../sections/Clients').then(m => ({ default: m.Clients })),
- { ssr: false }
+ () => import("../sections/Clients").then((m) => ({ default: m.Clients })),
+ { ssr: false },
+);
+
+const Partners = dynamic(
+ () => import("../sections/Partners").then((m) => ({ default: m.Partners })),
+ { ssr: false },
+);
+
+const Portfolio = dynamic(
+ () => import("../sections/Portfolio").then((m) => ({ default: m.Portfolio })),
+ { ssr: false },
);
export function HomePage() {
@@ -30,6 +40,9 @@ export function HomePage() {
+
+
+
@@ -37,6 +50,9 @@ export function HomePage() {
+
+
+
diff --git a/src/app/portafolio/PortafolioPage.tsx b/src/app/portafolio/PortafolioPage.tsx
new file mode 100644
index 0000000..b09f81c
--- /dev/null
+++ b/src/app/portafolio/PortafolioPage.tsx
@@ -0,0 +1,148 @@
+'use client';
+import { useState, useEffect } from 'react';
+import { motion } from 'framer-motion';
+import Loader from '../../components/Loader';
+import { usePortfolio } from '../../services/portfolio';
+import { assetUrl } from '../../services/api';
+
+const bg = '#f9f9f7';
+const text = '#0a0a0a';
+const sub = '#6a6866';
+const border = 'rgba(0,0,0,0.08)';
+const card = '#ffffff';
+const tagBg = 'rgba(0,0,0,0.05)';
+
+function PortafolioContent() {
+ const { data, isLoading } = usePortfolio();
+ const projects = data ?? [];
+
+ if (isLoading) return ;
+
+ return (
+
+ {/* Hero */}
+
+
+
+
+ Casos de éxito
+
+
+ Construimos el sistema.{' '}
+ Tú operas el negocio.
+
+
+ Proyectos reales, resultados medibles. Cada implementación parte de entender la operación antes de escribir una sola línea de código.
+
+
+
+
+
+ {/* Grid */}
+
+
+ {projects.length === 0 ? (
+
Próximamente casos de éxito.
+ ) : (
+
+ {projects.map((p, i) => {
+ const cover = p.images.find((img) => img.isCover) ?? p.images.sort((a, b) => a.order - b.order)[0];
+ return (
+
+ {/* Cover */}
+
+ {cover ? (
+
})
+ ) : (
+
+ )}
+
+
+ {/* Content */}
+
+ {p.clientCompanyName && (
+
+ {p.clientCompanyName}
+
+ )}
+
+ {p.title}
+
+ {p.publicSummary && (
+
+ {p.publicSummary}
+
+ )}
+ {p.technologies.length > 0 && (
+
+ {p.technologies.map((t) => (
+
+ {t.name}
+
+ ))}
+
+ )}
+
+
+ );
+ })}
+
+ )}
+
+
+
+ );
+}
+
+export function PortafolioPage() {
+ const [mounted, setMounted] = useState(false);
+ useEffect(() => setMounted(true), []);
+ if (!mounted) return (
+
+
+
+ );
+ return ;
+}
diff --git a/src/app/portafolio/loading.tsx b/src/app/portafolio/loading.tsx
new file mode 100644
index 0000000..73923f6
--- /dev/null
+++ b/src/app/portafolio/loading.tsx
@@ -0,0 +1,9 @@
+import Loader from '../../components/Loader';
+
+export default function Loading() {
+ return (
+
+
+
+ );
+}
diff --git a/src/app/portafolio/page.tsx b/src/app/portafolio/page.tsx
new file mode 100644
index 0000000..ecebea2
--- /dev/null
+++ b/src/app/portafolio/page.tsx
@@ -0,0 +1,12 @@
+import type { Metadata } from 'next';
+import { PortafolioPage } from './PortafolioPage';
+
+export const metadata: Metadata = {
+ title: 'Portafolio | Rynext Technologies',
+ description: 'Casos de éxito reales. Proyectos que transformaron operaciones empresariales con software diseñado a medida.',
+ alternates: { canonical: 'https://rynext.com.mx/portafolio' },
+};
+
+export default function Page() {
+ return ;
+}
diff --git a/src/components/Navbar.tsx b/src/components/Navbar.tsx
index 2cd304c..26f678f 100644
--- a/src/components/Navbar.tsx
+++ b/src/components/Navbar.tsx
@@ -10,7 +10,8 @@ import { pageLinks } from '../data/navigationData';
export const Navbar = () => {
const [scrolled, setScrolled] = useState(false);
const [menuOpen, setMenuOpen] = useState(false);
- const pathname = usePathname();
+ const rawPathname = usePathname();
+ const pathname = rawPathname?.replace(/\/$/, '') || '/';
const scrollToContact = () => {
setMenuOpen(false);
@@ -66,7 +67,7 @@ export const Navbar = () => {
{/* Desktop nav */}