@povio/pdf-generator-lambda
v0.1.0-rc.9
Published
AWS Lambda container runtime for rendering PDFs & images with Chromium.
Keywords
Readme
PDF Generator Lambda Runtime
Standalone AWS Lambda container runtime for rendering the Shippy PDF generator static bundle with Chromium/Puppeteer.
This package intentionally does not contain PDF templates. The consuming project builds the PDF generator frontend and provides the generated single-file app as:
build/index.htmlThe Lambda handler loads that file locally and posts render requests into the browser page.
Expected Usage
Use this runtime in one of two supported modes:
- Template/local package mode: keep
packages/lambdainside a newly generated project from this template. This is the bootstrap mode before the runtime is extracted or published. The rootpnpm-workspace.yamlowns dependency versions through the workspace catalog, andpackages/lambda/Dockerfilebuilds the runtime from local source. - Published package mode: install
@povio/pdf-generator-lambdain an application repository. This is the expected mode after the runtime is published to npm. The package contains compiled JavaScript, declarations, a deploy Dockerfile, a staging CLI, andnpm-shrinkwrap.jsonfor deterministic Docker installs.
In both modes, the consuming project must provide:
- a built PDF generator bundle containing
index.html - a Chromium pack, either copied by the Dockerfile to
/opt/chromiumor provided throughCHROMIUM_BIN_DIR/CHROMIUM_PACK_URL - Node.js 24 in Docker builds
The production handler export is:
app.handlerThe Lambda Docker image built from the supported Dockerfile uses:
CMD ["app.handler"]For local non-Docker HTTP development, the package also provides an Express wrapper that calls the production handler:
pnpm --filter @povio/pdf-generator-lambda devThe local endpoint is:
POST http://localhost:9000/pdfThis path still requires the same Chromium runtime configuration as production. Set CHROMIUM_BIN_DIR or CHROMIUM_PACK_URL, or run the Docker image instead.
Bundle Location
The bundle location can be configured with:
PDFGEN_BUNDLE_URL: full URL loaded by Puppeteer, for examplefile:///var/task/build/index.html.PDFGEN_BUNDLE_PATH: filesystem path to the bundle file.PDFGEN_BUILD_DIR: directory containingindex.html.
If none are set, the runtime checks build/index.html from the current working directory first. In AWS Lambda containers this means /var/task/build/index.html.
Mode 1: Local Template Package
Use this mode when this repository has just been copied as the starting point for a new project and packages/lambda still exists in the application monorepo.
Local Development
pnpm install
pnpm --filter @povio/pdf-generator-lambda compileTo run the local HTTP wrapper from this repository, place a valid PDF generator bundle at packages/lambda/build/index.html, then run:
pnpm --filter @povio/pdf-generator-lambda devDocker Image From Local Source
packages/lambda/Dockerfile is the source-build Dockerfile. It expects the repository root as the Docker build context and the PDF generator bundle at:
packages/lambda/build/index.htmlExample local build:
pnpm --filter pdfgen build
rm -rf packages/lambda/build
mkdir -p packages/lambda/build
cp -R apps/pdfgen/build/. packages/lambda/build/
docker build -f packages/lambda/Dockerfile -t pdf-generator-lambda .Run the same Lambda image locally through the AWS Lambda runtime interface endpoint:
docker run --rm -p 9000:8080 pdf-generator-lambda
curl -X POST "http://localhost:9000/2015-03-31/functions/function/invocations" \
-H "Content-Type: application/json" \
-d '{"outputType":"pdf","data":{"template":"QuoteDocumentPreview","data":{}}}'The local compose file also uses the Lambda image:
docker compose -f packages/lambda/compose.yml up --buildGitHub Actions Shape For Local Template Package
If the lambda package is still local to the application monorepo, deploy by staging into packages/lambda/build and building from the repository root:
- name: Build pdfgen frontend
run: pnpm --filter pdfgen build
shell: bash
- name: Stage pdfgen build for local Lambda runtime
shell: bash
run: |
rm -rf packages/lambda/build
mkdir -p packages/lambda/build
cp -R apps/pdfgen/build/. packages/lambda/build/
- name: Build Lambda image
shell: bash
run: |
docker build \
--platform linux/arm64 \
--provenance=false \
--sbom=false \
-f packages/lambda/Dockerfile \
-t "$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" \
.Do not use Dockerfile.package directly in this mode. It is a template that gets copied into the published package as dist/Dockerfile.
Mode 2: Published NPM Package
Use this mode once @povio/pdf-generator-lambda is published and the application repository no longer contains packages/lambda.
Install the package in the consuming repository:
{
"devDependencies": {
"@povio/pdf-generator-lambda": "1.0.0"
}
}The published package contains its own Dockerfile and a small CLI for locating the installed runtime and staging the PDFGen build. The consuming workflow only needs to build the PDF generator frontend, stage it into the installed package, then build the package directory as the Docker context. The same Dockerfile is used for local Docker checks and deployment.
Local Install Before Publishing
Before the package is published, install a local build of this package into a consuming project:
# In monorepo-template
pnpm --filter @povio/pdf-generator-lambda lib:build
# In the consuming project
pnpm add -Dw "@povio/pdf-generator-lambda@file:../monorepo-template/packages/lambda/dist"After publishing, replace the file: dependency with a normal semver range:
pnpm add -Dw @povio/pdf-generator-lambda@^1.0.0Docker Image From Installed Package
pnpm install --frozen-lockfile
pnpm --filter pdfgen build
pnpm exec pdfgen-lambda-runtime stage apps/pdfgen/build
LAMBDA_RUNTIME_PATH="$(pnpm exec pdfgen-lambda-runtime path)"
docker build \
--platform linux/arm64 \
--provenance=false \
--sbom=false \
-f "$LAMBDA_RUNTIME_PATH/Dockerfile" \
-t pdf-generator-lambda \
"$LAMBDA_RUNTIME_PATH"If a workflow needs to stage into a custom extracted runtime directory, pass --runtime-dir:
pnpm exec pdfgen-lambda-runtime stage apps/pdfgen/build --runtime-dir "$PDFGEN_LAMBDA_RUNTIME_PATH"Local Docker Service From Installed Package
Build the PDFGen app first, stage it into the installed runtime package, then run the same Lambda image locally:
services:
pdf-generator:
build:
context: ./node_modules/@povio/pdf-generator-lambda
dockerfile: Dockerfile
ports:
- "${PDF_GENERATOR_PORT:-9000}:8080"Invoke it through the Lambda runtime interface endpoint:
POST http://localhost:9000/2015-03-31/functions/function/invocationsThe response is the Lambda proxy result object. For document bytes, parse the JSON response and decode the body payload's selected output field.
GitHub Actions Shape For Installed Package
- name: Build pdfgen frontend
run: pnpm --filter pdfgen build
shell: bash
- name: Stage pdfgen build for installed Lambda runtime
shell: bash
run: pnpm exec pdfgen-lambda-runtime stage apps/pdfgen/build
- name: Resolve Lambda runtime path
id: lambda-runtime
shell: bash
run: echo "path=$(pnpm exec pdfgen-lambda-runtime path)" >> "$GITHUB_OUTPUT"
- name: Build Lambda image
shell: bash
env:
LAMBDA_RUNTIME_PATH: ${{ steps.lambda-runtime.outputs.path }}
run: |
docker build \
--platform linux/arm64 \
--provenance=false \
--sbom=false \
-f "$LAMBDA_RUNTIME_PATH/Dockerfile" \
-t "$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" \
"$LAMBDA_RUNTIME_PATH"The deployed Lambda image handler remains app.handler; consumers do not need to configure a node_modules/... handler path.
Choosing A Mode
- New project generated from this template: start with local template package mode.
- Existing project after removing
apps/lambda: use published package mode. - Testing before npm publish: build
packages/lambda/distlocally, install it with afile:dependency, and use published package mode against that local package.
Package Scripts
Common scripts:
dev: runs the local Express wrapper atPOST /pdfthrough the production handler; requiresCHROMIUM_BIN_DIRorCHROMIUM_PACK_URLstart: runs the compiled Lambda handler fromdistclean: removes generated build outputcompile: compiles TypeScript intodistformat/format:check: formats or verifies package fileslint/lint:check: fixes or verifies lint issuescheck:ci: runs package-specific compile checks; root Turbo checks handle format and lint dependencieslib:build: builds the external package indistlib:publish: publishes the generateddistpackage
Build the publishable package:
pnpm --filter @povio/pdf-generator-lambda lib:buildThe generated dist/package.json resolves workspace catalog: dependencies into standalone semver ranges and exposes compiled files, the deploy Dockerfile, CLI helper, and npm shrinkwrap:
app.js
app.d.ts
bin/pdfgen-lambda-runtime.js
Dockerfile
npm-shrinkwrap.jsonRelease
Publishing is handled by the Publish Lambda to NPM GitHub Actions workflow.
Create a stable release tag:
git tag v1.2.3-lambda
git push origin v1.2.3-lambdaCreate an RC release tag:
git tag v1.2.3-rc.1-lambda
git push origin v1.2.3-rc.1-lambdaStable tags publish with the latest npm dist-tag. RC tags publish with the next npm dist-tag.
Runtime Inputs
Document render request:
{
"outputType": "pdf",
"format": "A4",
"data": {
"template": "QuoteDocumentPreview",
"data": {},
"landscape": false
}
}Supported output types are pdf, html, and png.
For PDF output, format is optional and defaults to A4. Supported values are Puppeteer paper formats:
Letter, Legal, Tabloid, Ledger, A0, A1, A2, A3, A4, A5, and A6.
The Lambda does not infer templates, languages, output formats, or remote HTML/assets. Callers must send render-ready data and choose outputType explicitly.
Request types are exported from the package root and the request subpath:
import type { RenderLambdaEvent, RenderRequest, RenderRequestBody } from "@povio/pdf-generator-lambda";
import type { RenderRequest as RenderRequestFromSubpath } from "@povio/pdf-generator-lambda/request";