add: basic blog layout

Basic Blog Layout to work on
This commit is contained in:
webfussel 2025-06-11 20:41:34 +02:00
parent 9d691974ce
commit 91b59e4ebe
15 changed files with 278 additions and 3 deletions

View file

@ -0,0 +1,32 @@
.BlogAuthor {
display: flex;
align-items: center;
gap: 1rem;
& .meta {
display: flex;
flex-direction: column;
gap: .2rem;
& .name {
font-weight: bold;
}
& .date {
font-size: .8rem;
}
}
& .image {
--size: 50px;
height: var(--size);
width: var(--size);
border-radius: 50%;
overflow: hidden;
& img {
height: 100%;
width: 100%;
object-fit: cover;
}
}
}

View file

@ -0,0 +1,44 @@
.BlogCard {
overflow: hidden;
border-radius: 1rem;
background: var(--color-orange-black);
display: flex;
flex-direction: column;
height: 100%;
transition: 150ms;
gap: 1rem;
&:hover {
scale: 1.05;
}
& .card-content {
display: flex;
flex-direction: column;
height: 100%;
padding: 0 1.5rem 1rem;
gap: 1.5rem;
}
& .chip {
margin-bottom: 1rem;
}
& footer {
margin-top: auto;
display: flex;
flex-direction: column;
gap: .5rem;
}
& .tags {
display: flex;
flex-wrap: wrap;
gap: .5rem;
opacity: .5;
& .tag {
color: var(--color-orange);
}
}
}

View file

@ -142,7 +142,7 @@ span.chip {
border-radius: 999px; border-radius: 999px;
font-size: 1rem; font-size: 1rem;
height: max-content; height: max-content;
padding: .5em 1em; padding: .2em 1em;
user-select: none; user-select: none;
display: flex; display: flex;
align-items: center; align-items: center;
@ -288,6 +288,12 @@ span.chip {
align-items: center; align-items: center;
} }
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 2rem;
}
.tip-container .tip { .tip-container .tip {
scale: 0; scale: 0;
position: absolute; position: absolute;

View file

@ -0,0 +1,29 @@
<template>
<aside class="BlogAuthor">
<div class="image">
<img :src="image" :alt="`Bild von ${name}`" />
</div>
<div class="meta">
<span class="name">{{ name }}</span>
<span class="date">{{ dateFormatted }}</span>
</div>
</aside>
</template>
<script setup lang="ts">
type Props = {
name : string
image : string
date : string
}
const { date } = defineProps<Props>()
const formatter = new Intl.DateTimeFormat('de-DE', {
year: 'numeric',
month: 'long',
day: '2-digit',
})
const dateFormatted = computed(() => formatter.format(new Date(date)))
</script>

View file

@ -0,0 +1,42 @@
<template>
<NuxtLink :to="link" class="BlogCard z-2">
<img :src="image" alt=" " aria-hidden="true" />
<div class="card-content">
<header>
<span class="chip">{{ category }}</span>
<h2>{{ title }}</h2>
<small>{{ description }}</small>
</header>
<main>
<ContentRenderer :value="excerpt" />
</main>
<footer>
<BlogAuthor :name="author.name" :image="author.image" :date="date" />
<div class="tags">
<span>tags</span>
<span class="tag" v-for="tag in tags">{{tag}}</span>
</div>
</footer>
</div>
</NuxtLink>
</template>
<script setup lang="ts">
type Props = {
title : string
description : string
image : string
date : string
excerpt : { type: string, children?: any }
link : string
tags : string[]
category : string
author : {
name : string
image : string
}
}
defineProps<Props>()
</script>

View file

@ -8,7 +8,7 @@
<script setup lang="ts"> <script setup lang="ts">
type Props = { type Props = {
title : string title : string
titleTag ?: 'strong' | 'h3' titleTag ?: 'strong' | 'h3' | 'h2'
} }
defineProps<Props>() defineProps<Props>()

11
app/pages/blog/[slug].vue Normal file
View file

@ -0,0 +1,11 @@
<template>
</template>
<script setup lang="ts">
</script>
<style scoped>
</style>

25
app/pages/blog/index.vue Normal file
View file

@ -0,0 +1,25 @@
<template>
<section id="blog" class="Blog content">
<div class="grid">
<BlogCard v-for="article in articles" v-bind="makeBlogCard(article)" />
</div>
</section>
</template>
<script setup lang="ts">
const { data } = await useAsyncData('articles', () => queryCollection('blog').limit(10).all())
const articles = data.value!
const makeBlogCard = (article : typeof articles[0]) => ({
title: article.title,
description: article.description,
image: article.meta.image as string,
date: article.meta.date as string,
excerpt: article.excerpt,
link: article.path,
tags: article.meta.tags as string[],
category: article.meta.category as string,
author: article.meta.author as { name: string, image: string },
})
</script>

View file

@ -23,4 +23,10 @@ export const navigation = [
icon: 'ph:chats-circle-duotone', icon: 'ph:chats-circle-duotone',
aria: 'Link dieser Seite: Kontakt' aria: 'Link dieser Seite: Kontakt'
}, },
{
to: `/blog/`,
label: 'Blog',
icon: 'ph:book-open-user-duotone',
aria: 'Link dieser Seite: Blog'
},
] ]

