diff --git a/next.config.mjs b/next.config.mjs
index 1a67b9f..11f2e90 100644
--- a/next.config.mjs
+++ b/next.config.mjs
@@ -1,6 +1,9 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
output: 'standalone',
+ experimental: {
+ globalNotFound: true,
+ },
turbopack: {
root: process.cwd(),
},
diff --git a/src/app/global-not-found.module.css b/src/app/global-not-found.module.css
new file mode 100644
index 0000000..ea401d7
--- /dev/null
+++ b/src/app/global-not-found.module.css
@@ -0,0 +1,137 @@
+.page {
+ display: grid;
+ min-height: 100svh;
+ padding: var(--space-6) var(--layout-page-gutter);
+ place-items: center;
+ overflow: hidden;
+ background: var(--bg-page);
+ color: var(--text-primary);
+}
+
+.content {
+ display: flex;
+ width: min(100%, 36rem);
+ align-items: center;
+ flex-direction: column;
+ text-align: center;
+}
+
+.persian {
+ display: none;
+}
+
+:global(html[lang='fa']) .english {
+ display: none;
+}
+
+:global(html[lang='fa']) .persian {
+ display: flex;
+}
+
+.code {
+ color: color-mix(in srgb, var(--accent-default) 38%, var(--bg-page));
+ font-size: clamp(6rem, 22vw, 12rem);
+ font-weight: 850;
+ letter-spacing: -0.08em;
+ line-height: 0.82;
+ user-select: none;
+}
+
+:global(html[dir='rtl']) .code {
+ letter-spacing: 0;
+}
+
+.divider {
+ width: 3rem;
+ height: 0.2rem;
+ margin-block: var(--space-7) var(--space-5);
+ border-radius: var(--radius-pill);
+ background: var(--accent-default);
+}
+
+.content h1 {
+ max-width: 18ch;
+ color: var(--text-primary);
+ font-size: clamp(2rem, 5vw, 3rem);
+ font-weight: 780;
+ letter-spacing: -0.04em;
+ line-height: 1.12;
+ text-wrap: balance;
+}
+
+:global(html[dir='rtl']) .content h1 {
+ letter-spacing: 0;
+}
+
+.description {
+ max-width: 34rem;
+ margin-top: var(--space-4);
+ color: var(--text-secondary);
+ font-size: var(--font-size-body-large);
+ line-height: var(--line-height-body-large);
+ text-wrap: pretty;
+}
+
+.homeLink {
+ display: inline-flex;
+ min-height: var(--size-button-height);
+ align-items: center;
+ justify-content: center;
+ gap: var(--space-2);
+ margin-top: var(--space-7);
+ padding-inline: var(--space-5);
+ border: 1px solid transparent;
+ border-radius: var(--radius-pill);
+ background: var(--action-primary-bg);
+ color: var(--action-primary-fg);
+ font-size: var(--font-size-button);
+ font-weight: 700;
+ line-height: var(--line-height-button);
+ transition:
+ background-color var(--motion-duration-fast) ease,
+ box-shadow var(--motion-duration-fast) ease,
+ transform var(--motion-duration-fast) var(--motion-ease-out);
+}
+
+.homeLink svg {
+ width: var(--size-icon-md);
+ height: var(--size-icon-md);
+}
+
+.homeLink:active {
+ transform: scale(0.97);
+}
+
+@media (hover: hover) and (pointer: fine) {
+ .homeLink:hover {
+ background: var(--action-primary-hover);
+ box-shadow: 0 0.25rem 0.75rem var(--shadow-color);
+ transform: translateY(-1px);
+ }
+}
+
+@media (max-width: 650px) {
+ .page {
+ padding-block: var(--space-5);
+ }
+
+ .divider {
+ margin-block: var(--space-6) var(--space-4);
+ }
+
+ .description {
+ font-size: var(--font-size-body-default);
+ line-height: var(--line-height-body-default);
+ }
+}
+
+@media (prefers-reduced-motion: reduce) {
+ .homeLink {
+ transition: background-color 120ms ease, box-shadow 120ms ease;
+ }
+
+ .homeLink:hover,
+ .homeLink:active {
+ transform: none;
+ }
+}
diff --git a/src/app/global-not-found.tsx b/src/app/global-not-found.tsx
new file mode 100644
index 0000000..707768f
--- /dev/null
+++ b/src/app/global-not-found.tsx
@@ -0,0 +1,72 @@
+import type { Metadata } from 'next';
+import localFont from 'next/font/local';
+import Link from 'next/link';
+import { ArrowLeft, ArrowRight } from 'lucide-react';
+import { messagesByLocale, type Locale } from '@/i18n/content';
+import '@/styles/globals.css';
+import styles from './global-not-found.module.css';
+
+const themeAndLocaleScript = `
+ try {
+ const root = document.documentElement;
+ const isPersian = /^\\/fa(?:\\/|$)/.test(window.location.pathname);
+ root.lang = isPersian ? 'fa' : 'en';
+ root.dir = isPersian ? 'rtl' : 'ltr';
+ const savedTheme = localStorage.getItem('portfolio-theme');
+ root.dataset.theme = savedTheme === 'dark' ? 'dark' : 'light';
+ } catch {}
+`;
+
+const iranYekan = localFont({
+ src: '../../public/fonts/IRANYekanXVF.woff2',
+ variable: '--font-body',
+ weight: '100 1000',
+ style: 'normal',
+ display: 'swap',
+ preload: false,
+ fallback: ['-apple-system', 'BlinkMacSystemFont', 'Segoe UI', 'sans-serif'],
+});
+
+export const metadata: Metadata = {
+ title: '404 | Amirhossein Khalili',
+ description: 'The requested page could not be found.',
+};
+
+function NotFoundContent({ locale }: { locale: Locale }) {
+ const copy = messagesByLocale[locale].notFound;
+ const isRtl = locale === 'fa';
+
+ return (
+ {copy.description}{copy.title}
+