Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/syhily/yufan.me/llms.txt

Use this file to discover all available pages before exploring further.

The image library stores every uploaded image as an object in S3-compatible object storage and records its metadata — dimensions, byte size, thumbhash, and storage path — in Postgres. Before you can upload anything, you must enable and configure S3 in Settings → Assets (/admin/settings/assets). The library itself is always readable; only write operations require the storage toggle to be on.

Prerequisites

S3 storage must be enabled before any upload will succeed. Navigate to Settings → Assets and turn on Enable S3 uploads, then fill in your bucket credentials, region, and the public CDN host. Without this configuration, all upload endpoints return 503.
Toggling S3 storage off does not delete existing images. The storagePath values stored in Postgres still resolve against the saved CDN host, so public URLs remain valid as long as the S3 bucket is accessible. New uploads will fail with 503 until you re-enable storage — you do not need to re-enter your credentials.

Uploading images

Generic uploads

The main image library is at Admin → Image Library (/admin/library/images). Each file you upload is stored at the path:
images/yyyy/MM/<timestamp>.jpg
Images are compressed with Sharp before being written to S3. The JPEG quality setting and the maximum allowed byte size are both configurable in Settings → Assets.

Category cover images

When you create or edit a category, the Edit Category dialog includes an inline image uploader. The uploaded image is stored at:
images/categories/<slug>.jpg
Category covers are fixed at 1280 × 425 px and are re-encoded to JPEG on upload.

Friend banner images

The Edit Friend dialog includes an equivalent inline uploader. The banner is stored at:
images/links/<host>.jpg
Friend banners are also 1280 × 425 px and follow the same JPEG compression pipeline.

Image processing

Every uploaded image passes through the Sharp processing pipeline before it reaches S3:
  • Re-encoded to JPEG at the quality level set in Settings → Assets (blog.assets)
  • Byte size checked both before and after processing — the upload is rejected if either exceeds the configured limit
  • Dimensions recorded in the Postgres image row

Using images in posts

Two entry points in the Tiptap editor open the image picker:
  • Image Library button in the top toolbar
  • /image slash command in the body
Both show a picker of all images in your library. Selecting an image inserts it as a PortableText image block with the storage path reference.

Image URLs

The public URL for any image is:
<assets.asset.scheme>://<assets.asset.host>/<storagePath>
Both asset.scheme and asset.host come from Settings → Assets. The admin library appends a ?v=<updatedAt> cache-buster whenever an image is re-uploaded to the same key, so CDN and browser caches refresh immediately.
yufan.me pre-generates a thumbhash for every uploaded image. Thumbhashes are compact perceptual placeholders (stored in the image row) that the feed renderer uses to show a low-quality blurred preview while the full image loads. They are computed at upload time and can be recalculated from the Admin image library if needed.

Build docs developers (and LLMs) love