nicholai-work-2026/src/layouts/BaseLayout.astro
Nicholai bd16598998 Update site configuration and enhance SEO with structured data
- Changed site URL in configuration from 'https://example.com' to 'https://nicholai.work'.
- Updated site title and description for better SEO optimization.
- Removed outdated portrait images and replaced them with optimized formats in the hero section.
- Enhanced BaseHead component with structured data for improved search engine visibility.
- Added reading time calculation to blog posts for better user engagement.
2025-12-08 14:53:56 -07:00

115 lines
3.1 KiB
Plaintext

---
import type { ImageMetadata } from 'astro';
import BaseHead from '../components/BaseHead.astro';
import Footer from '../components/Footer.astro';
import GridOverlay from '../components/GridOverlay.astro';
import Navigation from '../components/Navigation.astro';
import CustomCursor from '../components/CustomCursor';
import { SITE_TITLE, SITE_DESCRIPTION } from '../consts';
interface Props {
title?: string;
description?: string;
usePadding?: boolean;
image?: ImageMetadata;
type?: 'website' | 'article';
publishedTime?: Date;
modifiedTime?: Date;
}
const {
title = SITE_TITLE,
description = SITE_DESCRIPTION,
usePadding = true,
image,
type = 'website',
publishedTime,
modifiedTime,
} = Astro.props;
---
<!DOCTYPE html>
<html lang="en" class="scroll-smooth">
<head>
<BaseHead
title={title}
description={description}
image={image}
type={type}
publishedTime={publishedTime}
modifiedTime={modifiedTime}
/>
<slot name="head" />
</head>
<body class="antialiased selection:bg-brand-accent selection:text-brand-dark bg-brand-dark text-white">
<CustomCursor client:load />
<GridOverlay />
<Navigation />
<main class:list={["relative z-10 min-h-screen pb-24", { "pt-32 lg:pt-48": usePadding }]}>
<slot />
</main>
<Footer />
<script>
// Initialize Lucide icons
// @ts-ignore
if (window.lucide) {
// @ts-ignore
window.lucide.createIcons();
}
// ===== SCROLL ANIMATION SYSTEM =====
// Observer for scroll-triggered animations
const scrollObserverOptions = {
threshold: 0.15,
rootMargin: "0px 0px -50px 0px"
};
const scrollObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('is-visible');
// Optionally unobserve after animation
// scrollObserver.unobserve(entry.target);
}
});
}, scrollObserverOptions);
// Observe all animate-on-scroll elements
document.querySelectorAll('.animate-on-scroll').forEach(el => {
scrollObserver.observe(el);
});
// Observer for legacy reveal-text animations
const revealObserverOptions = {
threshold: 0.1,
rootMargin: "0px"
};
const revealObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('active');
}
});
}, revealObserverOptions);
document.querySelectorAll('.reveal-text').forEach(el => {
revealObserver.observe(el);
});
// Auto-stagger children in containers with .stagger-children class
document.querySelectorAll('.stagger-children').forEach(container => {
const children = container.querySelectorAll('.animate-on-scroll');
children.forEach((child, index) => {
child.classList.add(`stagger-${Math.min(index + 1, 8)}`);
});
});
</script>
</body>
</html>