--- import BaseLayout from '../layouts/BaseLayout.astro'; import TerminalWindow from '../components/ui/TerminalWindow.astro'; import CommandPrompt from '../components/ui/CommandPrompt.astro'; import FilterPill from '../components/ui/FilterPill.astro'; import PostCard from '../components/PostCard.astro'; import FriendLinkCard from '../components/FriendLinkCard.astro'; import ViewMoreLink from '../components/ui/ViewMoreLink.astro'; import StatsList from '../components/StatsList.astro'; import TechStackList from '../components/TechStackList.astro'; import { terminalConfig } from '../lib/config/terminal'; import { api, DEFAULT_SITE_SETTINGS } from '../lib/api/client'; import { formatReadTime, getI18n } from '../lib/i18n'; import type { AppFriendLink } from '../lib/api/client'; import type { Post } from '../lib/types'; import { getAccentVars, getCategoryTheme, getPostTypeTheme, getTagTheme } from '../lib/utils'; export const prerender = false; const url = new URL(Astro.request.url); const selectedType = url.searchParams.get('type') || 'all'; const selectedTag = url.searchParams.get('tag') || ''; const selectedCategory = url.searchParams.get('category') || ''; const normalizedSelectedTag = selectedTag.trim().toLowerCase(); const normalizedSelectedCategory = selectedCategory.trim().toLowerCase(); const previewLimit = 5; let siteSettings = DEFAULT_SITE_SETTINGS; let allPosts: Post[] = []; let recentPosts: Post[] = []; let filteredPostsCount = 0; let pinnedPost: Post | null = null; let tags: string[] = []; let friendLinks: AppFriendLink[] = []; let categories: Awaited> = []; let apiError: string | null = null; const { locale, t } = getI18n(Astro); try { const [settings, posts, rawTags, rawFriendLinks, nextCategories] = await Promise.all([ api.getSiteSettings(), api.getPosts(), api.getTags(), api.getFriendLinks(), api.getCategories(), ]); siteSettings = settings; allPosts = posts; tags = rawTags.map(tag => tag.name); friendLinks = rawFriendLinks.filter(friend => friend.status === 'approved'); categories = nextCategories; const filteredPosts = allPosts.filter(post => { const normalizedCategory = post.category?.trim().toLowerCase() || ''; if (selectedType !== 'all' && post.type !== selectedType) return false; if (selectedCategory && normalizedCategory !== normalizedSelectedCategory) return false; if (selectedTag && !post.tags.some(tag => tag.trim().toLowerCase() === normalizedSelectedTag)) return false; return true; }); recentPosts = filteredPosts.slice(0, previewLimit); filteredPostsCount = filteredPosts.length; pinnedPost = allPosts.find(post => post.pinned) || null; } catch (error) { apiError = error instanceof Error ? error.message : t('common.apiUnavailable'); console.error('API Error:', error); } const systemStats = [ { label: t('common.posts'), value: String(allPosts.length) }, { label: t('common.tags'), value: String(tags.length) }, { label: t('common.categories'), value: String(categories.length) }, { label: t('common.friends'), value: String(friendLinks.length) }, ]; const techStack = siteSettings.techStack.map(name => ({ name })); const tagFrequency = new Map(); for (const post of allPosts) { for (const tag of post.tags) { tagFrequency.set(tag, (tagFrequency.get(tag) ?? 0) + 1); } } const tagEntries = tags .map(name => ({ name, count: tagFrequency.get(name) ?? 0, })) .sort((left, right) => right.count - left.count || left.name.localeCompare(right.name)); const getTagCloudStyle = (name: string) => { return getAccentVars(getTagTheme(name)); }; const matchesSelectedFilters = (post: Post) => { const normalizedCategory = post.category?.trim().toLowerCase() || ''; if (selectedType !== 'all' && post.type !== selectedType) return false; if (selectedCategory && normalizedCategory !== normalizedSelectedCategory) return false; if (selectedTag && !post.tags.some(tag => tag.trim().toLowerCase() === normalizedSelectedTag)) return false; return true; }; const buildHomeUrl = ({ type = selectedType, tag = selectedTag, category = selectedCategory, }: { type?: string; tag?: string; category?: string; }) => { const params = new URLSearchParams(); if (type && type !== 'all') params.set('type', type); if (category) params.set('category', category); if (tag) params.set('tag', tag); const query = params.toString(); return query ? `/?${query}` : '/'; }; const homeTagHrefPrefix = `${buildHomeUrl({ tag: '' })}${buildHomeUrl({ tag: '' }).includes('?') ? '&' : '?'}tag=`; const hasActiveFilters = selectedType !== 'all' || Boolean(selectedCategory) || Boolean(selectedTag); const previewCount = Math.min(filteredPostsCount, previewLimit); const categoryAccentMap = Object.fromEntries( categories.map((category) => [category.name.trim().toLowerCase(), getAccentVars(getCategoryTheme(category.name))]) ); const tagAccentMap = Object.fromEntries( tagEntries.map((tag) => [tag.name.trim().toLowerCase(), getAccentVars(getTagTheme(tag.name))]) ); const initialPinnedVisible = pinnedPost ? matchesSelectedFilters(pinnedPost) : false; const postTypeFilters = [ { id: 'all', name: t('common.all'), icon: 'fa-stream' }, { id: 'article', name: t('common.article'), icon: 'fa-file-alt' }, { id: 'tweet', name: t('common.tweet'), icon: 'fa-comment-dots' } ]; const activeFilterLabels = [ selectedType !== 'all' ? `type=${selectedType}` : '', selectedCategory ? `category=${selectedCategory}` : '', selectedTag ? `tag=${selectedTag}` : '', ].filter(Boolean); const discoverPrompt = hasActiveFilters ? t('home.promptDiscoverFiltered', { filters: activeFilterLabels.join(' · ') }) : t('home.promptDiscoverDefault'); const postsPrompt = hasActiveFilters ? t('home.promptPostsFiltered', { count: previewCount, filters: activeFilterLabels.join(' · ') }) : t('home.promptPostsDefault', { count: previewCount }); const navLinks = [ { icon: 'fa-file-code', text: t('nav.articles'), href: '/articles' }, { icon: 'fa-folder', text: t('nav.categories'), href: '/categories' }, { icon: 'fa-tags', text: t('nav.tags'), href: '/tags' }, { icon: 'fa-stream', text: t('nav.timeline'), href: '/timeline' }, { icon: 'fa-star', text: t('nav.reviews'), href: '/reviews' }, { icon: 'fa-link', text: t('nav.friends'), href: '/friends' }, { icon: 'fa-user-secret', text: t('nav.about'), href: '/about' }, ...(siteSettings.ai.enabled ? [{ icon: 'fa-robot', text: t('nav.ask'), href: '/ask' }] : []), ]; ---
{terminalConfig.asciiArt}

