perf: optimize portfolio runtime delivery
Some checks failed
Test and deploy / Verify production build (push) Has been cancelled
Test and deploy / Deploy production (push) Has been cancelled

Replace the blocking asset loader with progressive rendering, defer expensive media and Three.js work, and reduce hydration and animation costs. Move deployment from a static Nginx export to the standalone Next.js runtime with optimized dynamic images.
This commit is contained in:
2026-09-09 12:43:37 +03:30
parent 9143ba8504
commit f34bea05cd
63 changed files with 1296 additions and 1048 deletions

View File

@@ -1,7 +1,4 @@
'use client';
import { useState } from 'react';
import type { ContactItem, FooterContactId } from './IsoTypes';
import type { ContactItem } from './IsoTypes';
import IsometricScene from './IsometricScene';
import {
MailIcon,
@@ -12,6 +9,7 @@ import {
} from './IsoElements';
import styles from './IsometricFooter.module.css';
import { messagesByLocale, type Locale } from '@/i18n/content';
import { FooterInteraction } from './FooterInteraction';
export const contacts: ContactItem[] = [
{
@@ -50,21 +48,8 @@ export default function IsometricFooter({ locale }: { locale: Locale }) {
...contact,
name: copy[contact.id],
}));
const [activePost, setActivePost] = useState<FooterContactId | null>(null);
const handlePostClick = (id: FooterContactId) => {
const item = contacts.find((c) => c.id === id);
if (item && item.href) {
if (item.href.startsWith('tel:')) {
window.location.href = item.href;
} else {
window.open(item.href, '_blank', 'noopener,noreferrer');
}
}
};
return (
<div className={styles.footerContainer}>
<FooterInteraction className={styles.footerContainer}>
{/* Top Header & Contact Section */}
<header className={styles.footerHeader}>
<h2 className={styles.headerTitle}>
@@ -94,12 +79,7 @@ export default function IsometricFooter({ locale }: { locale: Locale }) {
{/* 3D Isometric SVG Scene */}
<div className={styles.sceneContainer} data-footer-reveal>
<IsometricScene
activePost={activePost}
ariaLabel={copy.sceneLabel}
onPostHover={setActivePost}
onPostClick={handlePostClick}
/>
<IsometricScene ariaLabel={copy.sceneLabel} />
</div>
{/* Responsive Synchronized Contact Cards Section */}
@@ -107,17 +87,14 @@ export default function IsometricFooter({ locale }: { locale: Locale }) {
<div className={styles.contactCardsGrid}>
{localizedContacts.map((contact) => {
const IconComponent = contact.Icon;
const isHovered = activePost === contact.id;
return (
<a
key={contact.id}
href={contact.href}
target={contact.href.startsWith('tel:') ? undefined : '_blank'}
rel={contact.href.startsWith('tel:') ? undefined : 'noopener noreferrer'}
className={`${styles.contactCard} ${isHovered ? styles.active : ''}`}
onMouseEnter={() => setActivePost(contact.id)}
onMouseLeave={() => setActivePost(null)}
onClick={() => setActivePost(contact.id)}
className={styles.contactCard}
data-contact-id={contact.id}
aria-label={`${contact.name}: ${contact.label}`}
>
<div className={styles.contactCardIconWrap}>
@@ -134,6 +111,6 @@ export default function IsometricFooter({ locale }: { locale: Locale }) {
})}
</div>
</section>
</div>
</FooterInteraction>
);
}