Push Blog and Team to new Collections feature

This commit is contained in:
Maarten Dekker
2023-01-26 11:27:50 +01:00
parent eb9db7c190
commit add7a887e0
11 changed files with 209 additions and 86 deletions

View File

@@ -1,11 +1,14 @@
---
draft: false
title: "The Complete Guide to Full Stack Web Development"
excerpt: "Ornare cum cursus laoreet sagittis nunc fusce posuere per euismod dis vehicula a, semper fames lacus maecenas dictumst pulvinar neque enim non potenti. Torquent hac sociosqu eleifend potenti."
publishDate: "2022-11-08T11:39:36.050Z"
image: "https://images.unsplash.com/photo-1593720213428-28a5b9e94613?&fit=crop&w=430&h=240"
snippet: "Ornare cum cursus laoreet sagittis nunc fusce posuere per euismod dis vehicula a, semper fames lacus maecenas dictumst pulvinar neque enim non potenti. Torquent hac sociosqu eleifend potenti."
image: {
src: "https://images.unsplash.com/photo-1593720213428-28a5b9e94613?&fit=crop&w=430&h=240",
alt: "full stack web development"
}
publishDate: "2022-11-08 11:39"
category: "Tutorials"
author: "Janette Lynch"
layout: "@layouts/BlogLayout.astro"
tags: [webdev, tailwindcss, frontend]
---

View File

@@ -1,11 +1,14 @@
---
draft: false
title: " Introduction to the Essential Data Structures & Algorithms"
excerpt: "Ornare cum cursus laoreet sagittis nunc fusce posuere per euismod dis vehicula a, semper fames lacus maecenas dictumst pulvinar neque enim non potenti. Torquent hac sociosqu eleifend potenti."
publishDate: "2022-11-09T16:39:36.050Z"
image: "https://images.unsplash.com/photo-1627163439134-7a8c47e08208?&fit=crop&w=430&h=240"
snippet: "Ornare cum cursus laoreet sagittis nunc fusce posuere per euismod dis vehicula a, semper fames lacus maecenas dictumst pulvinar neque enim non potenti. Torquent hac sociosqu eleifend potenti."
image: {
src: "https://images.unsplash.com/photo-1627163439134-7a8c47e08208?&fit=crop&w=430&h=240",
alt: "data structures & algorithms"
}
publishDate: "2022-11-09 16:39"
category: "Courses"
author: "Marcell Ziemann"
layout: "@layouts/BlogLayout.astro"
tags: [webdev, tailwindcss, frontend]
---

View File

@@ -1,11 +1,14 @@
---
draft: false
title: "How to become a Frontend Master"
excerpt: "Ornare cum cursus laoreet sagittis nunc fusce posuere per euismod dis vehicula a, semper fames lacus maecenas dictumst pulvinar neque enim non potenti. Torquent hac sociosqu eleifend potenti."
publishDate: "2022-11-07T15:39:36.050Z"
image: "https://images.unsplash.com/photo-1667372393119-3d4c48d07fc9?&fit=crop&w=430&h=240"
snippet: "Ornare cum cursus laoreet sagittis nunc fusce posuere per euismod dis vehicula a, semper fames lacus maecenas dictumst pulvinar neque enim non potenti. Torquent hac sociosqu eleifend potenti."
image: {
src: "https://images.unsplash.com/photo-1667372393119-3d4c48d07fc9?&fit=crop&w=430&h=240",
alt: "frontend master"
}
publishDate: "2022-11-07 15:39"
category: "Tutorials"
author: "Connor Lopez"
layout: "@layouts/BlogLayout.astro"
tags: [astro, tailwindcss, frontend]
---

View File

@@ -1,10 +1,13 @@
---
draft: false
title: "Typography Example Post"
excerpt: "Sint sit cillum pariatur eiusmod nulla pariatur ipsum. Sit laborum anim qui mollit tempor pariatur nisi minim dolor. Aliquip et adipisicing sit sit fugiat"
publishDate: "2022-11-05T15:36:19.399Z"
snippet: "Sint sit cillum pariatur eiusmod nulla pariatur ipsum. Sit laborum anim qui mollit tempor pariatur nisi minim dolor. Aliquip et adipisicing sit sit fugiat"
publishDate: "2022-11-05 15:36"
image: {
src: "https://images.unsplash.com/photo-1542393545-10f5cde2c810?&fit=crop&w=430&h=240",
alt: "typography"
}
category: "Technology"
layout: "@layouts/BlogLayout.astro"
image: "https://images.unsplash.com/photo-1542393545-10f5cde2c810?&fit=crop&w=430&h=240"
author: "Charles North"
tags: [mdx, astro, blog]
---

39
src/content/config.ts Normal file
View File

