summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDawid Rycerz <dawid@rycerz.xyz>2026-01-13 17:13:43 +0100
committerDawid Rycerz <dawid@rycerz.xyz>2026-01-13 17:20:15 +0100
commit9fe4480c3981c38ae8e24d0495df957039864a5d (patch)
treea5f3e4f8c0732c8cd934c28596c6a4d0ab38a4b4 /src
parentc0dcecc43e36eeb6b10f662c1be760736cd0dbac (diff)
Remove micro and migrate to use only posts
Diffstat (limited to 'src')
-rw-r--r--src/components/BaseHead.astro1
-rw-r--r--src/components/note/Note.astro86
-rw-r--r--src/content.config.ts25
-rw-r--r--src/content/post/devops-mindset.md1
-rw-r--r--src/content/post/fediverse-101.md1
-rw-r--r--src/content/post/niedziela-11-wrzesnia-2022.md1
-rw-r--r--src/content/post/piatek-16-wrzesnia-2022.md1
-rw-r--r--src/content/post/piatek-7-pazdziernika-2022.md1
-rw-r--r--src/content/post/piatek-9-wrzesnia-2022.md1
-rw-r--r--src/content/post/poniedzialek-3-pazdziernika-2022.md1
-rw-r--r--src/content/post/poniedzialek-5-wrzesnia-2022.md1
-rw-r--r--src/content/post/sobota-3-wrzesnia-2022.md1
-rw-r--r--src/content/post/sroda-21-wrzesnia-2022.md1
-rw-r--r--src/content/post/sroda-28-wrzesnia-2022.md1
-rw-r--r--src/content/post/sroda-7-wrzesnia-2022.md1
-rw-r--r--src/content/post/wtorek-13-wrzesnia-2022.md1
-rw-r--r--src/data/post.ts18
-rw-r--r--src/layouts/BlogPost.astro14
-rw-r--r--src/loaders/pleroma.ts110
-rw-r--r--src/pages/index.astro32
-rw-r--r--src/pages/micro/[...slug].astro34
-rw-r--r--src/pages/posts/[...page].astro6
-rw-r--r--src/pages/rss.xml.ts1
-rw-r--r--src/pages/tags/[tag]/[...page].astro44
-rw-r--r--src/pages/tags/[tag]/rss.xml.ts52
-rw-r--r--src/pages/tags/index.astro25
-rw-r--r--src/site.config.ts4
-rw-r--r--src/utils/date.ts5
-rw-r--r--src/utils/micro.ts40
29 files changed, 158 insertions, 352 deletions
diff --git a/src/components/BaseHead.astro b/src/components/BaseHead.astro
index 40f1d20..14286c3 100644
--- a/src/components/BaseHead.astro
+++ b/src/components/BaseHead.astro
@@ -95,7 +95,6 @@ const ogLocale = getOgLocale(lang);
{/* RSS auto-discovery */}
<link href="/rss.xml" title="Blog" rel="alternate" type="application/rss+xml" />
-<link href="/micro/rss.xml" title="Micro" rel="alternate" type="application/rss+xml" />
{/* Webmentions */}
{
diff --git a/src/components/note/Note.astro b/src/components/note/Note.astro
deleted file mode 100644
index 920cbc1..0000000
--- a/src/components/note/Note.astro
+++ /dev/null
@@ -1,86 +0,0 @@
----
-import { type CollectionEntry, render } from "astro:content";
-import type { HTMLTag, Polymorphic } from "astro/types";
-import FormattedDate from "@/components/FormattedDate.astro";
-
-type Props<Tag extends HTMLTag> = Polymorphic<{ as: Tag }> & {
- note: CollectionEntry<"micro">;
- isPreview?: boolean | undefined;
-};
-
-const { as: Tag = "div", note, isPreview = false } = Astro.props;
-const { Content } = await render(note);
----
-
-<article
- class:list={[
- isPreview && "inline-grid rounded-md bg-[rgb(240,240,240)] px-4 py-3 dark:bg-[rgb(33,35,38)]",
- ]}
- data-pagefind-body={isPreview ? false : true}
->
- <Tag class="title" class:list={{ "text-base": isPreview }}>
- {
- isPreview ? (
- <a class="cactus-link" href={`/micro/${note.id}/`}>
- {note.data.title}
- </a>
- ) : (
- <>{note.data.title}</>
- )
- }
- </Tag>
- <FormattedDate
- dateTimeOptions={{
- hour: "2-digit",
- minute: "2-digit",
- year: "2-digit",
- month: "2-digit",
- day: "2-digit",
- }}
- date={note.data.publishDate}
- />
- <div
- class="prose prose-sm prose-cactus mt-4 max-w-none [&>p:last-of-type]:mb-0"
- class:list={{ "line-clamp-6": isPreview }}
- >
- <Content />
- {
- !isPreview && note.data.attachments && note.data.attachments.length > 0 && (
- <div class="mt-6 grid grid-cols-1 gap-4 sm:grid-cols-2">
- {note.data.attachments.map((attachment: { type: string; url: string; alt?: string }) => (
- <a
- href={attachment.url}
- target="_blank"
- rel="noopener noreferrer"
- class="block overflow-hidden rounded-lg border border-gray-200 transition-colors hover:border-gray-300 dark:border-gray-700 dark:hover:border-gray-600"
- >
- <img
- src={attachment.url}
- alt={attachment.alt || "Image"}
- class="h-48 w-full object-cover"
- loading="lazy"
- />
- </a>
- ))}
- </div>
- )
- }
- {
- !isPreview && note.data.sourceUrl && (
- <>
- <hr class="mt-6 mb-4 border-t border-gray-300 dark:border-gray-600" />
- <p class="text-sm text-gray-600 dark:text-gray-400">
- <a
- href={note.data.sourceUrl}
- class="cactus-link"
- target="_blank"
- rel="noopener noreferrer"
- >
- View original post →
- </a>
- </p>
- </>
- )
- }
- </div>
-</article>
diff --git a/src/content.config.ts b/src/content.config.ts
index a9fa0e2..5b5836b 100644
--- a/src/content.config.ts
+++ b/src/content.config.ts
@@ -35,10 +35,12 @@ const post = defineCollection({
.optional()
.transform((str) => (str ? new Date(str) : undefined)),
language: z.string().optional(),
+ sourceUrl: z.string().optional(),
+ author: z.string().optional(),
}),
});
-const micro = defineCollection({
+const pleroma = defineCollection({
loader: pleromaLoader({
instanceUrl: "https://social.craftknight.com",
username: "dawid",
@@ -51,23 +53,8 @@ const micro = defineCollection({
sourceUrl: z.string().optional(),
language: z.string().optional(),
tags: z.array(z.string()).default([]).transform(removeDupsAndLowerCase),
- author: z
- .object({
- username: z.string(),
- displayName: z.string().optional(),
- acct: z.string(),
- url: z.string().optional(),
- })
- .optional(),
- attachments: z
- .array(
- z.object({
- url: z.string(),
- type: z.string(),
- alt: z.string().optional(),
- }),
- )
- .optional(),
+ draft: z.boolean().default(false),
+ author: z.string().optional(),
}),
});
@@ -79,4 +66,4 @@ const tag = defineCollection({
}),
});
-export const collections = { post, tag, micro };
+export const collections = { post, tag, pleroma };
diff --git a/src/content/post/devops-mindset.md b/src/content/post/devops-mindset.md
index 166d282..7761cc3 100644
--- a/src/content/post/devops-mindset.md
+++ b/src/content/post/devops-mindset.md
@@ -4,6 +4,7 @@ description: "DevOps - culture, mindset and processes"
publishDate: "3 July 2025"
tags: ["devops101", devops]
draft: false
+author: "Dawid"
---
## DevOps Mindset
diff --git a/src/content/post/fediverse-101.md b/src/content/post/fediverse-101.md
index 6c248b9..595606b 100644
--- a/src/content/post/fediverse-101.md
+++ b/src/content/post/fediverse-101.md
@@ -4,6 +4,7 @@ description: "A short collection of resources and links for getting started with
publishDate: 19 Dec 2025
tags: [fediverse, social]
draft: false
+author: "Dawid"
---
## Fediverse 101
diff --git a/src/content/post/niedziela-11-wrzesnia-2022.md b/src/content/post/niedziela-11-wrzesnia-2022.md
index 6f5a31a..3f47dec 100644
--- a/src/content/post/niedziela-11-wrzesnia-2022.md
+++ b/src/content/post/niedziela-11-wrzesnia-2022.md
@@ -3,6 +3,7 @@ title: "Niedziela 11 września 2022"
description: "Weekend minął jak z bicza strzelił. Zdecydowanie nie był to jeden z tych leniwych weekendów. W sobotę rano poznaliśmy przemiłą starszą parę z Polski."
publishDate: "2022-09-11"
tags: ["archived"]
+author: "Dawid"
---
Weekend minął „jak z bicza strzelił". Zdecydowanie nie był to jeden z tych leniwych weekendów.
diff --git a/src/content/post/piatek-16-wrzesnia-2022.md b/src/content/post/piatek-16-wrzesnia-2022.md
index b6a46a2..104f737 100644
--- a/src/content/post/piatek-16-wrzesnia-2022.md
+++ b/src/content/post/piatek-16-wrzesnia-2022.md
@@ -3,6 +3,7 @@ title: "Piątek 16 września 2022"
description: "Ostatnie dni były wyjątkowo ciepłe. Pogoda sprzyjała plażowaniu, więc po pracy dołączałem do Aleksandry. Mieliśmy swoją miejscówkę koło nadmorskiego baru, który był niestety zamknięty po sezonie."
publishDate: "2022-09-16"
tags: ["archived"]
+author: "Dawid"
---
Ostatnie dni były wyjątkowo ciepłe. Pogoda sprzyjała plażowaniu, więc po pracy dołączałem do Aleksandry. Mieliśmy swoją miejscówkę koło nadmorskiego baru, który był niestety zamknięty po sezonie. Rumuńskie plaże całe są w muszelkach. Większe i jeszcze ostre muszle są bliżej wody, natomiast mniejsze kawałki – już pokruszone – tworzą specyficzny "piasek".
diff --git a/src/content/post/piatek-7-pazdziernika-2022.md b/src/content/post/piatek-7-pazdziernika-2022.md
index 72819db..d278fd3 100644
--- a/src/content/post/piatek-7-pazdziernika-2022.md
+++ b/src/content/post/piatek-7-pazdziernika-2022.md
@@ -3,6 +3,7 @@ title: "Piątek 7 października 2022"
description: "Dotarłem na jedno z najbardziej epickich miejsc, w których zdarzyło nam się spać. Wysokie klify, rozległa polana, ogromne przestrzenie i tylko wypasające się konie, owce i kozy."
publishDate: "2022-10-07"
tags: ["archived"]
+author: "Dawid"
---
Dotarłem na jedno z najbardziej epickich miejsc, w których zdarzyło nam się spać. Wysokie klify, rozległa polana, ogromne przestrzenie i tylko wypasające się konie, owce i kozy. Nocą na horyzoncie widać światła Ahtopola, ale poza nimi tylko Księżyc i Jowisz rozświetla okolicę. Nad samą przepaścią ktoś wystawił stolik, krzesło i dalej ławkę, na których co kilka godzin ktoś przyjeżdża zrobić sobie zdjęcia.
diff --git a/src/content/post/piatek-9-wrzesnia-2022.md b/src/content/post/piatek-9-wrzesnia-2022.md
index 005a673..2ccd517 100644
--- a/src/content/post/piatek-9-wrzesnia-2022.md
+++ b/src/content/post/piatek-9-wrzesnia-2022.md
@@ -3,6 +3,7 @@ title: "Piątek 9 września 2022"
description: "Ostatnie dni miałem bardzo zawalone w pracy. Dużo spotkań, przygotowywania prezentacji, prowadzenie treningów – w sumie poza siedzeniem w laptopie niewiele się wydarzyło."
publishDate: "2022-09-09"
tags: ["archived"]
+author: "Dawid"
---
Ostatnie dni miałem bardzo zawalone w pracy. Dużo spotkań, przygotowywania prezentacji, prowadzenie treningów – w sumie poza siedzeniem w laptopie niewiele się wydarzyło. Wiatr za to tak zaczął doskwierać, że musieliśmy zwinąć markizę i prawie całe dwa dni spędziłem w kamperze. Przynajmniej Freja przestała nam plątać się we wsporniki i linki 🙂
diff --git a/src/content/post/poniedzialek-3-pazdziernika-2022.md b/src/content/post/poniedzialek-3-pazdziernika-2022.md
index 9ac4688..f4088ed 100644
--- a/src/content/post/poniedzialek-3-pazdziernika-2022.md
+++ b/src/content/post/poniedzialek-3-pazdziernika-2022.md
@@ -3,6 +3,7 @@ title: "Poniedziałek 3 października 2022"
description: "W czwartek rano już się upewniłem, że na skarpie zaparkował Groszek – zielony VW T4 który należy do kampermaniaków. Skończyło mi się wolne, więc szybko tylko poszedłem z Freją po banice do ajranu..."
publishDate: "2022-10-03"
tags: ["archived"]
+author: "Dawid"
---
W czwartek rano już się upewniłem, że na skarpie zaparkował Groszek – zielony VW T4 który należy do [kampermaniaków](https://kampermaniak.pl). Skończyło mi się wolne, więc szybko tylko poszedłem z Freją po banice do ajranu, rozłożyłem "biuro" i zacząłem normalny dzień pracy. Jak to ja – nawet na popołudniowym spacerze nie zebrałem się, żeby zagadać, a wieczorem już widziałem, że wszyscy siedzieli i nie chciałem przeszkadzać.
diff --git a/src/content/post/poniedzialek-5-wrzesnia-2022.md b/src/content/post/poniedzialek-5-wrzesnia-2022.md
index d3456c0..369f091 100644
--- a/src/content/post/poniedzialek-5-wrzesnia-2022.md
+++ b/src/content/post/poniedzialek-5-wrzesnia-2022.md
@@ -3,6 +3,7 @@ title: "Poniedziałek 5 września 2022"
description: "Postanowiliśmy zostać tutaj na dłużej. Miejsce do którego dojechaliśmy okazało się być plażą pełną przyczep kempingowych i kamperów. Mamy widok z okna na morze, szybki internet, dużo słońca (prądu) oraz proste podłoże."
publishDate: "2022-09-05"
tags: ["archived"]
+author: "Dawid"
---
Postanowiliśmy zostać tutaj na dłużej. Miejsce do którego dojechaliśmy okazało się być plażą pełną przyczep kempingowych i kamperów. Mamy widok z okna na morze, szybki internet, dużo słońca (prądu) oraz proste podłoże. Chyba gdzieś w okolicy jest źródło wody (przynajmniej na to wygląda sądząc po ludziach noszących butelki).
diff --git a/src/content/post/sobota-3-wrzesnia-2022.md b/src/content/post/sobota-3-wrzesnia-2022.md
index a77cdb4..0aeb464 100644
--- a/src/content/post/sobota-3-wrzesnia-2022.md
+++ b/src/content/post/sobota-3-wrzesnia-2022.md
@@ -3,6 +3,7 @@ title: "Sobota 3 września 2022"
description: "Dzień wyjazdu z Bukaresztu i ogarniania auta po tygodniu w wynajętym mieszkaniu. Wodę pozwolili nam nalać na stacji po tankowaniu auta, kasete zlaliśmy na parkingu dla kamperów, a po drodze kupiliśmy jeszcze karmę dla Freji."
publishDate: "2022-09-03"
tags: ["archived"]
+author: "Dawid"
---
Dzień wyjazdu z Bukaresztu i ogarniania auta po tygodniu w wynajętym mieszkaniu. Wodę pozwolili nam nalać na stacji po tankowaniu auta, kasete zlaliśmy na parkingu dla kamperów, a po drodze kupiliśmy jeszcze karmę dla Freji.
diff --git a/src/content/post/sroda-21-wrzesnia-2022.md b/src/content/post/sroda-21-wrzesnia-2022.md
index ae2665a..1ff94b5 100644
--- a/src/content/post/sroda-21-wrzesnia-2022.md
+++ b/src/content/post/sroda-21-wrzesnia-2022.md
@@ -3,6 +3,7 @@ title: "Środa 21 września 2022"
description: "W pierwszych dniach pobytu w Bułgarii mieliśmy nieco szczęścia. Warna przywitała nas burzą i oberwaniem chmury. W trakcie spaceru po mieście zerwał się deszcz i przemokliśmy do suchej nitki w przeciągu kilku minut."
publishDate: "2022-09-21"
tags: ["archived"]
+author: "Dawid"
---
W pierwszych dniach pobytu w Bułgarii mieliśmy nieco szczęścia. Warna przywitała nas burzą i oberwaniem chmury. W trakcie spaceru po mieście zerwał się deszcz i przemokliśmy do suchej nitki w przeciągu kilku minut. W tym samym czasie, kilkadziesiąt kilometrów na południe, przez Brugas przeszedł huragan który zrywał dachy i łamał drzewa. Dobrze, że zamarudziliśmy trochę i zwiedziliśmy jeszcze po drodze kamienny las.
diff --git a/src/content/post/sroda-28-wrzesnia-2022.md b/src/content/post/sroda-28-wrzesnia-2022.md
index 884ec2f..e0a456b 100644
--- a/src/content/post/sroda-28-wrzesnia-2022.md
+++ b/src/content/post/sroda-28-wrzesnia-2022.md
@@ -3,6 +3,7 @@ title: "Środa 28 września 2022"
description: "Wziąłem parę dni wolnego, abyśmy mogli spokojnie pozwiedzać okolicę. Zaczęliśmy od oddania rzeczy do pralni. Niestety w Bułgarii pralki na monety nie są popularne."
publishDate: "2022-09-28"
tags: ["archived"]
+author: "Dawid"
---
## Nesebar
diff --git a/src/content/post/sroda-7-wrzesnia-2022.md b/src/content/post/sroda-7-wrzesnia-2022.md
index 2b70da1..50b2e13 100644
--- a/src/content/post/sroda-7-wrzesnia-2022.md
+++ b/src/content/post/sroda-7-wrzesnia-2022.md
@@ -3,6 +3,7 @@ title: "Środa 7 września 2022"
description: "Musieliśmy się dzisiaj ruszyć po wodę. Źródełko płynące z rury koło domku rybaka okazało się na tyle brudne, że nie ryzykowaliśmy zalewać nim zbiornika w kamperze."
publishDate: "2022-09-07"
tags: ["archived"]
+author: "Dawid"
---
Musieliśmy się dzisiaj ruszyć po wodę. Źródełko płynące z rury koło domku rybaka okazało się na tyle brudne, że nie ryzykowaliśmy zalewać nim zbiornika w kamperze. Może i dało by się w nim wykąpać, ale bez wstępnej filtracji tylko by zasyfiło pompę, przewody i krany. Przy okazji zrobiliśmy zakupy w lokalnym Lidlu i umyliśmy auto (było całe od błota po sobotnich "przygodach").
diff --git a/src/content/post/wtorek-13-wrzesnia-2022.md b/src/content/post/wtorek-13-wrzesnia-2022.md
index 4023696..09dacc1 100644
--- a/src/content/post/wtorek-13-wrzesnia-2022.md
+++ b/src/content/post/wtorek-13-wrzesnia-2022.md
@@ -3,6 +3,7 @@ title: "Wtorek 13 września 2022"
description: "Przez jeden dzień mieliśmy nowe zwierzątko – konkretnie nietoperza. W poniedziałek nad ranem coś wpadło pomiędzy moskitierę, a okno dachowe i strasznie hałasowało."
publishDate: "2022-09-13"
tags: ["archived"]
+author: "Dawid"
---
Przez jeden dzień mieliśmy nowe zwierzątko – konkretnie nietoperza. W poniedziałek nad ranem coś wpadło pomiędzy moskitierę, a okno dachowe i strasznie hałasowało. Na początku myśleliśmy, że to mały ptak lub ćma, ale kiedy próbowałem uchylić trochę bardziej okno, to "coś" zatrzymało się na moskitierze. Nietoperz wcisnął się w szczelinę pomiędzy dachem Sprintera, a drewnianym sufitem i poszedł spać na cały dzień. Swoją drogą tak dowiedzieliśmy się, że jest tam przejście znad moskitiery pod dach i trzeba się tym zająć.
diff --git a/src/data/post.ts b/src/data/post.ts
index 7cadb93..85cc0d0 100644
--- a/src/data/post.ts
+++ b/src/data/post.ts
@@ -1,16 +1,18 @@
import { type CollectionEntry, getCollection } from "astro:content";
-/** filter out draft posts based on the environment and optionally archived posts and micro posts */
-export async function getAllPosts(
- includeArchived = false,
- includeMicro = false,
-): Promise<CollectionEntry<"post">[]> {
- return await getCollection("post", ({ data }) => {
+/** filter out draft posts based on the environment and optionally archived posts */
+export async function getAllPosts(includeArchived = false): Promise<CollectionEntry<"post">[]> {
+ const posts = await getCollection("post", ({ data }) => {
const isDraftFilter = import.meta.env.PROD ? !data.draft : true;
const isArchivedFilter = includeArchived || !data.tags.includes("archived");
- const isMicroFilter = includeMicro || !data.tags.includes("micro");
- return isDraftFilter && isArchivedFilter && isMicroFilter;
+ return isDraftFilter && isArchivedFilter;
});
+
+ // Fetch pleroma posts and cast them to post type since schemas are now compatible
+ const pleromaPosts = await getCollection("pleroma").catch(() => []);
+ const pleromaAsPost = pleromaPosts as unknown as CollectionEntry<"post">[];
+
+ return [...posts, ...pleromaAsPost];
}
/** Get tag metadata by tag name */
diff --git a/src/layouts/BlogPost.astro b/src/layouts/BlogPost.astro
index 9c60900..59f7282 100644
--- a/src/layouts/BlogPost.astro
+++ b/src/layouts/BlogPost.astro
@@ -33,6 +33,20 @@ const readingTime: string = remarkPluginFrontmatter.readingTime;
>
<slot />
<WebMentions />
+ {
+ post.data.sourceUrl && (
+ <p class="mt-8 border-t border-gray-200 pt-6 text-sm dark:border-gray-700">
+ <a
+ href={post.data.sourceUrl}
+ class="cactus-link"
+ target="_blank"
+ rel="noopener noreferrer"
+ >
+ View original post on Pleroma →
+ </a>
+ </p>
+ )
+ }
</div>
</article>
<button
diff --git a/src/loaders/pleroma.ts b/src/loaders/pleroma.ts
index c57a22b..b3fa8ff 100644
--- a/src/loaders/pleroma.ts
+++ b/src/loaders/pleroma.ts
@@ -265,12 +265,8 @@ function extractTrailingHashtags(content: string): {
/**
* Merge thread posts into a single content structure with image grids per segment
*/
-function mergeThreadContent(chain: PleromaStatus[]): {
- content: string;
- attachments: Array<{ url: string; type: string }>;
-} {
+function mergeThreadContent(chain: PleromaStatus[]): string {
const segments: string[] = [];
- const allAttachments: Array<{ url: string; type: string }> = [];
const allTags = new Set<string>(); // Collect all tags from all segments
for (const post of chain) {
@@ -286,28 +282,9 @@ function mergeThreadContent(chain: PleromaStatus[]): {
let segment = mainContent;
// Add image attachments as HTML grid after the text
- const imageAttachments = post.media_attachments.filter(
- (attachment) => attachment.type === "image",
- );
-
- if (imageAttachments.length > 0) {
- // Build HTML grid for images
- const imageGrid = `
-<div class="mt-4 mb-4 grid grid-cols-1 gap-4 sm:grid-cols-2">
-${imageAttachments
- .map((attachment) => {
- const description = attachment.description || "Image";
- allAttachments.push({
- url: attachment.url,
- type: `image/${attachment.url.split(".").pop() || "jpeg"}`,
- });
- return `<a href="${attachment.url}" target="_blank" rel="noopener noreferrer" class="block overflow-hidden rounded-lg border border-gray-200 transition-colors hover:border-gray-300 dark:border-gray-700 dark:hover:border-gray-600">
-<img src="${attachment.url}" alt="${description}" class="h-48 w-full object-cover" loading="lazy" />
-</a>`;
- })
- .join("\n")}
-</div>`;
+ const imageGrid = buildImageGridHtml(post.media_attachments);
+ if (imageGrid) {
segment = `${segment}\n\n${imageGrid}`;
}
@@ -323,7 +300,7 @@ ${imageAttachments
content = `${content}\n\n${tagLine}`;
}
- return { content, attachments: [] }; // Return empty attachments to avoid duplicate grid at end
+ return content;
}
async function getAccountId(
@@ -539,6 +516,30 @@ function cleanContent(htmlContent: string): string {
}
/**
+ * Build HTML grid for image attachments
+ * Returns empty string if no image attachments are provided
+ */
+function buildImageGridHtml(attachments: PleromaMediaAttachment[]): string {
+ const imageAttachments = attachments.filter((attachment) => attachment.type === "image");
+
+ if (imageAttachments.length === 0) {
+ return "";
+ }
+
+ return `
+<div class="mt-4 mb-4 grid grid-cols-1 gap-4 sm:grid-cols-2">
+${imageAttachments
+ .map((attachment) => {
+ const description = attachment.description || "Image";
+ return `<a href="${attachment.url}" target="_blank" rel="noopener noreferrer" class="block overflow-hidden rounded-lg border border-gray-200 transition-colors hover:border-gray-300 dark:border-gray-700 dark:hover:border-gray-600">
+<img src="${attachment.url}" alt="${description}" class="h-48 w-full object-cover" loading="lazy" />
+</a>`;
+ })
+ .join("\n")}
+</div>`;
+}
+
+/**
* Replace all hashtags in content with internal tag links
* Handles both plain #hashtags and existing markdown links [#tag](url)
* Returns modified content and extracted tags array
@@ -587,7 +588,7 @@ function replacePleromaLinks(
const markdownLinkRegex = new RegExp(`\\[([^\\]]+)\\]\\(${noticePattern}\\)`, "g");
let modifiedContent = content.replace(markdownLinkRegex, (match, linkText, statusId) => {
if (existingPostIds.has(statusId)) {
- return `[${linkText}](/micro/pleroma-${statusId}/)`;
+ return `[${linkText}](/posts/pleroma-${statusId}/)`;
}
return match; // Keep original if post doesn't exist
});
@@ -597,7 +598,7 @@ function replacePleromaLinks(
const plainUrlRegex = new RegExp(`(?<!\\()${noticePattern}(?!\\))`, "g");
modifiedContent = modifiedContent.replace(plainUrlRegex, (match, statusId) => {
if (existingPostIds.has(statusId)) {
- return `/micro/pleroma-${statusId}/`;
+ return `/posts/pleroma-${statusId}/`;
}
return match; // Keep original if post doesn't exist
});
@@ -679,7 +680,6 @@ export function pleromaLoader(config: PleromaFeedConfig): Loader {
try {
const content = status.content || "";
let cleanedContent: string;
- let attachments: Array<{ url: string; type: string }>;
let postId: string;
let sourceUrl: string;
let tags: string[];
@@ -695,13 +695,14 @@ export function pleromaLoader(config: PleromaFeedConfig): Loader {
logger.info(`Built chain with ${chain.length} post(s) for thread ${status.id}`);
// Merge thread content
- const merged = mergeThreadContent(chain);
- const { content: contentWithTags, tags: extractedTags } = replaceHashtagsWithLinks(
- merged.content,
- );
- tags = [...extractedTags, "micro"];
+ const mergedContent = mergeThreadContent(chain);
+ const { content: contentWithTags, tags: extractedTags } =
+ replaceHashtagsWithLinks(mergedContent);
+ // Add microblog tag if not already present
+ tags = extractedTags.includes("microblog")
+ ? extractedTags
+ : [...extractedTags, "microblog"];
cleanedContent = replacePleromaLinks(contentWithTags, instanceUrl, allPostIds);
- attachments = merged.attachments;
postId = status.id;
sourceUrl = status.url;
} else {
@@ -709,31 +710,26 @@ export function pleromaLoader(config: PleromaFeedConfig): Loader {
const rawContent = cleanContent(content);
const { content: contentWithTags, tags: extractedTags } =
replaceHashtagsWithLinks(rawContent);
- tags = [...extractedTags, "micro"];
- cleanedContent = replacePleromaLinks(contentWithTags, instanceUrl, allPostIds);
+ // Add microblog tag if not already present
+ tags = extractedTags.includes("microblog")
+ ? extractedTags
+ : [...extractedTags, "microblog"];
+ const contentWithLinks = replacePleromaLinks(
+ contentWithTags,
+ instanceUrl,
+ allPostIds,
+ );
+
+ // Build image grid HTML and append to content for RSS feeds
+ const imageGrid = buildImageGridHtml(status.media_attachments);
+ cleanedContent = imageGrid ? `${contentWithLinks}\n\n${imageGrid}` : contentWithLinks;
+
postId = status.id;
sourceUrl = status.url;
-
- // Extract image attachments only
- attachments = status.media_attachments
- .filter((attachment) => attachment.type === "image")
- .map((attachment) => ({
- url: attachment.url,
- type: `image/${attachment.url.split(".").pop() || "jpeg"}`,
- alt: attachment.description || undefined,
- }));
}
const title = extractTitle(cleanedContent);
- // Extract author information from status account
- const author = {
- username: status.account.username,
- displayName: status.account.display_name || undefined,
- acct: status.account.acct,
- url: status.account.url || undefined,
- };
-
// Create note entry
store.set({
id: `pleroma-${postId}`,
@@ -743,10 +739,10 @@ export function pleromaLoader(config: PleromaFeedConfig): Loader {
cleanedContent.substring(0, 160) + (cleanedContent.length > 160 ? "..." : ""),
publishDate: new Date(status.created_at),
sourceUrl,
- author,
- attachments,
language: status.language || undefined,
tags,
+ draft: false,
+ author: "Dawid",
},
body: cleanedContent,
rendered: {
diff --git a/src/pages/index.astro b/src/pages/index.astro
index 1bc088c..e3884ef 100644
--- a/src/pages/index.astro
+++ b/src/pages/index.astro
@@ -1,23 +1,27 @@
---
-import { type CollectionEntry, getCollection } from "astro:content";
+import type { CollectionEntry } from "astro:content";
import PostPreview from "@/components/blog/PostPreview.astro";
-import Note from "@/components/note/Note.astro";
import SocialList from "@/components/SocialList.astro";
import { getAllPosts } from "@/data/post";
import PageLayout from "@/layouts/Base.astro";
import { collectionDateSort } from "@/utils/date";
-// Posts
-const MAX_POSTS = 10;
+// Get all posts
const allPosts = await getAllPosts();
-const allPostsByDate = allPosts
+
+// Posts section - exclude archived and microblog
+const MAX_POSTS = 10;
+const regularPosts = allPosts.filter(
+ (post) => !post.data.tags.includes("archived") && !post.data.tags.includes("microblog"),
+);
+const allPostsByDate = regularPosts
.sort(collectionDateSort)
.slice(0, MAX_POSTS) as CollectionEntry<"post">[];
-// Micro
-const MAX_MICRO = 5;
-const allMicro = await getCollection("micro").catch(() => []); // Fallback to empty array if micro collection fails
-const latestMicro = allMicro.sort(collectionDateSort).slice(0, MAX_MICRO);
+// Microblog posts section - only posts with microblog tag
+const MAX_MICROBLOG = 5;
+const allMicroblogPosts = allPosts.filter((post) => post.data.tags.includes("microblog"));
+const latestMicroblog = allMicroblogPosts.sort(collectionDateSort).slice(0, MAX_MICROBLOG);
---
<PageLayout meta={{ title: "Home" }}>
@@ -46,15 +50,15 @@ const latestMicro = allMicro.sort(collectionDateSort).slice(0, MAX_MICRO);
</ul>
</section>
{
- latestMicro.length > 0 && (
+ latestMicroblog.length > 0 && (
<section class="mt-16">
<h2 class="title text-accent mb-6 text-xl">
- <a href="/tags/micro/">Micro</a>
+ <a href="/tags/microblog/">Microblog</a>
</h2>
<ul class="space-y-6" role="list">
- {latestMicro.map((note) => (
- <li>
- <Note note={note} as="h3" isPreview />
+ {latestMicroblog.map((post) => (
+ <li class="grid gap-2 sm:grid-cols-[auto_1fr]">
+ <PostPreview post={post} as="h3" />
</li>
))}
</ul>
diff --git a/src/pages/micro/[...slug].astro b/src/pages/micro/[...slug].astro
deleted file mode 100644
index 681c106..0000000
--- a/src/pages/micro/[...slug].astro
+++ /dev/null
@@ -1,34 +0,0 @@
----
-import { getCollection } from "astro:content";
-import type { GetStaticPaths, InferGetStaticPropsType } from "astro";
-import Note from "@/components/note/Note.astro";
-import PageLayout from "@/layouts/Base.astro";
-import { siteConfig } from "@/site.config";
-
-// if you're using an adaptor in SSR mode, getStaticPaths wont work -> https://docs.astro.build/en/guides/routing/#modifying-the-slug-example-for-ssr
-export const getStaticPaths = (async () => {
- // Get only Pleroma posts
- const allMicro = await getCollection("micro").catch(() => []); // Fallback to empty array if micro collection fails
-
- return allMicro.map((post) => ({
- params: { slug: post.id },
- props: { note: post }, // Keep 'note' name for compatibility with existing component
- }));
-}) satisfies GetStaticPaths;
-
-export type Props = InferGetStaticPropsType<typeof getStaticPaths>;
-
-const { note } = Astro.props;
-
-const meta = {
- description:
- note.data.description ||
- `Read about my note posted on: ${note.data.publishDate.toLocaleDateString()}`,
- title: note.data.title,
- lang: note.data.language || siteConfig.lang,
-};
----
-
-<PageLayout meta={meta}>
- <Note as="h1" note={note} />
-</PageLayout>
diff --git a/src/pages/posts/[...page].astro b/src/pages/posts/[...page].astro
index acca040..d318525 100644
--- a/src/pages/posts/[...page].astro
+++ b/src/pages/posts/[...page].astro
@@ -12,7 +12,11 @@ export const getStaticPaths = (async ({ paginate }) => {
const MAX_POSTS_PER_PAGE = 10;
const MAX_TAGS = 7;
const allPosts = await getAllPosts();
- const sortedPosts = allPosts.sort(collectionDateSort);
+ // Filter out archived and microblog posts from main posts page
+ const filteredPosts = allPosts.filter(
+ (post) => !post.data.tags.includes("archived") && !post.data.tags.includes("microblog"),
+ );
+ const sortedPosts = filteredPosts.sort(collectionDateSort);
const uniqueTags = getUniqueTags(sortedPosts).slice(0, MAX_TAGS);
return paginate(sortedPosts, {
pageSize: MAX_POSTS_PER_PAGE,
diff --git a/src/pages/rss.xml.ts b/src/pages/rss.xml.ts
index 39f3964..d428cc9 100644
--- a/src/pages/rss.xml.ts
+++ b/src/pages/rss.xml.ts
@@ -15,6 +15,7 @@ export const GET = async (context: APIContext) => {
description: post.data.description,
pubDate: post.data.publishDate,
link: `posts/${post.id}/`,
+ author: post.data.author,
})),
customData: `<atom:link href="${context.site}rss.xml" rel="self" type="application/rss+xml" xmlns:atom="http://www.w3.org/2005/Atom" />`,
});
diff --git a/src/pages/tags/[tag]/[...page].astro b/src/pages/tags/[tag]/[...page].astro
index 9556309..8ae9716 100644
--- a/src/pages/tags/[tag]/[...page].astro
+++ b/src/pages/tags/[tag]/[...page].astro
@@ -1,35 +1,27 @@
---
-import { getCollection, render } from "astro:content";
+import { render } from "astro:content";
import type { GetStaticPaths, InferGetStaticPropsType } from "astro";
import { Icon } from "astro-icon/components";
import PostPreview from "@/components/blog/PostPreview.astro";
-import Note from "@/components/note/Note.astro";
import Pagination from "@/components/Paginator.astro";
import { getAllPosts, getTagMeta, getUniqueTags } from "@/data/post";
import PageLayout from "@/layouts/Base.astro";
import { collectionDateSort } from "@/utils/date";
-import { getUniqueMicroTags } from "@/utils/micro";
export const getStaticPaths = (async ({ paginate }) => {
- const allPosts = await getAllPosts(true, true); // Include archived and micro posts for tag filtering
- const allMicro = await getCollection("micro", ({ data }) => data.tags?.includes("micro")).catch(
- () => [],
- );
+ const allPosts = await getAllPosts(true); // Include archived posts (now includes pleroma too)
- // Get unique tags from both collections
- const postTags = getUniqueTags(allPosts);
- const microTags = getUniqueMicroTags(allMicro);
- const allTags = [...new Set([...postTags, ...microTags])];
+ // Get unique tags from all posts
+ const allTags = getUniqueTags(allPosts);
return allTags.flatMap((tag) => {
- // Filter posts and micro posts by tag
+ // Filter posts by tag
const postsWithTag = allPosts.filter((post) => post.data.tags.includes(tag));
- const microWithTag = allMicro.filter((micro) => micro.data.tags?.includes(tag));
- // Combine and sort chronologically
- const allItems = [...postsWithTag, ...microWithTag].sort(collectionDateSort);
+ // Sort chronologically
+ const sortedPosts = postsWithTag.sort(collectionDateSort);
- return paginate(allItems, {
+ return paginate(sortedPosts, {
pageSize: 10,
params: { tag },
});
@@ -55,13 +47,13 @@ const meta = {
const paginationProps = {
...(page.url.prev && {
prevUrl: {
- text: "← Previous Tags",
+ text: "← Previous posts",
url: page.url.prev,
},
}),
...(page.url.next && {
nextUrl: {
- text: "Next Tags →",
+ text: "Next posts →",
url: page.url.next,
},
}),
@@ -96,17 +88,11 @@ const paginationProps = {
</div>
<ul class="space-y-6">
{
- page.data.map((item) =>
- item.collection === "post" ? (
- <li class="grid gap-2 sm:grid-cols-[auto_1fr]">
- <PostPreview as="h2" post={item} />
- </li>
- ) : (
- <li>
- <Note note={item} as="h2" isPreview />
- </li>
- ),
- )
+ page.data.map((post) => (
+ <li class="grid gap-2 sm:grid-cols-[auto_1fr]">
+ <PostPreview as="h2" post={post} />
+ </li>
+ ))
}
</ul>
<Pagination {...paginationProps} />
diff --git a/src/pages/tags/[tag]/rss.xml.ts b/src/pages/tags/[tag]/rss.xml.ts
index 3fc8ff3..3a61414 100644
--- a/src/pages/tags/[tag]/rss.xml.ts
+++ b/src/pages/tags/[tag]/rss.xml.ts
@@ -1,21 +1,14 @@
-import { getCollection } from "astro:content";
import rss from "@astrojs/rss";
import type { APIContext } from "astro";
import { getAllPosts, getUniqueTags } from "@/data/post";
import { siteConfig } from "@/site.config";
-import { getUniqueMicroTags } from "@/utils/micro";
export async function getStaticPaths() {
- // Get all posts (including archived) and micro posts to extract all possible tags
- const allPosts = await getAllPosts(true, true); // Include archived and micro
- const allMicro = await getCollection("micro", ({ data }) => data.tags?.includes("micro")).catch(
- () => [],
- );
+ // Get all posts (including archived, now includes pleroma too)
+ const allPosts = await getAllPosts(true);
- // Get unique tags from both collections
- const postTags = getUniqueTags(allPosts);
- const microTags = getUniqueMicroTags(allMicro);
- const allTags = [...new Set([...postTags, ...microTags])];
+ // Get unique tags from all posts
+ const allTags = getUniqueTags(allPosts);
return allTags.map((tag) => ({
params: { tag },
@@ -29,33 +22,14 @@ export const GET = async (context: APIContext) => {
throw new Error("Tag parameter is required");
}
- // Get posts with this tag (include archived and micro)
- const allPosts = await getAllPosts(true, true);
+ // Get posts with this tag (include archived)
+ const allPosts = await getAllPosts(true);
const postsWithTag = allPosts.filter((post) => post.data.tags.includes(tag));
- // Get micro posts with this tag
- const allMicro = await getCollection("micro", ({ data }) => data.tags?.includes("micro")).catch(
- () => [],
+ // Sort chronologically
+ const sortedPosts = postsWithTag.sort(
+ (a, b) => b.data.publishDate.getTime() - a.data.publishDate.getTime(),
);
- const microWithTag = allMicro.filter((micro) => micro.data.tags?.includes(tag));
-
- // Combine and sort chronologically
- const allItems = [
- ...postsWithTag.map((post) => ({
- title: post.data.title,
- description: post.data.description,
- pubDate: post.data.publishDate,
- link: `posts/${post.id}/`,
- content: undefined,
- })),
- ...microWithTag.map((micro) => ({
- title: micro.data.title,
- description: micro.data.description,
- pubDate: micro.data.publishDate,
- link: `micro/${micro.id}/`,
- content: micro.rendered?.html || micro.body || "",
- })),
- ].sort((a, b) => b.pubDate.getTime() - a.pubDate.getTime());
const site = context.site || import.meta.env.SITE;
@@ -63,7 +37,13 @@ export const GET = async (context: APIContext) => {
title: `${siteConfig.title} - ${tag}`,
description: `Posts tagged with ${tag}`,
site,
- items: allItems,
+ items: sortedPosts.map((post) => ({
+ title: post.data.title,
+ description: post.data.description,
+ pubDate: post.data.publishDate,
+ link: `posts/${post.id}/`,
+ author: post.data.author,
+ })),
customData: `<atom:link href="${site}tags/${tag}/rss.xml" rel="self" type="application/rss+xml" xmlns:atom="http://www.w3.org/2005/Atom" />`,
});
};
diff --git a/src/pages/tags/index.astro b/src/pages/tags/index.astro
index 2c7b07b..260a4fa 100644
--- a/src/pages/tags/index.astro
+++ b/src/pages/tags/index.astro
@@ -1,29 +1,12 @@
---
-import { getCollection } from "astro:content";
import { getAllPosts, getUniqueTagsWithCount } from "@/data/post";
import PageLayout from "@/layouts/Base.astro";
-import { getUniqueMicroTagsWithCount } from "@/utils/micro";
-const allPostsIncludingArchived = await getAllPosts(true, true); // Include archived and micro
-const allMicro = await getCollection("micro", ({ data }) => data.tags?.includes("micro")).catch(
- () => [],
-);
+// Get all posts including archived (now includes pleroma posts too)
+const allPostsIncludingArchived = await getAllPosts(true);
-// Get tags with counts from both collections
-const postTags = getUniqueTagsWithCount(allPostsIncludingArchived);
-const microTags = getUniqueMicroTagsWithCount(allMicro);
-
-// Merge tags and sum counts
-const tagMap = new Map<string, number>();
-for (const [tag, count] of postTags) {
- tagMap.set(tag, count);
-}
-for (const [tag, count] of microTags) {
- tagMap.set(tag, (tagMap.get(tag) || 0) + count);
-}
-
-// Convert back to array and sort by count
-const allTags = Array.from(tagMap.entries()).sort((a, b) => b[1] - a[1]);
+// Get tags with counts from all posts
+const allTags = getUniqueTagsWithCount(allPostsIncludingArchived);
const meta = {
description: "A list of all the topics I've written about in my posts",
diff --git a/src/site.config.ts b/src/site.config.ts
index d9b395c..d2fa871 100644
--- a/src/site.config.ts
+++ b/src/site.config.ts
@@ -46,8 +46,8 @@ export const menuLinks: { path: string; title: string }[] = [
title: "Blog",
},
{
- path: "/tags/micro/",
- title: "Micro",
+ path: "/tags/microblog/",
+ title: "Microblog",
},
{
path: "/privacy-policy/",
diff --git a/src/utils/date.ts b/src/utils/date.ts
index b8c0376..314a837 100644
--- a/src/utils/date.ts
+++ b/src/utils/date.ts
@@ -15,9 +15,6 @@ export function getFormattedDate(
}).format(date);
}
-export function collectionDateSort(
- a: CollectionEntry<"post" | "micro">,
- b: CollectionEntry<"post" | "micro">,
-) {
+export function collectionDateSort(a: CollectionEntry<"post">, b: CollectionEntry<"post">) {
return b.data.publishDate.getTime() - a.data.publishDate.getTime();
}
diff --git a/src/utils/micro.ts b/src/utils/micro.ts
deleted file mode 100644
index 7f06b41..0000000
--- a/src/utils/micro.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-import type { CollectionEntry } from "astro:content";
-
-export type MicroEntry = CollectionEntry<"micro">;
-
-export function sortMicroEntries(entries: MicroEntry[]): MicroEntry[] {
- return entries.sort((a, b) => b.data.publishDate.getTime() - a.data.publishDate.getTime());
-}
-
-export async function getAllMicroPosts(): Promise<MicroEntry[]> {
- const { getCollection } = await import("astro:content");
-
- // Get only Pleroma micro posts
- try {
- const microPosts = await getCollection("micro");
- return sortMicroEntries(microPosts);
- } catch (error) {
- console.warn("Micro collection not available:", error);
- return [];
- }
-}
-
-/** Extract all tags from micro posts */
-export function getAllMicroTags(entries: MicroEntry[]): string[] {
- return entries.flatMap((entry) => entry.data.tags ?? []);
-}
-
-/** Get unique tags from micro posts */
-export function getUniqueMicroTags(entries: MicroEntry[]): string[] {
- return [...new Set(getAllMicroTags(entries))];
-}
-
-/** Get unique tags with counts from micro posts */
-export function getUniqueMicroTagsWithCount(entries: MicroEntry[]): [string, number][] {
- return [
- ...getAllMicroTags(entries).reduce(
- (acc, t) => acc.set(t, (acc.get(t) ?? 0) + 1),
- new Map<string, number>(),
- ),
- ].sort((a, b) => b[1] - a[1]);
-}