site: media + colocation — chunk 1/4 (code, configs, docs)

Code, configs, README, CHANGELOG, sources/log files, .claude.
Subsequent chunks land the renamed media files.
This commit is contained in:
2026-05-04 17:54:14 -04:00
parent e873460465
commit 5dcd99361f
25 changed files with 1138 additions and 243 deletions
+50 -13
View File
@@ -35,7 +35,18 @@ npm run preview # serve the built site
## Adding a review
Create an MDX file under `src/content/reviews/<slug>.mdx`:
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:
```mdx
---
@@ -52,21 +63,42 @@ description: "Optional <meta> override; defaults to subtitle."
Body in markdown / MDX. You can import and use components here.
```
The slug becomes the URL at `/reviews/<slug>/`.
The folder name becomes the URL at `/reviews/<slug>/`. Media is referenced relatively:
```mdx
![alt](./screenshot.png)
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
Visuals for a review live at `src/assets/reviews/<slug>/`, mirroring the slug. Reference them from MDX with relative paths so Astro's image pipeline picks them up (responsive variants, lazy loading, modern formats):
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.
```mdx
![alt text](../../assets/reviews/<slug>/feature.png)
**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:
```bash
# 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
```
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.
For animated GIFs, use the same recipe with `crf 26` and source `.gif` — the resulting MP4 is typically 515× smaller.
## Adding a post (essay)
Create an MDX file under `src/content/posts/<slug>.mdx`:
Create a folder + `index.mdx` under `src/content/posts/<slug>/`:
```mdx
---
@@ -80,18 +112,23 @@ description: "Optional <meta> tag override."
Body in markdown / MDX.
```
The slug becomes the URL at `/posts/<slug>/`.
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)
assets/
reviews/<slug>/ # hero images and screenshots per review
content.config.ts # collection schemas (reviews, posts, find, finds)
content/
reviews/*.mdx # product reviews
posts/*.mdx # essays (empty for now)
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/