@tuzzle/url

Pure, dependency-free builder for CDN delivery URLs and server-side signing.

@tuzzle/url is the daily driver: a zero-dependency builder for composing CDN delivery URLs and, on the server, signing them. It runs anywhere JavaScript runs.

npm install @tuzzle/url

Building URLs

createTuzzle is bound to a CDN host and a space. Use url() for a one-shot URL or image() for a chainable builder.

import { createTuzzle } from '@tuzzle/url'

const tuzzle = createTuzzle({
  cdnUrl: 'https://cdn.tzzl.io',
  space: 'a1b2c3',
})

// One-shot with a transforms object
tuzzle.url('image-01HQ...', { width: 400, height: 300, format: 'webp', quality: 80 })
// https://cdn.tzzl.io/a1b2c3/image-01HQ...?w=400&h=300&f=webp&q=80

// Fluent builder
tuzzle
  .image('image-01HQ...')
  .width(400)
  .height(300)
  .resize('fill')
  .gravity('face')
  .format('webp')
  .quality(80)
  .toURL()

Transform options

The transforms object and the builder methods map to the same CDN query parameters:

Option / methodParamValues
widthwpixels
heighthpixels
formatfjpeg, png, webp, avif, tiff, gif, pdf
qualityq1100
resizerscale, fit, fill, crop, thumb
gravitygnorthnorthwest, center, face, faces, eyes, auto

See Transformations for what each parameter does.

Signing URLs (server-only)

For private and authenticated files, the original must be requested with a signed URL. Signing requires your space's signed-URL secret, so it must only run on the server.

import { createTuzzleSigner, signUrl } from '@tuzzle/url'

const signer = createTuzzleSigner({
  cdnUrl: 'https://cdn.tzzl.io',
  space: 'a1b2c3',
  secret: process.env.TUZZLE_SIGNED_URL_SECRET!,
})

// Signed delivery URL, valid for 30 minutes
const url = await signer.signedUrl('private/contract.pdf', { expiresIn: 1800 })

// Or the standalone helper
const url2 = await signUrl(
  { cdnUrl: 'https://cdn.tzzl.io', space: 'a1b2c3', secret: process.env.TUZZLE_SIGNED_URL_SECRET! },
  'private/contract.pdf',
  { transforms: { width: 800, format: 'webp' }, expiresIn: 1800 },
)

Signed uploads

signUploadParams signs a set of upload parameters so a browser can upload directly without exposing your secret. See Signed Upload.

import { signUploadParams } from '@tuzzle/url'

const signed = await signUploadParams(process.env.TUZZLE_SIGNED_URL_SECRET!, {
  params: { space: 'a1b2c3', filename: 'photo.jpg' },
  expiresIn: 3600,
})
// { params, signature, expires }

Never ship a signing secret to the browser. createTuzzle (URL building) never takes a secret; only createTuzzleSigner, signUrl, and signUploadParams do, and they belong on the server.