@@ -0,0 +1,39 @@
// 1. Import utilities from `astro:content`
import { z, defineCollection } from 'astro:content';
// 2. Define your collection(s)
const blogCollection = defineCollection({
schema: z.object({
draft: z.boolean(),
title: z.string(),
snippet: z.string(),
image: z.object({
src: z.string(),
alt: z.string(),
}),
publishDate: z.string().transform(str => new Date(str)),
author: z.string().default('Astroship'),
category: z.string(),
tags: z.array(z.string()),
}),
});
const teamCollection = defineCollection({
schema: z.object({
draft: z.boolean(),
name: z.string(),
title: z.string(),
avatar: z.object({
src: z.string(),
alt: z.string(),
}),
publishDate: z.string().transform(str => new Date(str)),
}),
});
// 3. Export a single `collections` object to register your collection(s)
// This key should match your collection directory name in "src/content"
export const collections = {
'blog': blogCollection,
'team': teamCollection,
};

View File

@@ -0,0 +1,10 @@
---
draft: false
name: "Janette Lynch"
title: "Senior Director"
avatar: {
src: "https://images.unsplash.com/photo-1580489944761-15a19d654956?&fit=crop&w=280",
alt: "Janette Lynch"
}
publishDate: "2022-11-07 15:39"
---

View File

@@ -0,0 +1,10 @@
---
draft: false
name: "Marcell Ziemann"
title: "Principal Strategist"
avatar: {
src: "https://images.unsplash.com/photo-1633332755192-727a05c4013d?&fit=crop&w=280",
alt: "Marcell Ziemann"
}
publishDate: "2022-11-08 15:39"
---

View File

@@ -0,0 +1,10 @@
---
draft: false
name: "Robert Palmer"
title: "Marketing Engineer"
avatar: {
src: "https://images.unsplash.com/photo-1535713875002-d1d0cf377fde?&fit=crop&w=280",
alt: "Robert Palmer"
}
publishDate: "2022-11-09 15:39"
---

View File

