/** * Homepage — renders different hero layouts based on theme config. * * Styles: split, fullbleed, minimal, stacked, typographic, mosaic. */ import Link from 'next/link'; import Image from 'next/image'; import { immich } from '@/lib/immich'; import { getConfig } from '@/lib/config'; import { imageUrl, assetPlaceholder } from '@/lib/urls'; import { HeroCarousel } from '@/components/HeroCarousel'; import { FadeIn } from '@/components/FadeIn'; // Render at request time — requires live Immich connection export const dynamic = 'force-dynamic'; /** Shared nav links for hero sections. */ function HeroNavLinks({ subpages, albums, }: { subpages: { slug: string; name: string }[]; albums: { id: string; slug: string; albumName: string }[]; }) { return ( <> {subpages.map((sp) => ( {sp.name} ))} {albums.map((album) => ( {album.albumName} ))} > ); } export default async function HomePage() { const config = getConfig(); const [subpages, albums] = await Promise.all([ immich.getSubpages(), immich.getStandaloneAlbums(), ]); // Fetch ThumbHash for all hero images const heroData = await Promise.all( config.heroImages.map(async (id) => { const asset = await immich.getAssetInfo(id); const ph = asset ? assetPlaceholder(asset) : null; return { src: imageUrl(id, 'preview'), ...(ph ? { blurDataURL: ph.blurDataURL } : {}), }; }), ); const heroStyle = config.theme.heroStyle; // ── Typographic: no image, pure text ─────────────────────────── if (heroStyle === 'typographic') { return (
{config.siteSubtitle}
{config.siteSubtitle}
{config.siteSubtitle}
{config.siteSubtitle}