View file

@ -4,7 +4,13 @@ export default defineContentConfig({
collections: { collections: {
blog: defineCollection({ blog: defineCollection({
type: 'page', type: 'page',
source: 'blog/**/*.md' source: 'blog/*.md',
schema: z.object({
excerpt: z.object({
type: z.string(),
children: z.any(),
}),
}),
}), }),
skills: defineCollection({ skills: defineCollection({

View file

@ -0,0 +1,18 @@
---
image: 'https://picsum.photos/600/250?random=4'
title: 'Blogfussel - für mehr Fussel im Blog'
description: 'Und nochmal...'
navigation: true
date: 2025-07-01
category: 'start'
tags: ['start', 'story']
author:
name: 'webfussel'
image: '/img/og.webp'
---
Warum ich mich dazu entschlossen habe jetzt doch wieder mit dem Bloggen anzufangen? Nun ja, das hat alles angefangen, als man mich einfach so auf Instagram gesperrt hat.
<!-- more -->
Noch mehr Text

View file

@ -0,0 +1,18 @@
---
image: 'https://picsum.photos/600/250?random=3'
title: 'Post 1'
description: 'Blablabla'
navigation: true
date: 2025-07-01
category: 'test'
tags: ['test', 'wasd']
author:
name: 'webfussel'
image: '/img/og.webp'
---
Blablabla test 1 2 3
<!-- more -->
Noch mehr Text

View file

@ -0,0 +1,18 @@
---
image: 'https://picsum.photos/600/250?random=2'
title: 'Post 2'
description: 'Blablabla'
navigation: true
date: 2025-07-01
category: 'test'
tags: ['test', 'asdf']
author:
name: 'webfussel'
image: '/img/og.webp'
---
Blablabla test 1 2 3
<!-- more -->
Noch mehr Text

View file

@ -0,0 +1,18 @@
---
image: 'https://picsum.photos/600/250?random=1'
title: 'Post 3'
description: 'Blablabla'
navigation: true
date: 2025-07-01
category: 'test'
tags: ['test', '123']
author:
name: 'webfussel'
image: '/img/og.webp'
---
Blablabla test 1 2 3
<!-- more -->
Noch mehr Text

View file

@ -43,6 +43,8 @@ export default defineNuxtConfig({
'~/assets/css/burger.css', '~/assets/css/burger.css',
'~/assets/css/teaser.css', '~/assets/css/teaser.css',
'~/assets/css/project.css', '~/assets/css/project.css',
'~/assets/css/blogCard.css',
'~/assets/css/blogAuthor.css',
], ],
postcss: { postcss: {