@@ -1,45 +1,14 @@
---
import { getCollection } from "astro:content";
import { Picture } from "@astrojs/image/components";
import Layout from "@layouts/Layout.astro";
import Container from "@components/container.astro";
import Sectionhead from "@components/sectionhead.astro";
import { Picture } from "@astrojs/image/components";
const TeamImg1 =
"https://images.unsplash.com/photo-1580489944761-15a19d654956?&fit=crop&w=280";
const TeamImg2 =
"https://images.unsplash.com/photo-1633332755192-727a05c4013d?&fit=crop&w=280";
const TeamImg3 =
"https://images.unsplash.com/photo-1535713875002-d1d0cf377fde?&fit=crop&w=280";
const team = [
{
name: "Janette Lynch",
title: "Senior Director",
avatar: {
src: TeamImg1,
width: 480,
height: 560,
},
},
{
name: "Marcell Ziemann",
title: "Principal Strategist",
avatar: {
src: TeamImg2,
width: 580,
height: 580,
},
},
{
name: "Robert Palmer",
title: "Marketing Engineer",
avatar: {
src: TeamImg3,
width: 580,
height: 580,
},
},
];
// Filter team entries with 'draft: false' & date before current date
const publishedTeamMembers = await getCollection("team", ({ data }) => {
return !data.draft && data.publishDate < new Date();
});
---
<Layout title="About">
@@ -61,24 +30,31 @@ const team = [
</div>
<div class="grid md:grid-cols-3 gap-10 mx-auto max-w-4xl mt-12">
{
team.map((item) => (
publishedTeamMembers.map((teamMemberEntry) => (
<div class="group">
<div class="w-full aspect-square">
<Picture
{...item.avatar}
format="avif"
alt="Team"
src={teamMemberEntry.data.avatar.src}
alt={teamMemberEntry.data.avatar.alt}
sizes="(max-width: 800px) 100vw, 400px"
widths={[200, 400]}
aspectRatio="1:1"
sizes="(max-width: 800px) 100vw, 400px"
class="w-full h-full object-cover rounded transition group-hover:-translate-y-1 group-hover:shadow-xl"
format="avif"
background="#ffffff"
fit="cover"
position="center"
class="w-full rounded-md rounded transition group-hover:-translate-y-1 group-hover:shadow-xl"
/>
</div>
<div class="mt-4 text-center">
<h2 class="text-lg text-gray-800"> {item.name}</h2>
<h3 class="text-sm text-slate-500"> {item.title}</h3>
<h2 class="text-lg text-gray-800">
{" "}
{teamMemberEntry.data.name}
</h2>
<h3 class="text-sm text-slate-500">
{" "}
{teamMemberEntry.data.title}
</h3>
</div>
</div>
))

View File

@@ -1,62 +1,66 @@
---
import { getCollection } from "astro:content";
import { Picture } from "@astrojs/image/components";
import Layout from "@layouts/Layout.astro";
import Container from "@components/container.astro";
import Sectionhead from "@components/sectionhead.astro";
import Layout from "@layouts/Layout.astro";
import { getFormattedDate } from "@utils/all";
import { log } from "astro/dist/core/logger/core";
// Use Astro.glob() to fetch all posts, and then sort them by date.
const posts = (await Astro.glob("./blog/*.{md,mdx}")).sort(
(a, b) =>
new Date(b.frontmatter.publishDate).valueOf() -
new Date(a.frontmatter.publishDate).valueOf()
);
console.log(posts[0].frontmatter.image);
// Filter blog entries with 'draft: false' & date before current date
const publishedBlogEntries = await getCollection("blog", ({ data }) => {
return !data.draft && data.publishDate < new Date();
});
// Sort content entries by publication date
publishedBlogEntries.sort(function (a, b) {
return b.data.publishDate.valueOf() - a.data.publishDate.valueOf();
});
---
<Layout title="Blog">
<Container>
<Sectionhead>
<Fragment slot="title">Our Blog</Fragment>
<Fragment slot="desc"
>We write about building startups and thoughts going on our mind.</Fragment
>
<Fragment slot="desc">
We write about building startups and thoughts going on our mind.
</Fragment>
</Sectionhead>
<main class="mt-16">
<ul class="grid gap-16 max-w-4xl mx-auto">
{
posts.map((post, index) => (
publishedBlogEntries.map((blogPostEntry, index) => (
<li>
<a href={post.url}>
<a href={`/blog/${blogPostEntry.slug}`}>
<div class="grid md:grid-cols-2 gap-5 md:gap-10 items-center">
<Picture
src={post.frontmatter.image}
widths={[200, 400, 800]}
src={blogPostEntry.data.image.src}
alt={blogPostEntry.data.image.alt}
sizes="(max-width: 800px) 100vw, 800px"
widths={[200, 400, 800]}
aspectRatio="16:9"
alt="Thumbnail"
background="#ffffff"
fit="cover"
position="center"
loading={index === 0 ? "eager" : "lazy"}
class="w-full rounded-md aspect-video"
class="w-full rounded-md"
/>
<div>
<span class="text-blue-400 uppercase tracking-wider text-sm font-medium">
{post.frontmatter.category}
{blogPostEntry.data.category}
</span>
<h2 class="text-3xl font-semibold leading-snug tracking-tight mt-1 ">
{post.frontmatter.title}
{blogPostEntry.data.title}
</h2>
<div class="flex gap-2 mt-3">
<span class="text-gray-400">
{post.frontmatter.author}
{blogPostEntry.data.author}
</span>
<span class="text-gray-400">• </span>
<time
class="text-gray-400"
datetime={post.frontmatter.publishDate}>
{getFormattedDate(post.frontmatter.publishDate)}
datetime={blogPostEntry.data.publishDate.toISOString()}>
{blogPostEntry.data.publishDate.toDateString()}
</time>
</div>
</div>

View File

@@ -0,0 +1,62 @@
---
import { getCollection } from "astro:content";
import Layout from "@layouts/Layout.astro";
import Container from "@components/container.astro";
// Generate a new path for every collection entry
export async function getStaticPaths() {
const blogEntries = await getCollection("blog");
return blogEntries.map((entry) => ({
params: { slug: entry.slug },
props: { entry },
}));
}
// Get the entry directly from the prop on render
const { entry } = Astro.props;
const { Content } = await entry.render();
---
<Layout title={entry.data.title}>
<Container>
<div class="mx-auto max-w-[735px] mt-14">
<span class="text-blue-400 uppercase tracking-wider text-sm font-medium">
{entry.data.category}
</span>
<h1
class="text-4xl lg:text-5xl font-bold lg:tracking-tight mt-1 lg:leading-tight">
{entry.data.title}
</h1>
<div class="flex gap-2 mt-3 items-center flex-wrap md:flex-nowrap">
<span class="text-gray-400">
{entry.data.author}
</span>
<span class="text-gray-400">•</span>
<time
class="text-gray-400"
datetime={entry.data.publishDate.toISOString()}>
{entry.data.publishDate.toDateString()}
</time>
<span class="text-gray-400 hidden md:block">•</span>
<div class="w-full md:w-auto flex flex-wrap gap-3">
{
entry.data.tags.map((tag) => (
<span class="text-sm text-gray-500">#{tag}</span>
))
}
</div>
</div>
</div>
<div class="mx-auto prose prose-lg mt-6">
<Content />
</div>
<div class="text-center mt-8">
<a
href="/blog"
class="bg-gray-100 px-5 py-3 rounded-md hover:bg-gray-200 transition"
>← Back to Blog</a
>
</div>
</Container>
</Layout>