Adds a build-time mosaic generator (scripts/build-list-mosaics.mjs, sharp) that composites a single tile image per superpost from its referenced finds. Wired via predev/prestart/prebuild hooks; output lives in src/generated/ (gitignored). The /finds/ index and home grid both render the mosaic when present and fall back to text-only tiles otherwise.
Unique
A small blog about delightful, unique things — products, apps, phenomena, oddities.
Built with Astro + MDX.
Key features
- Four-collection pipeline:
find(captured items, hidden from indexes),finds(editorial superposts that reference find slugs in a grid),reviews(full-length, sometimes graduated from a find),posts(generic essays) - Daily capture skills under
.claude/skills/:daily-finds(sweeps every source insources.json, writes one find file per qualifying item — capture-only, no editorial selection);build-finds(drafts a thematic superpost from the find pool);build-review(graduates a find to a full review, linking the two viafromFind/promotedTo) - Sources catalog at
sources.jsonwith per-source fetch strategy (webfetch/curl/skip) and the/sourcespage rendering a 3-column card stream with a "Recent finds" sub-list per card - Strict find visibility: find items are reachable only via the superposts that reference them, the
/sourcescross-reference, or direct URL — they don't crowd the home feed, tag pages, or category pages - Backlinks computed at build time: each find page lists every superpost that references it; promoted finds show a forward link to the review; reviews show a "← First surfaced…" backlink to their originating find
- Newspaper-style masthead on every page: live entry-count + last-updated stats on the left, large serif "Unique" wordmark centered between thin rules, About/Blog nav on the right; per-page italic subheader ("A small log of delightful things.") with last-updated date on listing pages
- Pinterest-style home page: hero card for the latest review plus a 3-column masonry grid of remaining reviews with a "Load more" reveal; old plain-list home preserved at
/index3/ - Unified chronological feed at
/index3/across reviews + finds (superposts) + posts - SEO-friendly site footer with Browse / Collections (live counts) / About link columns and a centered legal line; consistent 76rem page width across the entire site (article prose constrained to a comfortable reading measure inside the wider layout)
- Reviews render as two-line index entries: bold name + muted subtitle (
Cotypist/ Autocomplete that lives everywhere on your Mac) - Auto-generated
/categories/<name>/and/tags/<name>/listing pages — finds excluded by design - Amazon affiliate handling in
src/lib/affiliate.ts: outbound links to Amazon (amazon.com,amzn.to,a.co,smile.amazon.com) get the configured tracking ID appended automatically; the link getsrel="sponsored", an "Affiliate" badge appears next to it, and a one-line disclosure is shown beneath. Add additional marketplace IDs (e.g.amazon.co.uk) to theAMAZON_TAGSmap when needed - SEO surface: single
<SEO>component owning canonical, Open Graph, Twitter Card, and JSON-LD; per-page structured data (Review,BlogPosting,Product,Article,CollectionPage,ItemList,BreadcrumbList,WebSite,Organization); auto-generatedsitemap-index.xml(excludes/grid/and/index3/); RSS feed at/rss.xml;robots.txt; static OG image fallbacks under/public/og/; promoted finds canonical to their review - Custom 404 page with recent-reviews and navigation fallback
- Light/dark mode via
prefers-color-scheme - No JavaScript shipped to the client
- Static build, deployable anywhere
Local development
npm install
npm run dev # local dev server
npm run build # type-check + static build to ./dist
npm run preview # serve the built site
Adding a review
Each review is a folder with index.mdx plus its media. The folder name is the slug:
src/content/reviews/cotypist/
├── index.mdx # the article + frontmatter
├── hero.mp4 # web-ready variants live here, alongside the article
├── screenshot.png
└── source/ # heavy originals (archival; never bundled)
└── hero.gif
index.mdx frontmatter:
---
name: "Cotypist"
subtitle: "Autocomplete that lives everywhere on your Mac"
date: 2026-05-03
category: writing
tags: [macos, productivity]
link: https://cotypist.app/ # optional product URL
linkText: "Visit in App Store" # optional; defaults to the link's hostname (sans `www.`)
description: "Optional <meta> override; defaults to subtitle."
---
Body in markdown / MDX. You can import and use components here.
The folder name becomes the URL at /reviews/<slug>/. Media is referenced relatively:

import demo from './hero.mp4';
<video src={demo} autoplay loop muted playsinline preload="metadata" />
If the review needs a hero on the home/grid pages, add it to src/lib/hero.ts.
Media
Prefer real screenshots, GIFs, or short clips from the app's own site (downloaded locally — don't hotlink). Pair with a short italic caption that names what's being shown. Visuals should illustrate the virtue of the product, not decorate the page.
Source vs published media. Heavy originals live in <slug>/source/; web-ready variants live at <slug>/<file> and are what the site actually ships. Files inside source/ aren't imported anywhere, so Astro doesn't bundle them into dist/. To add or replace a video:
# 1. drop the original into source/
mv ~/Downloads/demo.mp4 src/content/reviews/<slug>/source/
# 2. encode a smaller web variant alongside (h264 CRF 28, ≤1280px, no audio)
ffmpeg -i src/content/reviews/<slug>/source/demo.mp4 \
-c:v libx264 -preset slow -crf 28 \
-movflags +faststart -pix_fmt yuv420p \
-vf "scale='min(1280,iw)':-2,crop=trunc(iw/2)*2:trunc(ih/2)*2" \
-an src/content/reviews/<slug>/demo.mp4
# 3. reference ./demo.mp4 from index.mdx or src/lib/hero.ts
For animated GIFs, use the same recipe with crf 26 and source .gif — the resulting MP4 is typically 5–15× smaller.
Adding a post (essay)
Create a folder + index.mdx under src/content/posts/<slug>/:
---
title: "Some essay title"
date: 2026-05-10
category: writing
tags: [meta, opinion]
description: "Optional <meta> tag override."
---
Body in markdown / MDX.
The folder name becomes the URL at /posts/<slug>/. Drop any media (images, screenshots) next to index.mdx and reference them as ./image.png. Same convention applies to the find/ and finds/ collections — each entry is a folder with index.mdx and any sibling media.
Project layout
src/
content.config.ts # collection schemas (reviews, posts, find, finds)
content/
reviews/<slug>/
index.mdx # article + frontmatter
<media files> # web-ready variants (hero, screenshots, demos)
source/ # archival originals (not bundled)
find/<slug>/
index.mdx
hero.{jpg,png,gif,webp} # auto-resolved by src/lib/find-hero.ts
finds/<slug>/index.mdx # editorial superposts (text-only today)
posts/<slug>/index.mdx # essays
lib/
entries.ts # getAllEntries() — unified feed across collections
components/
EntryList.astro # shared two-shape entry list
layouts/
BaseLayout.astro
pages/
index.astro # Pinterest-style home (hero + masonry)
index3.astro # plain chronological list view
about.astro # About page
blog.astro # /posts index (essays)
grid.astro # full grid of every review
sources.astro # source catalog
reviews/[...slug].astro
posts/[...slug].astro
categories/[category].astro
tags/[tag].astro
public/
favicon.svg
Adding a new content type
- Define the collection in
src/content.config.ts. - Extend the
Entryunion andgetAllEntries()insrc/lib/entries.tsso the new type joins the merged feed. - Add a detail route at
src/pages/<type>/[...slug].astro.
Listing pages (index, categories, tags) need no changes — they consume getAllEntries().