TypeScript-first upload infrastructure

Direct uploads without provider-specific application code.

Define typed assets, validate file information, and prepare secure upload targets for AWS S3 and ImageKit through one focused API.

Typed configuration
Server-side signing
Validation before signing
Direct browser uploads
Upload flow
Secure

Browser

Sends filename, content type, and file size

File metadata

Application server

Authenticates the request and calls the SDK

prepareUpload()

Upload SDK

Validates, resolves the profile, and signs

Signed fields

Storage provider

Receives the file directly from the browser

Method

POST

Body

FormData

Strategy

multipart

2

Providers

AWS S3 and ImageKit

1

Upload strategy

Multipart POST

0

Client secrets

Credentials remain server-side

100%

Typed configuration

Assets and profiles are inferred

Why Upload SDK

A clean boundary between product logic and provider APIs.

Your application describes upload intent. The SDK handles shared validation and provider-specific signing.

01

Typed assets

Represent avatars, documents, banners, and other uploads as named, strongly typed configurations.

02

Storage profiles

Route assets through named AWS S3 or ImageKit profiles without leaking provider details into product code.

03

Validation first

Validate filename, key prefix, MIME type, extension, size, and expiration before generating upload credentials.

04

Server-side signing

Keep provider credentials inside server-side factories and return only short-lived upload fields.

How it works

A predictable four-step upload flow.

The server prepares the upload. The browser transfers the actual file directly to the provider.

01

Configure providers

Create named storage profiles using AWS S3 or ImageKit credentials.

02

Define assets

Describe file rules, limits, metadata, storage profile, and key prefix.

03

Prepare

Send file metadata to your server and call prepareUpload.

04

Upload

Submit the returned fields and file directly to the provider.

Developer experience

Configuration that reads like product policy.

Profiles contain provider configuration. Assets describe what your application accepts. The uploader connects them at runtime.

Literal asset-name inference
Typed storage-profile references
Runtime validation before signing
Provider-independent preparation output
Read the quick-start guide
upload.server.tsServer
import {
  awsS3,
  createUploader,
  defineAssets,
  defineStorageProfiles,
} from "@marinedotsh/upload-sdk";

const storageProfiles = defineStorageProfiles({
  media: awsS3({
    bucket: process.env.AWS_BUCKET!,
    region: process.env.AWS_REGION!,
    credentials: {
      accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
      secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
    },
  }),
});

const assets = defineAssets(storageProfiles, {
  avatar: {
    storageProfile: "media",
    keyPrefix: "uploads/avatars",
    expiresIn: { value: 5, unit: "minutes" },
    accept: {
      mimeTypes: ["image/png", "image/jpeg"],
      extensions: [".png", ".jpg", ".jpeg"],
    },
    limits: {
      maxFileSize: { value: 1, unit: "MB" },
    },
  },
});

export const uploader = createUploader({
  storageProfiles,
  defaultStorageProfile: "media",
  assets,
});

Asset

avatar

Profile

media

Provider

AWS S3

upload-file.tsBrowser
const prepared = await uploader.prepareUpload("avatar", {
  filename: "profile.png",
  contentType: "image/png",
  size: 120_000,
});

const formData = new FormData();

for (const [name, value] of Object.entries(prepared.fields)) {
  formData.append(name, value);
}

formData.append("file", file);

await fetch(prepared.url, {
  method: prepared.method,
  headers: prepared.headers,
  body: formData,
});

Prepared result

strategy
"multipart"
method
"POST"
fields
Record<string, string>
expiresAt
ISO timestamp

Providers

One shared contract, provider-specific signing.

The application-facing preparation flow remains stable while each provider generates the fields it requires.

View provider documentation
S3

AWS S3

Signature V4 POST policy

Generate signed multipart POST fields with constrained object keys, content type, metadata, expiration, and optional file-size limits.

Strategy
Multipart POST
Authentication
AWS SigV4
Expiry
Up to 7 days
IK

ImageKit

V2 upload JWT

Generate short-lived upload JWTs with destination fields, overwrite protection, metadata, and optional MIME checks.

Strategy
Multipart POST
Authentication
HS256 JWT
Overwrite
Disabled

Clear boundaries

The SDK prepares uploads. Your application owns the product flow.

Keeping these responsibilities separate prevents the SDK from becoming tightly coupled to your framework, database, or authentication system.

Upload SDK

Handled for you

  • Asset and storage-profile resolution
  • Filename and key-prefix sanitization
  • MIME, extension, and file-size validation
  • Provider-specific upload signing
  • Typed preparation results and SDK errors
Your application

Remains in your control

  • Authentication and authorization
  • API routes or server actions
  • Submitting FormData from the browser
  • Upload completion and persistence
  • Retries, cleanup, and rate limiting

Prepare your first direct upload.

Install the SDK, configure a storage profile, and define your first typed upload asset.

Terminal
$pnpm add @marinedotsh/upload-sdk