]> git.otsuka.systems Git - cotsuka.github.io/commitdiff
create missive and marginalia article types, add badges
authorCameron Otsuka <cameron@otsuka.haus>
Tue, 14 Apr 2026 06:24:26 +0000 (23:24 -0700)
committerCameron Otsuka <cameron@otsuka.haus>
Tue, 14 Apr 2026 06:24:26 +0000 (23:24 -0700)
70 files changed:
content/articles/bitcoin-mempools-cleared-is-nobody-using-bitcoin/index.mdx
content/articles/minimum-utxo-value/index.mdx
content/articles/monetary-system-enshittification/index.mdx
content/articles/r1-vs-o1-ai-as-commodity-or-moat/index.mdx
content/articles/removing-a-drive-from-a-btrfs-array.mdx
content/reviews/28-days-later.md
content/reviews/a-cinderella-story.md
content/reviews/a-complete-unknown.mdx
content/reviews/boiling-point.md
content/reviews/bugonia.md
content/reviews/burning.md
content/reviews/call-me-by-your-name.md
content/reviews/casino-royale.md
content/reviews/caught-stealing.md
content/reviews/challengers.md
content/reviews/chef.md
content/reviews/conclave.md
content/reviews/death-becomes-her.md
content/reviews/den-of-thieves-pantera.md
content/reviews/donnie-darko.md
content/reviews/f1-the-movie.md
content/reviews/fallen-angels/index.mdx
content/reviews/gnomeo-juliet.md
content/reviews/hamnet.md
content/reviews/house-of-huawei.md
content/reviews/hunchback-of-notre-dame.md
content/reviews/its-whats-inside.md
content/reviews/jurassic-park.md
content/reviews/marty-supreme.md
content/reviews/materialists.md
content/reviews/moulin-rouge.md
content/reviews/mulholland-drive.md
content/reviews/noah.md
content/reviews/nosferatu.md
content/reviews/one-battle-after-another.mdx
content/reviews/patlabor-the-movie.md
content/reviews/people-we-meet-on-vacation.md
content/reviews/perfect-days.md
content/reviews/problemista.md
content/reviews/sinners.md
content/reviews/star-wars-episode-iii-revenge-of-the-sith.md
content/reviews/subservience.md
content/reviews/superman.mdx
content/reviews/taipei-story.md
content/reviews/the-apprentice.md
content/reviews/the-boy-and-the-heron.md
content/reviews/the-godfather.md
content/reviews/the-little-mermaid.md
content/reviews/the-lord-of-the-rings-the-fellowship-of-the-ring.md
content/reviews/the-pianist.md
content/reviews/the-social-network.md
content/reviews/the-swan-princess.md
content/reviews/thunderbolts.md
content/reviews/tick-tick-boom.md
content/reviews/wake up dead man.md
content/reviews/warfare.md
content/reviews/when-harry-met-sally.md
content/reviews/wicked-for-good.mdx
content/reviews/wicked.md
src/components/metadata.astro
src/components/ui/badge.astro [new file with mode: 0644]
src/components/ui/contentlist.astro
src/content.config.ts
src/pages/feed.xml.ts
src/pages/index.astro
src/pages/reviews/[type]/[id]/index.astro [moved from src/pages/reviews/[category]/[id]/index.astro with 92% similarity]
src/pages/reviews/[type]/[id]/opengraph.png.ts [moved from src/pages/reviews/[category]/[id]/opengraph.png.ts with 90% similarity]
src/pages/reviews/index.astro
src/pages/search.astro
src/utils/generateContentUrl.ts

index e71ef36..c931b5f 100644 (file)
@@ -1,5 +1,6 @@
 ---
 title: 'Bitcoin Mempools Cleared: Is Nobody Using Bitcoin?'
+type: missive
 date: 2025-02-09
 modified: 2025-10-24
 description: Bitcoin mempools have cleared before and there's no immediate reason to panic.
index 1e76262..6e679bd 100644 (file)
@@ -1,5 +1,6 @@
 ---
 title: Minimum UTXO Value
+type: missive
 date: 2023-08-04
 modified: 2025-02-07
 description: A look at what Bitcoin dust is, historical fee rates, how fees are calculated, and a decision on a minimum UTXO value to stay above the dust threshold.
