# How the Instatic Media Workspace Manages Uploads and Image Variants

> Discover how Instatic's media workspace manages uploads and image variants using a three-stage pipeline. Learn about byte-transfer isolation, pluggable storage, and automatic WebP optimization for responsive delivery.

- Repository: [CoreBunch/Instatic](https://github.com/CoreBunch/Instatic)
- Tags: internals
- Published: 2026-08-01

---

**Instatic’s media workspace implements a three-stage upload pipeline that isolates byte-transfer from the QuickJS sandbox, stores files via pluggable storage adapters, and automatically generates optimized WebP image variants for responsive delivery.**

The Instatic media workspace provides a complete asset management system that handles everything from file ingestion to responsive image delivery. As implemented in the CoreBunch/Instatic repository, this architecture separates upload orchestration from byte-stream execution while supporting multiple storage backends through a plugin-based adapter system.

## Three-Stage Upload Pipeline Architecture

### Upload Orchestration and Validation

When a user drops a file onto the Media canvas or submits via the upload queue, the UI calls `POST /admin/api/cms/media`. The handler in [`server/handlers/cms/mediaUpload.ts`](https://github.com/CoreBunch/Instatic/blob/main/server/handlers/cms/mediaUpload.ts) validates the file through size checks and MIME sniffing before forwarding to [`mediaUploadDispatch.ts`](https://github.com/CoreBunch/Instatic/blob/main/mediaUploadDispatch.ts). 

This dispatch layer selects the **elected storage adapter** based on the asset's role—whether original, variant, or avatar—and invokes the adapter's `beginWrite` method to generate a `MediaStorageUploadPlan` containing signed URLs or local-disk sentinels.

### Byte-Stream Execution Outside the Sandbox

The host executes [`mediaUploadExecutor.ts`](https://github.com/CoreBunch/Instatic/blob/main/mediaUploadExecutor.ts), which iterates over each step of the upload plan while streaming bytes **outside** the QuickJS sandbox. 

For the built-in **local-disk** adapter, the executor detects the sentinel constant `LOCAL_DISK_STEP_METHOD` (`'LOCAL'`) and writes directly using `fs.writeFile`. Remote adapters trigger `'PUT'` or `'POST'` steps, where the executor uses Bun's native `fetch` to transmit slices with appropriate `Content-Length` headers and signed request signatures.

### Finalization and Event Broadcasting

After all steps complete successfully, the adapter's `finalizeWrite` returns a public URL—either `/uploads/<path>` for local storage or a signed read URL for external providers. 

The handler persists the new row to the `media_assets` table via [`server/repositories/media.ts`](https://github.com/CoreBunch/Instatic/blob/main/server/repositories/media.ts) and emits a `mediaAssetCreated` event through [`mediaAssetEvents.ts`](https://github.com/CoreBunch/Instatic/blob/main/mediaAssetEvents.ts), enabling real-time refresh across all open Media windows.

## Automatic Image Variant Generation

### WebP Ladder and Blurhash Computation

Once the original asset exists in the database, the host invokes the **image-variant worker** ([`server/handlers/cms/imageVariantWorker.ts`](https://github.com/CoreBunch/Instatic/blob/main/server/handlers/cms/imageVariantWorker.ts)). This worker utilizes the `sharp` library to probe the source image, compute a **blurhash** for placeholder display, and generate a responsive ladder of WebP files at predefined widths ranging from 64 px up to the intrinsic image width.

### Variant Metadata Storage

Variant metadata—including `width`, `height`, `format`, `path`, `sizeBytes`, `storagePath`, and `storageAdapterId`—is serialized into the JSON column `variants_json` of the `media_assets` table. 

The mapping logic in [`server/repositories/mediaAssetMapping.ts`](https://github.com/CoreBunch/Instatic/blob/main/server/repositories/mediaAssetMapping.ts) parses this column to produce the `RenderResolvedMedia` shape used throughout the application.

## Responsive Rendering and Storage Abstraction

### Building Srcset and Selecting Optimal Variants

Both the admin UI and public publisher consume the same `RenderResolvedMedia` interface. Helper functions in [`src/modules/base/utils/mediaAttrs.ts`](https://github.com/CoreBunch/Instatic/blob/main/src/modules/base/utils/mediaAttrs.ts) construct responsive image attributes: `buildMediaSrcset` assembles a `srcset` string from the variant ladder, while `pickMediaVariantUrl` selects the smallest variant meeting or exceeding the requested width. 

The publisher's [`mediaPresentation.ts`](https://github.com/CoreBunch/Instatic/blob/main/mediaPresentation.ts) streams these URLs to clients, while the admin canvas renders previews using identical helpers.

### Pluggable Storage Adapter System

The [`mediaStorageRegistry.ts`](https://github.com/CoreBunch/Instatic/blob/main/mediaStorageRegistry.ts) maintains a registry of storage adapters initialized at boot, including the built-in **local-disk** adapter configured via `configureLocalDisk`. 

Plugins can register additional adapters through the SDK's `api.cms.media.registerStorageAdapter` method, provided they hold the `media.storage.adapter` permission. Each adapter declares a `servingMode`—either `public-url` for direct browser access or `non-public-url` requiring signed redirects through `/_instatic/media/<adapterId>/<storagePath>`.

## Implementation Examples

Creating an upload plan through the adapter interface:

```typescript
// Adapter-side plan creation
await adapter.beginWrite({
  suggestedStoragePath: 'my-image-abc123.webp',
  role: 'original',
});

```

Executing the upload plan on the host:

```typescript
// Host-side execution outside the sandbox
import { executeUploadPlan } from '@core/mediaUploadExecutor';
await executeUploadPlan(plan, fileBytes);

```

Selecting responsive variants in a React component:

```typescript
// Responsive image selection utilities
import { pickMediaVariantUrl, buildMediaSrcset } from '@modules/base/utils/mediaAttrs';

const src = pickMediaVariantUrl(resolvedMedia, 1280);
const srcset = buildMediaSrcset(resolvedMedia);

```

Registering a custom storage adapter via the plugin SDK:

```typescript
// Plugin SDK registration for external storage
api.cms.media.registerStorageAdapter({
  id: 'myS3',
  label: 'S3',
  roles: ['original', 'variant'],
  servingMode: 'non-public-url',
  // ...implement beginWrite, finalizeWrite, abortWrite...
});

```

## Summary

- The upload pipeline in [`mediaUpload.ts`](https://github.com/CoreBunch/Instatic/blob/main/mediaUpload.ts) and [`mediaUploadDispatch.ts`](https://github.com/CoreBunch/Instatic/blob/main/mediaUploadDispatch.ts) validates files and creates signed upload plans through pluggable adapters.
- [`mediaUploadExecutor.ts`](https://github.com/CoreBunch/Instatic/blob/main/mediaUploadExecutor.ts) streams bytes outside the QuickJS sandbox using local file system writes or remote HTTP requests.
- Original assets persist via [`server/repositories/media.ts`](https://github.com/CoreBunch/Instatic/blob/main/server/repositories/media.ts), triggering `mediaAssetCreated` events for real-time UI updates.
- The [`imageVariantWorker.ts`](https://github.com/CoreBunch/Instatic/blob/main/imageVariantWorker.ts) generates WebP ladders and blurhashes, storing metadata in the `variants_json` column.
- [`mediaAttrs.ts`](https://github.com/CoreBunch/Instatic/blob/main/mediaAttrs.ts) provides `buildMediaSrcset` and `pickMediaVariantUrl` helpers for responsive image rendering across admin and public contexts.

## Frequently Asked Questions

### How does Instatic handle large file uploads without blocking the QuickJS sandbox?

Instatic isolates byte-transfer operations in [`mediaUploadExecutor.ts`](https://github.com/CoreBunch/Instatic/blob/main/mediaUploadExecutor.ts), which runs on the host outside the sandbox. The executor processes `MediaStorageUploadPlan` steps using either `fs.writeFile` for local storage or Bun's native `fetch` for remote adapters, ensuring the JavaScript sandbox remains unblocked during large file transfers.

### What image formats does the variant generator produce?

The [`imageVariantWorker.ts`](https://github.com/CoreBunch/Instatic/blob/main/imageVariantWorker.ts) automatically generates **WebP** variants at predefined widths (64 px, 320 px, and up to the intrinsic width). It also computes a **blurhash** string for low-quality image placeholders, storing all variant metadata in the `variants_json` column of the `media_assets` table.

### Can I use external storage providers like S3 with Instatic?

Yes. The [`mediaStorageRegistry.ts`](https://github.com/CoreBunch/Instatic/blob/main/mediaStorageRegistry.ts) supports custom adapters registered via the plugin SDK's `api.cms.media.registerStorageAdapter` method. Adapters implement `beginWrite`, `finalizeWrite`, and `abortWrite` methods, and can specify `servingMode: 'non-public-url'` to route requests through `/_instatic/media/<adapterId>/<storagePath>` with signed redirects.

### How does the media workspace select the right image size for different devices?

The `pickMediaVariantUrl` function in [`src/modules/base/utils/mediaAttrs.ts`](https://github.com/CoreBunch/Instatic/blob/main/src/modules/base/utils/mediaAttrs.ts) selects the smallest variant with a width greater than or equal to the requested display width. For comprehensive responsive support, `buildMediaSrcset` constructs a complete `srcset` attribute from the variant ladder stored in `variants_json`, allowing browsers to choose optimal resolutions.