npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@hyperframes/aws-lambda

v0.6.29

Published

AWS Lambda adapter for HyperFrames distributed rendering — handler, client-side SDK, and CDK construct.

Downloads

870

Readme

@hyperframes/aws-lambda

AWS Lambda adapter for HyperFrames distributed rendering. Ships three things together:

  1. The Lambda handler that wraps the OSS plan / renderChunk / assemble primitives behind a single dispatch boundary Step Functions can drive (src/handler.ts).
  2. A client-side SDKrenderToLambda, getRenderProgress, deploySite, plus validateDistributedRenderConfig and computeRenderCost (src/sdk/).
  3. An aws-cdk-lib L2 construct (HyperframesRenderStack) that provisions the same topology as examples/aws-lambda/template.yaml inside an adopter's own CDK app (src/cdk/).

The handler ZIP and the SAM template still drive a maintainer-run real-AWS smoke flow; the SDK + CDK are the supported public surface for adopters.

Architecture

┌──────────────────────────────────────────────────────────────────┐
│ Step Functions state machine                                     │
│   Plan → Map(N) RenderChunk → Assemble                           │
└──────────────────────────────────────────────────────────────────┘
                              │ dispatches by event.Action
                              ▼
┌──────────────────────────────────────────────────────────────────┐
│ One Lambda function (this package's `dist/handler.zip`)          │
│   handler.mjs                                                    │
│     ├─ Action="plan"        → @hyperframes/producer/distributed  │
│     ├─ Action="renderChunk" → @hyperframes/producer/distributed  │
│     └─ Action="assemble"    → @hyperframes/producer/distributed  │
│   bin/ffmpeg                — ffmpeg-static                      │
│   node_modules/@sparticuz/chromium/ — Lambda-optimised Chromium  │
└──────────────────────────────────────────────────────────────────┘
                              │ pure functions over local paths
                              ▼
┌──────────────────────────────────────────────────────────────────┐
│ S3 bucket — plan tarball + per-chunk outputs + final mp4         │
└──────────────────────────────────────────────────────────────────┘

The handler downloads inputs from S3 into /tmp, calls the OSS primitive, uploads outputs back to S3, and returns a small JSON result that fits inside Step Functions' history budget (under 200 bytes per chunk).

Chrome runtime

The package supports two Chromium sources:

| Source | Default | Size | When to pick it | | ------------------------------- | ------- | ------------------ | --------------------------------------------------------------------------------------------------------------------- | | @sparticuz/chromium | yes | ~70 MiB compressed | Lambda. Decompresses into /tmp at runtime; the rest of the ecosystem already uses it for headless-Chrome-in-Lambda. | | Bundled chrome-headless-shell | no | ~140 MiB | Fallback. Used if @sparticuz/chromium ever drops HeadlessExperimental.beginFrame support. |

Pick the source at build time:

bun run --cwd packages/aws-lambda build:zip
bun run --cwd packages/aws-lambda build:zip -- --source=chrome-headless-shell

The handler reads HYPERFRAMES_LAMBDA_CHROME_SOURCE at boot. The build script sets that env var via Lambda function configuration in examples/aws-lambda/template.yaml.

BeginFrame regression guard

HyperFrames' renderer drives Chrome via the CDP HeadlessExperimental.beginFrame command — same path the K8s deploy uses. The Lambda adapter assumes that @sparticuz/chromium's chrome-headless-shell build honours BeginFrame. To prove it (and re-prove it on every release), the package ships a Docker probe:

# Build the Lambda-like container and run the probe.
bun run --cwd packages/aws-lambda probe:beginframe:docker

The probe boots @sparticuz/chromium inside public.ecr.aws/lambda/nodejs:22 and asserts CDP beginFrame with screenshot: true returns a PNG buffer. Exit code 0 = green; non-zero = fall back to bundling chrome-headless-shell directly via --source=chrome-headless-shell.

Building the ZIP

bun install                                          # at the monorepo root
bun run --cwd packages/aws-lambda build:zip          # → packages/aws-lambda/dist/handler.zip
bun run --cwd packages/aws-lambda verify:zip-size    # CI gate

The build script bundles src/handler.ts via esbuild, stages @sparticuz/chromium and puppeteer-core under node_modules/, copies ffmpeg-static into bin/, and zips the result. The unzipped layout is designed to extract cleanly into Lambda's /var/task/.

verify:zip-size enforces:

  • Unzipped ≤ 248 MiB (in-house budget; Lambda hard ceiling is 250 MiB unzipped — AWS docs label this "250 MB" but use binary mebibytes)
  • Zipped ≤ 150 MiB (in-house budget; Lambda has no hard zipped cap for S3-deployed functions)

CI fails the PR if either is exceeded.

Running tests

bun run --cwd packages/aws-lambda test               # unit tests (no Chrome)
bun run --cwd packages/aws-lambda probe:beginframe   # local probe (Linux only)

Using the SDK

After deploying the stack (via the SAM template, CDK construct below, or your own CFN of choice), drive renders from Node:

import { deploySite, getRenderProgress, renderToLambda } from "@hyperframes/aws-lambda";

// One-time upload per project version.
const site = await deploySite({
  projectDir: "./my-composition",
  bucketName: "hyperframes-render-bucket",
});

// Start a render. Returns immediately — does NOT poll.
const handle = await renderToLambda({
  siteHandle: site,
  bucketName: site.bucketName,
  stateMachineArn: "arn:aws:states:us-east-1:123:stateMachine:hyperframes-render",
  config: {
    fps: 30,
    width: 1920,
    height: 1080,
    format: "mp4",
    chunkSize: 240,
    maxParallelChunks: 16,
    runtimeCap: "lambda",
  },
});

// Poll progress + cost on your own cadence.
const progress = await getRenderProgress({ executionArn: handle.executionArn });
console.log(progress.overallProgress, progress.costs.displayCost);
if (progress.status === "SUCCEEDED" && progress.outputFile) {
  console.log("Render landed at", progress.outputFile.s3Uri);
}

renderToLambda validates the config client-side via validateDistributedRenderConfig and throws a typed InvalidConfigError before the Step Functions execution starts, so shape errors surface synchronously instead of as opaque ExecutionFailed results.

getRenderProgress reports an approximate per-render cost (accruedSoFarUsd plus a formatted displayCost) derived from Lambda billed-duration × memory × the us-east-1 on-demand rate plus the Step Functions transition price. The math is documented in src/sdk/costAccounting.ts; numbers are best-effort and exclude S3 transfer.

Using the CDK construct

import { App, Stack } from "aws-cdk-lib";
import { HyperframesRenderStack } from "@hyperframes/aws-lambda/cdk";

const app = new App();
const stack = new Stack(app, "MyApp");
const render = new HyperframesRenderStack(stack, "Render", {
  // optional: reservedConcurrency: 8,
  // optional: lambdaMemoryMb: 10240,
  // optional: chromeSource: "sparticuz",
});

// Re-export so an adopter app can wire dashboards / SNS topics.
new CfnOutput(stack, "RenderBucketName", { value: render.bucket.bucketName });
new CfnOutput(stack, "StateMachineArn", { value: render.stateMachine.stateMachineArn });

aws-cdk-lib and constructs are optional peer dependencies: SDK-only consumers don't pull them at runtime. The construct itself imports from @hyperframes/aws-lambda/cdk.

What's still ahead

  • hyperframes lambda CLI (deploy / sites create / render / progress / destroy) — PR 6.5.
  • IAM bootstrap subcommand (policies role | user | validate) — PR 6.9.
  • Lambda-local regression harness (--mode=lambda-local) — PR 6.6.
  • Adopter-facing migration guide — PR 6.8.