Getting Started
imgcraft is a chainable image transform pipeline that runs in both Node.js and the browser. One API, everywhere.
Install
npm install imgcraftnpm install imgcraftNode.js requires sharp as an optional peer dependency:
npm install imgcraft sharpnpm install imgcraft sharpBrowser usage requires no additional install — WebAssembly is bundled automatically.
First image
import { img } from 'imgcraft'
const buffer = await img('photo.jpg')
.resize(800, 600)
.webp({ quality: 85 })
.toBuffer()import { img } from 'imgcraft'
const buffer = await img('photo.jpg')
.resize(800, 600)
.webp({ quality: 85 })
.toBuffer()img() accepts a file path (Node.js), Buffer, Uint8Array, ArrayBuffer, or a browser File / Blob.
Output methods
| Method | Returns | Environment |
|---|---|---|
.toBuffer() | Buffer (Node) / Uint8Array (browser) | Node + Browser |
.toFile(path) | Promise<void> | Node only |
.toStream() | ReadableStream<Uint8Array> | Node only |
.toDataURL() | Promise<string> (base64 data URI) | Browser |
.meta() | Promise<MetadataResult> | Node + Browser |
// Write to disk
await img('photo.jpg').resize(800).toFile('./output.jpg')
// Stream (e.g. pipe to HTTP response)
const stream = await img('photo.jpg').resize(800).toStream()
// Browser — display in an <img> tag
const url = await img(file).resize(400).toDataURL()
document.querySelector('img').src = url// Write to disk
await img('photo.jpg').resize(800).toFile('./output.jpg')
// Stream (e.g. pipe to HTTP response)
const stream = await img('photo.jpg').resize(800).toStream()
// Browser — display in an <img> tag
const url = await img(file).resize(400).toDataURL()
document.querySelector('img').src = urlNode vs Browser
imgcraft detects your runtime automatically. No flag needed.
| Environment | Engine | Notes |
|---|---|---|
| Node.js | sharp | Full feature set, fastest |
| Browser | WASM | Same API, no server required |
// Node.js — uses sharp
const out = await img('photo.jpg').resize(800).toBuffer()
// Browser — same API, WASM engine selected automatically
const out = await img(fileInput).resize(800).toDataURL()// Node.js — uses sharp
const out = await img('photo.jpg').resize(800).toBuffer()
// Browser — same API, WASM engine selected automatically
const out = await img(fileInput).resize(800).toDataURL()AI operations (removeBackground, smartCrop, upscale) are Node.js only — they load ONNX and TensorFlow models on first use.
Chaining transforms
Every method returns the same Pipeline instance, so transforms compose left to right:
const buffer = await img('photo.jpg')
.resize(1200) // scale down
.sharpen() // recover detail
.brightness(1.05) // slight lift
.webp({ quality: 85 }) // encode
.toBuffer()const buffer = await img('photo.jpg')
.resize(1200) // scale down
.sharpen() // recover detail
.brightness(1.05) // slight lift
.webp({ quality: 85 }) // encode
.toBuffer()Batch processing
batch() applies the same pipeline to multiple inputs in parallel:
import { batch } from 'imgcraft'
await batch(['a.jpg', 'b.jpg', 'c.jpg'], { concurrency: 4 })
.resize(800)
.webp({ quality: 85 })
.toDir('./output')import { batch } from 'imgcraft'
await batch(['a.jpg', 'b.jpg', 'c.jpg'], { concurrency: 4 })
.resize(800)
.webp({ quality: 85 })
.toDir('./output')Output options:
// Write to a directory (filename preserved, extension changed to match format)
await batch(inputs).resize(800).webp().toDir('./out')
// Get results as an array of Uint8Array
const buffers = await batch(inputs).resize(800).toBuffers()
// 1:1 path mapping
await batch(inputs).resize(800).toFiles(['./a-sm.jpg', './b-sm.jpg', './c-sm.jpg'])// Write to a directory (filename preserved, extension changed to match format)
await batch(inputs).resize(800).webp().toDir('./out')
// Get results as an array of Uint8Array
const buffers = await batch(inputs).resize(800).toBuffers()
// 1:1 path mapping
await batch(inputs).resize(800).toFiles(['./a-sm.jpg', './b-sm.jpg', './c-sm.jpg'])TypeScript
imgcraft is written in strict TypeScript. All transforms are fully typed.
import type { Pipeline, MetadataResult } from 'imgcraft'
async function thumbnail(input: string): Promise<Buffer> {
return img(input).resize(200, 200, { fit: 'cover' }).jpeg({ quality: 75 }).toBuffer()
}import type { Pipeline, MetadataResult } from 'imgcraft'
async function thumbnail(input: string): Promise<Buffer> {
return img(input).resize(200, 200, { fit: 'cover' }).jpeg({ quality: 75 }).toBuffer()
}Next steps
- Transforms — resize, crop, rotate, flip, flop
- Filters — blur, sharpen, colour adjustments
- Format — JPEG, PNG, WebP, AVIF options
- AI Operations — background removal, smart crop, upscale
- Batch — concurrent processing
- REST API — hosted endpoint for any language