index 291ec22..c93d303 100644 (file)
@@ -1,5 +1,6 @@
 ---
 title: Monetary System Enshittification
+type: missive
 date: 2024-03-01
 modified: 2025-01-27
 description: Is the US monetary system experiencing enshittification? And how do we solve it?
index d4110a5..e3086d5 100644 (file)
@@ -1,5 +1,6 @@
 ---
 title: 'R1 vs. o1: AI as Commodity or Moat'
+type: missive
 date: 2025-01-27
 modified: 2025-10-24
 description: Is DeepSeek's R1 an existential threat to OpenAI?
index df09719..c5c765f 100644 (file)
@@ -1,5 +1,6 @@
 ---
 title: 'Removing a Drive from a Btrfs Array'
+type: marginalia
 date: 2023-07-05
 modified: 2024-12-23
 description: If a drive is failing in an array, Btrfs could block attempts at removing the drive due to corrupted files. A quick write-up of how to get it removed.
index e00e3a2..fc9218f 100644 (file)
@@ -1,5 +1,5 @@
 ---
-category: movie
+type: movie
 title: 28 Days Later
 date: 2025-06-06
 modified: 2025-12-07
index b2fc03d..84158bb 100644 (file)
@@ -1,5 +1,5 @@
 ---
-category: movie
+type: movie
 title: A Cinderella Story
 date: 2026-03-15
 modified: 2026-03-16
index ee11b0e..06ed3fd 100644 (file)
@@ -1,5 +1,5 @@
 ---
-category: movie
+type: movie
 title: A Complete Unknown
 date: 2025-06-04
 modified: 2025-06-04
index 93bc683..eff4abc 100644 (file)
@@ -1,5 +1,5 @@
 ---
-category: movie
+type: movie
 title: Boiling Point
 date: 2026-04-11
 modified: 2026-04-11
index 5f0f818..b638bcc 100644 (file)
@@ -1,5 +1,5 @@
 ---
-category: movie
+type: movie
 title: Bugonia
 date: 2025-10-30
 modified: 2025-11-01
index f1bee46..04ca35c 100644 (file)
@@ -1,5 +1,5 @@
 ---
-category: movie
+type: movie
 title: Burning
 date: 2025-02-28
 modified: 2025-03-02
index adaecb7..9848405 100644 (file)
@@ -1,5 +1,5 @@
 ---
-category: movie
+type: movie
 title: Call Me By Your Name
 date: 2026-03-22
 modified: 2026-03-23
index 00786cb..7b4a4f9 100644 (file)
@@ -1,5 +1,5 @@
 ---
-category: movie
+type: movie
 title: Casino Royale
 date: 2025-12-14
 modified: 2025-12-16
index f69da80..42758e6 100644 (file)
@@ -1,5 +1,5 @@
 ---
-category: movie
+type: movie
 title: Caught Stealing
 date: 2025-09-12
 modified: 2025-09-13
index 4ec9100..53c6594 100644 (file)
@@ -1,5 +1,5 @@
 ---
-category: movie
+type: movie
 title: Challengers
 date: 2024-12-24
 modified: 2024-12-26
index 4959c5a..2eb6330 100644 (file)
@@ -1,5 +1,5 @@
 ---
-category: movie
+type: movie
 title: Chef
 date: 2026-03-14
 modified: 2026-03-16
index 3097f36..f44e43f 100644 (file)
@@ -1,5 +1,5 @@
 ---
-category: movie
+type: movie
 title: Conclave
 date: 2025-03-02
 modified: 2025-03-18
index f1f9e63..c424d18 100644 (file)
@@ -1,5 +1,5 @@
 ---
-category: movie
+type: movie
 title: Death Becomes Her
 date: 2025-10-02
 modified: 2025-10-07
index b8ac9f7..464cf37 100644 (file)
@@ -1,5 +1,5 @@
 ---
-category: movie
+type: movie
 title: 'Den of Thieves: Pantera'
 date: 2025-10-18
 modified: 2025-10-19
index cc81111..0c39ac1 100644 (file)
@@ -1,5 +1,5 @@
 ---
