feat: add new 'articles' section to KB

This commit is contained in:
kodster28 committed 2026-09-30 11:10:09 -05:00
1 parent 13de8189c9
commit 897dd41925
6 files changed
+307 -1

No files matched your search

+28 -1
View File
@@ -4,6 +4,19 @@ import { z } from 'astro/zod'
import { TOPIC_NAMES } from './lib/topics'
// Format date as "26 SEPTEMBER 2026"
const formatDate = (date: Date): string => {
// Adjust for timezone offset to preserve the intended date
const adjusted = new Date(date.getTime() + date.getTimezoneOffset() * 60000)
return new Intl.DateTimeFormat('en-US', {
year: 'numeric',
month: 'long',
day: 'numeric',
})
.format(adjusted)
.toUpperCase()
}
// Every entry here is rendered through GuideLayout by
// src/pages/guides/[...slug].astro — dropping a new file in
// src/content/guides doesn't need any per-file layout wiring.
@@ -21,4 +34,18 @@ const guides = defineCollection({
}),
})
export const collections = { guides }
const articles = defineCollection({
loader: glob({ pattern: '**/*.{md,mdx}', base: './src/content/articles' }),
schema: z
.object({
title: z.string(),
description: z.string(),
date: z.date(),
})
.transform((data) => ({
...data,
formattedDate: formatDate(data.date),
})),
})
export const collections = { guides, articles }
@@ -0,0 +1,97 @@
---
title: 'Sample article 2'
description: 'A lorem ipsum sample guide exercising every base Markdown element supported by the guide layout.'
date: 2026-09-29
---
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis
nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
## Heading level 2
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore
eu fugiat nulla pariatur. This paragraph mixes **bold text**, _italic text_,
**_bold italic text_**, ~~strikethrough text~~, and `inline code`.
### Heading level 3
Here's a [link to the Astro docs](https://docs.astro.build/en/basics/layouts/),
followed by an unordered list with a nested list:
- Excepteur sint occaecat cupidatat non proident
- Sunt in culpa qui officia deserunt mollit anim id est laborum
- Nested item one
- Nested item two
- Curabitur blandit tempus porttitor
#### Heading level 4
And an ordered list with a nested list:
1. Lorem ipsum dolor sit amet
2. Consectetur adipiscing elit
1. Nested step one
2. Nested step two
3. Sed do eiusmod tempor incididunt
##### Heading level 5
> Neque porro quisquam est qui dolorem ipsum quia dolor sit amet,
> consectetur, adipisci velit.
>
> > Nested blockquote: at vero eos et accusamus et iusto odio dignissimos.
GitHub-style alert blockquotes, rendered through the `Admonition` component:
> [!NOTE]
> Useful information that users should know, even when skimming content.
> [!TIP]
> Helpful advice for doing things better or more easily.
> [!IMPORTANT]
> Key information users need to know to achieve their goal.
> [!WARNING]
> Urgent info that needs immediate attention to avoid problems.
> [!CAUTION]
> Advises about risks or negative outcomes of certain actions.
###### Heading level 6
A fenced code block with a language tag:
```js
function add(a, b) {
return a + b
}
console.log(add(2, 3))
```
And another in a different language:
```bash
npm install
npm run dev
```
A table:
| Element | Supported | Notes |
| -------- | --------- | ---------------------------- |
| Headings | Yes | h2 through h6 |
| Tables | Yes | via GitHub-flavored Markdown |
| Images | Yes | see below |
An image:
![Placeholder image](https://placehold.co/800x400?text=Placeholder+Image)
---
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium
doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore
veritatis et quasi architecto beatae vitae dicta sunt explicabo.
@@ -0,0 +1,97 @@
---
title: 'Sample article'
description: 'A lorem ipsum sample guide exercising every base Markdown element supported by the guide layout.'
date: 2026-09-30
---
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis
nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
## Heading level 2
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore
eu fugiat nulla pariatur. This paragraph mixes **bold text**, _italic text_,
**_bold italic text_**, ~~strikethrough text~~, and `inline code`.
### Heading level 3
Here's a [link to the Astro docs](https://docs.astro.build/en/basics/layouts/),
followed by an unordered list with a nested list:
- Excepteur sint occaecat cupidatat non proident
- Sunt in culpa qui officia deserunt mollit anim id est laborum
- Nested item one
- Nested item two
- Curabitur blandit tempus porttitor
#### Heading level 4
And an ordered list with a nested list:
1. Lorem ipsum dolor sit amet
2. Consectetur adipiscing elit
1. Nested step one
2. Nested step two
3. Sed do eiusmod tempor incididunt
##### Heading level 5
> Neque porro quisquam est qui dolorem ipsum quia dolor sit amet,
> consectetur, adipisci velit.
>
> > Nested blockquote: at vero eos et accusamus et iusto odio dignissimos.
GitHub-style alert blockquotes, rendered through the `Admonition` component:
> [!NOTE]
> Useful information that users should know, even when skimming content.
> [!TIP]
> Helpful advice for doing things better or more easily.
> [!IMPORTANT]
> Key information users need to know to achieve their goal.
> [!WARNING]
> Urgent info that needs immediate attention to avoid problems.
> [!CAUTION]
> Advises about risks or negative outcomes of certain actions.
###### Heading level 6
A fenced code block with a language tag:
```js
function add(a, b) {
return a + b
}
console.log(add(2, 3))
```
And another in a different language:
```bash
npm install
npm run dev
```
A table:
| Element | Supported | Notes |
| -------- | --------- | ---------------------------- |
| Headings | Yes | h2 through h6 |
| Tables | Yes | via GitHub-flavored Markdown |
| Images | Yes | see below |
An image:
![Placeholder image](https://placehold.co/800x400?text=Placeholder+Image)
---
Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium
doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore
veritatis et quasi architecto beatae vitae dicta sunt explicabo.
+20
View File
@@ -0,0 +1,20 @@
---
import Layout from './Layout.astro'
interface Props {
title: string
description?: string
formattedDate: string
}
const { title, description, formattedDate } = Astro.props
---
<Layout title={title} description={description}>
<article class="prose max-w-3xl mx-auto px-6 py-16">
<h1>{title}</h1>
<p>{formattedDate}</p>
{description && <p class="lead">{description}</p>}
<slot />
</article>
</Layout>
@@ -0,0 +1,22 @@
---
import { getCollection, render } from 'astro:content'
import { Admonition } from 'ui-patterns/Admonition'
import ArticleLayout from '../../layouts/ArticleLayout.astro'
export async function getStaticPaths() {
const articles = await getCollection('articles')
return articles.map((article) => ({
params: { slug: article.id },
props: { article },
}))
}
const { article } = Astro.props
const { title, description, formattedDate } = article.data
const { Content } = await render(article)
---
<ArticleLayout title={title} description={description} formattedDate={formattedDate}>
<Content components={{ Admonition }} />
</ArticleLayout>
+43
View File
@@ -0,0 +1,43 @@
---
import { getCollection } from 'astro:content'
import Layout from '../../layouts/Layout.astro'
const articles = await getCollection('articles')
// Sort articles by date, newest first
const sortedArticles = articles.sort(
(a, b) => new Date(b.data.date).getTime() - new Date(a.data.date).getTime()
)
---
<Layout title="Articles" description="Long-form articles on Supabase and the broader database ecosystem">
<div class="mx-auto flex max-w-7xl flex-col gap-12 px-6 py-16">
<section id="articles" class="flex flex-col gap-1">
<div class="mb-8 flex items-center justify-between border-b border-border pb-4">
<h1 class="text-l font-semibold uppercase tracking-widest text-muted-foreground">Articles</h1>
</div>
<ul class="flex flex-col gap-0">
{sortedArticles.map((article, idx) => (
<li class={`border-b border-border py-8 ${idx === sortedArticles.length - 1 ? 'border-b-0' : ''}`}>
<a
href={`${import.meta.env.BASE_URL}/articles/${article.id}`}
class="group flex flex-col gap-2 hover:opacity-70 transition-opacity"
>
<div class="flex items-start justify-between gap-4">
<h3 class="flex-1 text-xl font-semibold leading-tight text-foreground group-hover:underline">
{article.data.title}
</h3>
<div class="flex-shrink-0 whitespace-nowrap text-right text-xs text-muted-foreground">
{article.data.formattedDate}
</div>
</div>
<p class="text-sm text-muted-foreground">{article.data.description}</p>
</a>
</li>
))}
</ul>
</section>
</div>
</Layout>