index/pages/blog/index.vue

140 lines
4.2 KiB
Vue

<script setup lang="ts">
import { formatDate } from 'date-fns'
const config = useAppConfig()
const meta = {
title: 'The Ender Chest',
description:
'A blog about software development, scientific research and Windows quirks.',
image: `${config.url}/images/chest.png`,
url: `${config.url}/blog`,
}
useSeoMeta({
title: meta.title,
description: meta.description,
ogTitle: meta.title,
ogDescription: meta.description,
ogImage: meta.image,
ogUrl: meta.url,
ogType: 'website',
twitterTitle: meta.title,
twitterDescription: meta.description,
twitterImage: meta.image,
twitterCard: 'summary',
})
useHead({
title: 'The Ender Chest',
htmlAttrs: {
lang: config.locale || 'en',
},
link: [
{
rel: 'icon',
type: 'image/x-icon',
href: '/favicon.ico',
},
],
})
</script>
<template>
<section>
<h3 class="mb-2">The Ender Chest</h3>
<p class="mb-4">
You're browsing the Ender Chest — a blog about software development,
scientific research and Windows quirks.
</p>
<h4 class="mb-2">Recent posts</h4>
<ContentList
:query="{
path: '/blog',
where: [{ draft: false }],
limit: 3,
sort: [{ created: -1 }],
}"
>
<template #default="{ list }">
<div class="grid gap-4">
<NuxtLink
v-for="post in list"
:key="post._path"
:to="post._path"
class="text-inherit hover:text-inherit no-underline"
>
<article
class="post-box flex flex-col md:flex-row gap-4 rounded-xl h-full"
>
<div class="post-thumb">
<img
draggable="false"
:src="
post.thumbnail ??
`/images/blog/thumbnails/${post._path!.split('/').at(-1)}.png`
"
:alt="post.title"
class="rounded-xl"
/>
</div>
<div class="w-full">
<h3 class="post-title">{{ post.title }}</h3>
<p class="post-description mb-0">{{ post.description }}</p>
<div class="post-tags flex flex-row flex-wrap gap-2 py-2">
<span
v-for="(tag, index) in post.tags.slice(0, 3)"
:key="index"
class="whitespace-nowrap"
>
{{ tag }}
</span>
<span v-if="post.tags.length > 3" class="whitespace-nowrap">
{{ post.tags.length - 3 }} more
</span>
</div>
<hr class="accent-text accent-gradient border-0 h-px" />
<div class="post-details py-2">
<div class="flex flex-row items-center gap-2">
<iconify-icon icon="mdi:calendar" />
<small class="whitespace-nowrap">
{{ formatDate(post.created, 'LLLL do, y &ndash; HH:mm') }}
</small>
</div>
<div
v-if="post.updated"
class="flex flex-row items-center gap-2"
>
<iconify-icon icon="mdi:pencil" />
<small class="whitespace-nowrap">
{{ formatDate(post.updated, 'LLLL do, y &ndash; HH:mm') }}
</small>
</div>
</div>
</div>
<div
class="post-pocket absolute bottom-0 right-0 uppercase rounded-tl-xl flex flex-row items-center gap-2 p-2"
>
<iconify-icon icon="mdi:clock-outline" />
<small class="whitespace-nowrap font-mono font-small">
{{ post.readingTime.text }}
</small>
</div>
</article>
</NuxtLink>
</div>
</template>
<template #not-found>
<div class="flex flex-col justify-center items-center gap-4">
<span>No posts found 🙁</span>
<NuxtLink to="/">Back to index</NuxtLink>
</div>
</template>
</ContentList>
</section>
</template>