-category: movie
+type: movie
 title: Donnie Darko
 date: 2026-01-07
 modified: 2026-01-09
index affcc80..45d8cbc 100644 (file)
@@ -1,5 +1,5 @@
 ---
-category: movie
+type: movie
 title: 'F1: The Movie'
 date: 2025-10-16
 modified: 2025-10-17
index e426289..0ce7345 100644 (file)
@@ -1,5 +1,5 @@
 ---
-category: movie
+type: movie
 title: Fallen Angels
 date: 2025-08-02
 modified: 2025-10-24
index 324a388..427a1cc 100644 (file)
@@ -1,5 +1,5 @@
 ---
-category: movie
+type: movie
 title: Gnomeo & Juliet
 date: 2026-03-01
 modified: 2026-03-02
index b90e301..5a1dae8 100644 (file)
@@ -1,5 +1,5 @@
 ---
-category: movie
+type: movie
 title: Hamnet
 date: 2026-02-13
 modified: 2026-02-14
index ea53455..9785819 100644 (file)
@@ -1,5 +1,5 @@
 ---
-category: book
+type: book
 title: House of Huawei
 date: 2025-07-13
 modified: 2025-12-27
index 2b8b17f..f4076af 100644 (file)
@@ -1,5 +1,5 @@
 ---
-category: movie
+type: movie
 title: The Hunchback of Notre Dame
 date: 2025-03-04
 modified: 2025-03-22
index a7ba9b1..259e1d3 100644 (file)
@@ -1,5 +1,5 @@
 ---
-category: movie
+type: movie
 title: It's What's Inside
 date: 2025-03-01
 modified: 2025-03-02
index 648435f..ee54337 100644 (file)
@@ -1,5 +1,5 @@
 ---
-category: movie
+type: movie
 title: Jurassic Park
 date: 2025-09-10
 modified: 2025-09-13
index 6a76448..d148b60 100644 (file)
@@ -1,5 +1,5 @@
 ---
-category: movie
+type: movie
 title: Marty Supreme
 date: 2026-01-21
 modified: 2026-01-23
index ffa1858..81750d0 100644 (file)
@@ -1,5 +1,5 @@
 ---
-category: movie
+type: movie
 title: Materialists
 date: 2025-08-14
 modified: 2025-08-15
index 511b60f..f876cc3 100644 (file)
@@ -1,5 +1,5 @@
 ---
-category: movie
+type: movie
 title: Moulin Rouge!
 date: 2025-12-25
 modified: 2025-12-26
index d5708a8..0e220ea 100644 (file)
@@ -1,5 +1,5 @@
 ---
-category: movie
+type: movie
 title: Mulholland Drive
 date: 2025-12-06
 modified: 2025-12-07
index dc7ff24..063faec 100644 (file)
@@ -1,5 +1,5 @@
 ---
-category: movie
+type: movie
 title: Noah
 date: 2025-12-24
 modified: 2025-12-25
index 2312939..b0f907b 100644 (file)
@@ -1,5 +1,5 @@
 ---
-category: movie
+type: movie
 title: Nosferatu
 date: 2025-09-09
 modified: 2025-09-13
index c64f64e..7e5cd2d 100644 (file)
@@ -1,5 +1,5 @@
 ---
-category: movie
+type: movie
 title: One Battle After Another
 date: 2025-10-01
 modified: 2025-10-04
index 330d625..7518d34 100644 (file)
@@ -1,5 +1,5 @@
 ---
-category: movie
+type: movie
 title: 'Patlabor: The Movie'
 date: 2026-01-11
 modified: 2026-01-11
index 2ebc270..3092f46 100644 (file)
@@ -1,5 +1,5 @@
 ---
-category: movie
+type: movie
 title: People We Meet on Vacation
 date: 2026-02-12
 modified: 2026-02-14
index 192288b..6b4bc4c 100644 (file)
@@ -1,5 +1,5 @@
 ---
-category: movie
+type: movie
 title: Perfect Days
 date: 2025-02-15
 modified: 2025-02-15
index d40d0d4..f19c27b 100644 (file)
@@ -1,5 +1,5 @@
 ---
