fix(404): add redirects for broken URLs and custom not-found page
Some checks failed
Build and Deploy / build (push) Has been cancelled
Some checks failed
Build and Deploy / build (push) Has been cancelled
- Add permanent redirects for /products/manoon to /products - Strip malformed /contact suffix from product URLs - Create custom branded 404 page with product navigation - Add NotFound translations for en and sr locales
This commit is contained in:
@@ -5,6 +5,32 @@ const withNextIntl = createNextIntlPlugin();
|
|||||||
|
|
||||||
const nextConfig: NextConfig = {
|
const nextConfig: NextConfig = {
|
||||||
output: 'standalone',
|
output: 'standalone',
|
||||||
|
async redirects() {
|
||||||
|
return [
|
||||||
|
// Fix malformed URLs with /contact appended to product slugs
|
||||||
|
{
|
||||||
|
source: '/:locale(en|sr)/products/:slug*/contact',
|
||||||
|
destination: '/:locale/products/:slug*',
|
||||||
|
permanent: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
source: '/products/:slug*/contact',
|
||||||
|
destination: '/products/:slug*',
|
||||||
|
permanent: true,
|
||||||
|
},
|
||||||
|
// Redirect old/removed product "manoon" to products listing
|
||||||
|
{
|
||||||
|
source: '/:locale(en|sr)/products/manoon',
|
||||||
|
destination: '/:locale/products',
|
||||||
|
permanent: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
source: '/products/manoon',
|
||||||
|
destination: '/products',
|
||||||
|
permanent: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
},
|
||||||
async rewrites() {
|
async rewrites() {
|
||||||
const rybbitHost = process.env.NEXT_PUBLIC_RYBBIT_HOST || "https://rybbit.nodecrew.me";
|
const rybbitHost = process.env.NEXT_PUBLIC_RYBBIT_HOST || "https://rybbit.nodecrew.me";
|
||||||
return [
|
return [
|
||||||
|
|||||||
68
src/app/[locale]/not-found.tsx
Normal file
68
src/app/[locale]/not-found.tsx
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { useTranslations, useLocale } from "next-intl";
|
||||||
|
import Header from "@/components/layout/Header";
|
||||||
|
import Footer from "@/components/layout/Footer";
|
||||||
|
import Link from "next/link";
|
||||||
|
import { Home, Search, Package } from "lucide-react";
|
||||||
|
|
||||||
|
export default function NotFoundPage() {
|
||||||
|
const t = useTranslations("NotFound");
|
||||||
|
const locale = useLocale();
|
||||||
|
const basePath = `/${locale}`;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Header locale={locale} />
|
||||||
|
<main className="min-h-screen bg-white">
|
||||||
|
<div className="pt-[180px] lg:pt-[200px] pb-20 px-4">
|
||||||
|
<div className="max-w-2xl mx-auto text-center">
|
||||||
|
{/* 404 Code */}
|
||||||
|
<div className="text-[120px] lg:text-[180px] font-light text-black/5 leading-none select-none mb-4">
|
||||||
|
404
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h1 className="text-2xl lg:text-3xl font-medium mb-4">
|
||||||
|
{t("title")}
|
||||||
|
</h1>
|
||||||
|
<p className="text-[#666666] mb-10 max-w-md mx-auto">
|
||||||
|
{t("description")}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
{/* Quick Links */}
|
||||||
|
<div className="flex flex-col sm:flex-row items-center justify-center gap-4 mb-12">
|
||||||
|
<Link
|
||||||
|
href={`${basePath}/products`}
|
||||||
|
className="flex items-center gap-2 px-6 py-3 bg-black text-white text-sm uppercase tracking-[0.1em] hover:bg-[#333333] transition-colors w-full sm:w-auto justify-center"
|
||||||
|
>
|
||||||
|
<Package className="w-4 h-4" />
|
||||||
|
{t("browseProducts")}
|
||||||
|
</Link>
|
||||||
|
<Link
|
||||||
|
href={basePath}
|
||||||
|
className="flex items-center gap-2 px-6 py-3 border border-black text-black text-sm uppercase tracking-[0.1em] hover:bg-black hover:text-white transition-colors w-full sm:w-auto justify-center"
|
||||||
|
>
|
||||||
|
<Home className="w-4 h-4" />
|
||||||
|
{t("goHome")}
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Search Suggestion */}
|
||||||
|
<div className="p-6 bg-[#f8f8f8] rounded-sm">
|
||||||
|
<div className="flex items-center gap-3 mb-3 text-[#666666]">
|
||||||
|
<Search className="w-5 h-5" />
|
||||||
|
<span className="text-sm font-medium uppercase tracking-[0.1em]">
|
||||||
|
{t("lookingFor")}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<p className="text-sm text-[#666666]">
|
||||||
|
{t("searchSuggestion")}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
<Footer locale={locale} />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -464,5 +464,13 @@
|
|||||||
"description": "Pay via bank transfer",
|
"description": "Pay via bank transfer",
|
||||||
"comingSoon": "Coming soon"
|
"comingSoon": "Coming soon"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"NotFound": {
|
||||||
|
"title": "Page Not Found",
|
||||||
|
"description": "The page you're looking for doesn't exist or has been moved.",
|
||||||
|
"browseProducts": "Browse Products",
|
||||||
|
"goHome": "Go Home",
|
||||||
|
"lookingFor": "Can't find what you're looking for?",
|
||||||
|
"searchSuggestion": "Try browsing our product collection or contact us for assistance."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -463,5 +463,13 @@
|
|||||||
"description": "Platite putem bankovnog transfera",
|
"description": "Platite putem bankovnog transfera",
|
||||||
"comingSoon": "Uskoro dostupno"
|
"comingSoon": "Uskoro dostupno"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"NotFound": {
|
||||||
|
"title": "Stranica Nije Pronađena",
|
||||||
|
"description": "Stranica koju tražite ne postoji ili je premeštena.",
|
||||||
|
"browseProducts": "Pregledaj Proizvode",
|
||||||
|
"goHome": "Početna Strana",
|
||||||
|
"lookingFor": "Ne možete da pronađete ono što tražite?",
|
||||||
|
"searchSuggestion": "Pokušajte da pregledate našu kolekciju proizvoda ili nas kontaktirajte za pomoć."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user