CodeForPhilly / CodeForPhilly/codeforphilly-ng

media: runtime thumbnail service for attachments (currently serves originals as-is)

Open
#108 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
1
Forks
1
Avg merge
5d 3h
Merged PRs (30d)
9

Description

## What's deferred

Blog-post bodies (after PR #107 + follow-up) store **original** media bytes as gitsheets attachments under \`blog-posts//.\`. The API serves them via \`GET /api/attachments/:key\` — but as the original bytes, no resizing.

Practical consequences:

- A blog index card that wants a 200×200 thumbnail downloads the full 2MB JPEG and lets CSS scale it.
- A featured-image header that wants a 1920px wide hero downloads the same 2MB JPEG regardless of viewport.
- Per-render bytes-on-the-wire are 5-50× larger than they need to be.

We accepted this because:

- The legacy laddr server's \`/thumbnail//\` endpoint can't be relied on past cutover.
- Storing **originals** in the data repo is the right durable record.
- Resizing on demand is a runtime concern that can be added without changing the data shape.

## Fix shape

Add a thumbnail endpoint:

\`\`\`
GET /api/attachments/:key?w=200&h=200&fit=cover&format=auto
\`\`\`

- Reads the original blob from gitsheets.
- Pipes through \`sharp\` (already a dep — used in avatar uploads).
- Caches the resized output keyed by \`(blobHash, w, h, fit, format)\` so the same params return from cache after the first hit.
- Cache lives in the pod's memory or a tmpfs volume — invalidated on hot-reload (the blobHash key handles that naturally).

Alternative: precompute thumbnails at import time (write \`-200x200.jpg\` alongside \`.jpg\`). Trades repo size for runtime cost. Probably the wrong trade — variants explode quickly.

## Until then

Markdown bodies render \`\` tags pointing at \`/api/attachments/...\` and the browser pulls the full original. SPA can add \`loading="lazy"\` and CSS \`max-width\` for ergonomics; bandwidth cost is real but not blocking v1.

## Related

- Avatar upload (\`apps/api/src/routes/people.ts\`) already does a sharp-based resize at write time + stores both originals and 128×128 thumbnails. The pattern is established; the read-time variant would unify the two surfaces.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.