{siteSettings.heroTitle}

{siteSettings.heroSubtitle}

{t('common.resultsCount', { count: filteredPostsCount })} {siteSettings.ai.enabled && ( {t('nav.ask')} )}
{navLinks.map(link => ( {link.text} ))}
{apiError && (
{apiError}
)}
home filters

{t('common.browsePosts')}

{t('common.categoriesCount', { count: categories.length })} · {t('common.tagsCount', { count: tags.length })} · {t('common.resultsCount', { count: filteredPostsCount })}

{postTypeFilters.map(filter => ( {filter.name} ))}
item.id === selectedType)?.icon || 'fa-stream'} text-[10px]`}> {postTypeFilters.find((item) => item.id === selectedType)?.name || selectedType} {selectedCategory} {selectedTag}

{t('nav.categories')}

{categories.length}
{categories.map(category => (

{category.name}

{category.count ?? 0}
))}

{t('nav.tags')}

{tags.length}
{tagEntries.map((tag) => ( # {tag.name} {tag.count} ))}
{pinnedPost && (
{t('home.pinned')} {pinnedPost.type === 'article' ? t('common.article') : t('common.tweet')} {pinnedPost.title}

{pinnedPost.date} | {t('common.readTime')}: {formatReadTime(locale, pinnedPost.readTime, t)}

{pinnedPost.description}

)}
{allPosts.length > 0 ? (
{allPosts.map((post) => { const matchesCurrentFilter = matchesSelectedFilters(post); const filteredIndex = matchesCurrentFilter ? allPosts.filter(matchesSelectedFilters).findIndex((item) => item.slug === post.slug) : -1; const isVisible = matchesCurrentFilter && filteredIndex < previewLimit; return (
tag.trim().toLowerCase()).join('|')} data-home-pinned={post.pinned ? 'true' : 'false'} data-home-slug={post.slug} class:list={[!isVisible && 'hidden']} >
); })}
) : (

{t('articlesPage.emptyTitle')}

{t('articlesPage.emptyDescription')}

)} {allPosts.length > 0 && (
0 && 'hidden']}>

{t('articlesPage.emptyTitle')}

{t('articlesPage.emptyDescription')}

)}
{friendLinks.map(friend => ( ))}

{t('home.about')}

{siteSettings.ownerBio}

{t('home.techStack')}

{t('home.systemStatus')}