Generate a PDF & upload to S3 using AWS Lambda & Puppeteer.
Tags: aws, serverless, node, tutorial
Published: 2022-06-09 18:09:13

---
title: Generate a PDF & upload to S3 using AWS Lambda & Puppeteer.
published: true
description: 
tags: #aws #serverless #node #tutorial
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/232ecofx47i7dqbjz0s1.png
---

I've put together a working project that'll take all of your dev.to posts, create a .pdf and upload it to S3. Ba-boom.

Head over to GitHub to grab the [code](https://github.com/danstanhope/aws-lambda-puppeteer).

First, a little bit about the project. It's run using sam cli and CloudFormation(make sure you've got your sam/aws cli installed and configured properly. Here's how to do [this](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-quickstart.html)). 

Modules and custom code will be compiled into a Lambda Layer. This is where all the requisite node_modules will live, as well as some custom code and our html templates. Cool thing about layers is once you've built it you can share it amongst your other functions. We're also going to be including another layer(``chrome-aws-lambda``), which will be used to run puppeteer inside the Lambda environment.

Here's what the .pdf looks like with my data(I know, not great. It's a .pdf and I'm no designer. Let's move on).

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qgl2af5lhntowoksyplv.png)

###Show me the code!

I briefly mentioned layers before, it's a pretty cool feature of AWS Lambda. If you've got a bunch of functions running and you want to share node_modules or custom code(i.e. adapters, helper functions, templates etc.) you can create 1 or more layers and attach them to your functions.

When importing anything other than a ``node_module`` you need to reference a different path(``/opt/``). Here you can see the modules being included vs. the custom code.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vts9dg0wlnfsiau17zca.png)

The function is quite simple, we start off by ingesting our html template from our layer and initializing a few variables(*note: change the bucket name to something other than my name). Next, we pull down some dev.to posts and compile our template.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s90new88vhash5tyq4vg.png)

Then we initialize puppeteer and pass in our template string. We'll create a buffer and give this to our S3 upload method.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h99keu35uasi5fh6vyal.png)

Guys. That's it. It's done. We made a .pdf.

###How do I run this?

Once you've cloned the repo, head into ``/layers/shared/nodejs`` and run ``yarn``. This will install all the packages we need. You can add this to a build step at some point, too. When creating a layer, it's important to note that you need to include the function's runtime as part of the folder structure in order for lambda to recognize it(in this case ``nodejs``). 

Jump back into the root of the project and run: ```sam local invoke PuppeteerFunction --no-event```

If you've configured everything properly, you should have a nice .pdf created & waiting for you in S3.

One thing to note, there is some strange bug with the aws chrome package and it's not working with Nodejs14. That's why all the runtimes are set to Nodejs12. If you can get it working with a more up-to-date runtime, please let me know and I'll update the repo.

Thanks so much for reading! Hope this helps someone.