-category: movie
+type: movie
 title: Problemista
 date: 2025-11-04
 modified: 2025-11-06
index f5bb570..4526189 100644 (file)
@@ -1,5 +1,5 @@
 ---
-category: movie
+type: movie
 title: Sinners
 date: 2025-05-02
 modified: 2025-05-02
index 1a7cbfa..5158034 100644 (file)
@@ -1,5 +1,5 @@
 ---
-category: movie
+type: movie
 title: 'Star Wars: Episode III - Revenge of the Sith'
 date: 2025-09-05
 modified: 2025-09-07
index 7ea01e4..b10701f 100644 (file)
@@ -1,5 +1,5 @@
 ---
-category: movie
+type: movie
 title: Subservience
 date: 2024-12-25
 modified: 2024-12-26
index e40bab1..c1affe6 100644 (file)
@@ -1,5 +1,5 @@
 ---
-category: movie
+type: movie
 title: Superman
 date: 2025-10-04
 modified: 2025-10-04
index 37f2b17..e260153 100644 (file)
@@ -1,5 +1,5 @@
 ---
-category: movie
+type: movie
 title: Taipei Story
 date: 2025-12-27
 modified: 2025-12-28
index 906239e..4fc5620 100644 (file)
@@ -1,5 +1,5 @@
 ---
-category: movie
+type: movie
 title: The Apprentice
 date: 2025-09-06
 modified: 2025-09-07
index d7e526d..b6ae5b4 100644 (file)
@@ -1,5 +1,5 @@
 ---
-category: movie
+type: movie
 title: The Boy and the Heron
 date: 2024-12-21
 modified: 2024-12-23
index 187e957..1f77edc 100644 (file)
@@ -1,5 +1,5 @@
 ---
-category: movie
+type: movie
 title: The Godfather
 date: 2025-11-16
 modified: 2025-11-19
index 8e6b582..2131433 100644 (file)
@@ -1,5 +1,5 @@
 ---
-category: movie
+type: movie
 title: The Little Mermaid
 date: 2026-01-01
 modified: 2026-01-01
index f50bd24..d5c9024 100644 (file)
@@ -1,5 +1,5 @@
 ---
-category: movie
+type: movie
 title: 'The Lord of the Rings: The Fellowship of the Ring'
 date: 2025-11-26
 modified: 2025-11-30
index abfe280..9c33f3d 100644 (file)
@@ -1,5 +1,5 @@
 ---
-category: movie
+type: movie
 title: The Pianist
 date: 2026-04-11
 modified: 2026-04-11
index 6edf6b3..1c110f0 100644 (file)
@@ -1,5 +1,5 @@
 ---
-category: movie
+type: movie
 title: The Social Network
 date: 2025-12-28
 modified: 2025-12-29
index 04cdabc..73200ac 100644 (file)
@@ -1,5 +1,5 @@
 ---
-category: movie
+type: movie
 title: The Swan Princess
 date: 2026-03-17
 modified: 2026-03-18
index fe9649f..044e409 100644 (file)
@@ -1,5 +1,5 @@
 ---
-category: movie
+type: movie
 title: Thunderbolts*
 date: 2026-01-01
 modified: 2026-01-01
index 002824c..732cda1 100644 (file)
@@ -1,5 +1,5 @@
 ---
-category: movie
+type: movie
 title: Tick, Tick... Boom!
 date: 2025-12-27
 modified: 2025-12-28
index 20f91bd..c8284e6 100644 (file)
@@ -1,5 +1,5 @@
 ---
-category: movie
+type: movie
 title: Wake Up Dead Man
 date: 2025-12-15
 modified: 2025-12-16
index 19ed383..7c983b3 100644 (file)
@@ -1,5 +1,5 @@
 ---
-category: movie
+type: movie
 title: Warfare
 date: 2025-04-11
 modified: 2025-04-11
index 0d752ca..ba3a015 100644 (file)
@@ -1,5 +1,5 @@
 ---
-category: movie
+type: movie
 title: When Harry Met Sally...
 date: 2025-12-30
 modified: 2026-01-01
index 7d4d498..511a05a 100644 (file)
@@ -1,5 +1,5 @@
 ---
-category: movie
+type: movie
 title: 'Wicked: For Good'
 date: 2025-11-25
 modified: 2025-11-25
index 4bc74af..cee81b1 100644 (file)
@@ -1,5 +1,5 @@
 ---
-category: movie
+type: movie
 title: Wicked
 date: 2024-11-29
 modified: 2025-06-04
index 76616f0..ffd94a3 100644 (file)
@@ -31,6 +31,12 @@ const modifiedDate = entryData.modified
         >{modifiedDate}</time
       >
     </li>
+    <li
+      data-pagefind-meta={`type:${entryData.type}`}
+      data-pagefind-filter={`type:${entryData.type}`}
+    >
+      Type: {entryData.type}
+    </li>
     {entryData.tags && <li>Tags: {entryData.tags.join(', ')}</li>}
     {
       entryData.posse && (
diff --git a/src/components/ui/badge.astro b/src/components/ui/badge.astro
new file mode 100644 (file)
index 0000000..8954d55
--- /dev/null
@@ -0,0 +1,19 @@
+<span class="badge">
+  <slot />
+</span>
+
+<style>
+  .badge {
+    margin-inline-end: 0.5rem;
+    display: inline-block;
+    padding: 0.15rem 0.5rem;
+    color: var(--color-text);
+    background-color: transparent;
+    border: 1px solid var(--color-border);
+    border-radius: 0;
+    font-family: var(--font-sans);
+    font-size: 0.8rem;
+    line-height: 1.2;
+    white-space: nowrap;
+  }
+</style>
index a252a10..06d43fe 100644 (file)
@@ -1,27 +1,34 @@
 ---
 import { getCollection, type CollectionKey } from 'astro:content';
+import Badge from '@components/ui/badge.astro';
 import sortByDate from '@utils/sortByDate';
 import generateContentUrl from '@utils/generateContentUrl';
 
 interface Props {
   collection: CollectionKey;
+  limit?: number;
 }
 
-const { collection } = Astro.props;
+const { collection, limit } = Astro.props;
 const entries = await getCollection(collection);
 const sorted = sortByDate(entries);
+const displayedEntries =
+  typeof limit === 'number' ? sorted.slice(0, limit) : sorted;
 ---
 
 <dl>
   {
-    sorted.map((entry) => (
+    displayedEntries.map((entry) => (
       <>
         <dt>
           <a href={generateContentUrl(entry)}>
             <h4>{entry.data.title}</h4>
           </a>
         </dt>
-        {entry.data.description && <dd>{entry.data.description}</dd>}
+        <dd>
+          <Badge>{entry.data.type}</Badge>
+          {entry.data.description && entry.data.description}
+        </dd>
       </>
     ))
   }
index 141781d..f0a9f88 100644 (file)
@@ -13,7 +13,9 @@ const baseSchema = z.object({
 
 const articles = defineCollection({
   loader: glob({ pattern: '**/*.{md,mdx}', base: 'content/articles' }),
-  schema: baseSchema,
+  schema: baseSchema.extend({
+    type: z.enum(['marginalia', 'missive']),
+  }),
 });
 
 const podcasts = defineCollection({
@@ -34,7 +36,7 @@ const reviews = defineCollection({
   loader: glob({ pattern: '**/*.{md,mdx}', base: 'content/reviews' }),
   schema: baseSchema.extend({
     rating: z.int().gt(0).lte(5),
-    category: z.enum(['book', 'game', 'movie', 'music', 'show']),
+    type: z.enum(['book', 'game', 'movie', 'music', 'show']),
   }),
 });
 
index cdf230c..e58ce1d 100644 (file)
@@ -29,9 +29,7 @@ export async function GET(context: APIContext) {
         const { Content } = await render(item);
         const content = await container.renderToString(Content);
         const categories = (item.data.tags ?? []).concat(item.collection);
-        if (item.collection === 'reviews') {
-          categories.push(item.data.category);
-        }
+        categories.push(item.data.type);
 
         let title: string;
         let description: string;
index ff32067..ab4b90a 100644 (file)
@@ -1,28 +1,6 @@
 ---
 import Base from '@layouts/base.astro';
-
-const contributions = [
-  {
-    title: 'Git',
-    url: 'https://git.otsuka.systems',
-  },
-  {
-    title: 'Arch User Repository',
-    url: 'https://aur.archlinux.org/packages?O=0&SeB=M&K=cotsuka&outdated=&SB=p&SO=d&PP=50&submit=Go',
-  },
-  {
-    title: 'ArchWiki',
-    url: 'https://wiki.archlinux.org/title/Special:Contributions/Cotsuka',
-  },
-  {
-    title: 'GitHub',
-    url: 'https://github.com/search?q=author%3Acotsuka&type=pullrequests',
-  },
-  {
-    title: 'Wikipedia',
-    url: 'https://en.wikipedia.org/wiki/Special:Contributions/Cotsuka',
-  },
-];
+import ContentList from '@components/ui/contentlist.astro';
 ---
 
 <Base
@@ -44,19 +22,9 @@ const contributions = [
         vehicles, and built the internal tech stack that glues everything together.
       </p>
     </section>
-    <section data-pagefind-body>
-      <h2>Contributions</h2>
-      <ul>
-        {
-          contributions.map((contribution) => {
-            return (
-              <li>
-                <a href={contribution.url}>{contribution.title}</a>
-              </li>
-            );
-          })
-        }
-      </ul>
+    <section data-pagefind-ignore>
+      <h2>Latest Articles</h2>
+      <ContentList collection="articles" limit={5} />
     </section>
   </article>
 </Base>
similarity index 92%
rename from src/pages/reviews/[category]/[id]/index.astro
rename to src/pages/reviews/[type]/[id]/index.astro
index e98d605..c634180 100644 (file)
@@ -6,7 +6,7 @@ import Metadata from '@components/metadata.astro';
 export async function getStaticPaths() {
   const reviews = await getCollection('reviews');
   return reviews.map((review) => ({
-    params: { category: review.data.category, id: review.id },
+    params: { type: review.data.type, id: review.id },
     props: { entry: review },
   }));
 }
@@ -15,7 +15,7 @@ export const GET = (async ({ props, url }) => {
 export async function getStaticPaths() {
   const reviews = await getCollection('reviews');
   return reviews.map((review) => ({
-    params: { category: review.data.category, id: review.id },
+    params: { type: review.data.type, id: review.id },
     props: { entry: review },
   }));
 }
index 875a7dc..988fbee 100644 (file)
@@ -23,7 +23,7 @@ const sortedReviews = sortByDate(reviews);
     <table>
       <thead>
         <tr>
-          <th scope="col">Category</th>
+          <th scope="col">Type</th>
           <th scope="col">Title</th>
           <th scope="col">Rating</th>
         </tr>
@@ -32,7 +32,7 @@ const sortedReviews = sortByDate(reviews);
         {
           sortedReviews.map((review) => (
             <tr>
-              <td>{review.data.category}</td>
+              <td>{review.data.type}</td>
               <td>
                 <h4>
                   <a href={generateContentUrl(review)}>{review.data.title}</a>
index 7d0af54..47c0567 100644 (file)
@@ -29,6 +29,8 @@ const pagefindResultTemplate = String.raw`
     <div class="searchFilters" aria-label="Search result filters">
       <pagefind-filter-dropdown filter="category" label="Category"
       ></pagefind-filter-dropdown>
+      <pagefind-filter-dropdown filter="type" label="Type"
+      ></pagefind-filter-dropdown>
       <pagefind-filter-dropdown
         filter="tag"
         label="Tag"
@@ -75,7 +77,7 @@ const pagefindResultTemplate = String.raw`
 
   .searchFilters {
     display: grid;
-    grid-template-columns: repeat(2, minmax(0, 1fr));
+    grid-template-columns: repeat(3, minmax(0, 1fr));
     gap: 1rem;
     margin-block: 1rem;
   }
index a97c0b9..1b40046 100644 (file)
@@ -8,6 +8,6 @@ export default function generateContentUrl(item: SiteCollectionEntry): string {
     case 'podcasts':
       return `/podcasts/${item.id}/`;
     case 'reviews':
-      return `/reviews/${item.data.category}/${item.id}/`;
+      return `/reviews/${item.data.type}/${item.id}/`;
   }
 }