Learn how to design and generate a beautiful PDF in your Bubble.io app. Save the PDF to your database and let users download it.
Contents
Overview
Generating PDFs in Bubble can be a pain. While there are plenty of options available via the Bubble plugin marketplace, these can be of mixed quality. There are also a range of external APIs that can be used to generate PDFs, but these solutions are usually not designed specifically for Bubble apps and come with a range of limitations.
This article will show how you can generate PDFs from your Bubble.io app with PDF Potion, a PDF solution built specifically for Bubble.
Designing your PDF
PDF Potion is going to generate a PDF of a specific target page in your Bubble app. We typically recommend creating a separate page in your app for this purpose. This page will be used purely for generating PDFs and your users should never end up actually seeing it. In the below example, we're creating a new page called 'pdf':

Next, you're going to want to design your PDF. Before adding any elements to your pdf page, we recommend changing the 'Container Layout' of the page to 'Container'. You can
In the image below, we've added two groups:
- A 'cover-page' group that will act as the front/cover page of our PDF (we've added an image as the background)
- A 'quotation' group that will contain details on a quote for a service

Setting the dimensions of your PDF page
We recommend using groups (or repeating groups) to create 'pages' in your PDF. To ensure your design matches the output PDF, it is recommended to set the dimensions of each group to be equal to the dimensions of the PDF you're creating. In this example, we're going to be creating an A4-sized PDF in portrait mode, so we'll set the height of each group to be 1123px and the width to be 794px. You can see a full list of recommended dimensions for different formats here.
Installing PDF Potion
Now that we have some elements on our pdf page, you can start building a workflow in your Bubble app to generate a PDF of it. Go to the 'Plugins' tab of your Bubble editor and install the PDF Potion plugin:

Next, you'll need to add an access token to the 'Access Token' and 'Access Token - dev.' fields in the PDF Potion plugin section of your Bubble editor:

To get an access token, go the PDF Potion website and sign up for an account by clicking on the 'Register / Sign in' button in the top navigation bar. Once you sign up for an account, you'll be brought to a dashboard area. You can get your access token by navigating to the 'My Account' tab and clicking on the 'Generate Access Token' button.

Once you paste your access token into the 'Access Token' and 'Access Token - dev.' fields, you're good to go!
NOTE: You will use the same access token for both the 'Access Token' and 'Access Token - dev.' fields.
Generating the PDF
To generate the PDF, add a button to the page in your Bubble app where the user will be triggering the PDF creation. Attach a new workflow to the button and add the 'Create PDF' action that comes with the PDF Potion plugin. Add the dynamic expression 'Website home URL' to the 'Website Home URL' field and the name of the page where you designed your PDF to the 'Page Name' field:

Please note that you will have two issues at this stage, because the 'Identifier' and 'Callback URL' fields are blank (we will come to this shortly), but you can still proceed with generating your PDF.
Click on the button you've attached the workflow to and navigate to the 'File Manager' section of the Database tab in your Bubble editor. You will see a a PDF file there (you may need to refresh your browser as it does take a few seconds for PDF Potion to generate the PDF and upload it to your database).

Click on the file name and your beautifully designed PDF should open in a new window of your browser.
Linking the PDF to an entry in your Bubble database
Next, we'll link the PDF to a specific entry in your Bubble database. To do this, you'll need to create a text field on a data type. The data type you choose will depend on how your app is structured, but in the example below we've created a data type called 'Report' and added a field called 'Link' (type text).

Go back to the workflow where you've added the 'Create PDF' action. Insert an action BEFORE the 'Create PDF' action and create a new Report (or whatever custom data type you're using). You do NOT need to change any fields on the Report at this stage. For the 'Identifier' field in the 'Create PDF' action, you can now add in the unique ID for the Report you've just created:

The Callback URL field will be used to run a backend workflow that adds the URL associated with the PDF to the 'Link' field on your Report data type. In order to use the callback URL, you will need to enable backend workflows in your Bubble editor by going to:
Settings -> API -> check the 'Enable Workflow API and backend workflows' option

NOTE: you will need to be on a paid Bubble plan to do this
Navigate to the backend workflows section of your Bubble editor and create a new API workflow (in the example below, we've called ours 'get_pdf'). Add in two keys:
- id (type text)
- link (type text)
You MUST use the exact spelling specified above for these two keys.

Add an action to the workflow that makes changes to a Report. You can filter for the first item where the unique id = id (the key that is being passed through). This means we're searching for the first (and only) Report in our database where it's unique id = the Key id.
Change the 'Link' field of the Report to equal the 'link' key value:

This API workflow is the Callback URL we need to add to the 'Create PDF' action. To get the correct value for it, you can go to:
Settings -> API
and copy the 'Workflow API Root URL' value:

Copy and paste this value into your 'Callback URL' field in the 'Create PDF' action and add the name of your backend workflow to the very end of it. Then, replace all text BEFORE 'api...' with the dynamic expression 'Website home URL'. You will end up with something like this:

Now, when you run the workflow with the 'Create PDF' action, the URL associated with the PDF will be added to the 'Link' field in your Bubble database:

Letting users download the PDF
To enable users to download their PDFs, create a custom event on the page where users generate PDFs. In the below example, we've called our custom event 'PDF Created'. Add a parameter to the custom event, EG 'Report', and set its data type to match the custom data type used to link to the PDF:

Add the 'Download PDF' action to the workflow. Set the 'link' field to 'Report's Link (or your designated custom data type and link field) and specify the desired file name:

Ensure this custom event is triggered each time a PDF is generated by adding a 'Trigger custom event when data changes' action to the original workflow containing the 'Create PDF' action.
Set the 'Thing to watch" as the "Report' (or equivalent custom data type you're using), and the 'Field to watch' as 'Link' (or the field where the PDF URL is stored):
Now, when the 'Link' field is updated with the URL associated the PDF, the PDF will be downloaded in the user's browser.

Using dynamic data in your PDF
It's quite likely you'll want to include some dynamic data in your PDF. In order to do this, you'll need to add some information to the 'Page Name' field in the 'Create PDF' action. For example, in the below demo app, there's two custom data types highlighted:
- Quotation has a custom field called Products (which is a list of products)
- Products contains info on a good that was sold

Here's a 'Quotation' entry in our database that has 3 products attached to it.:

If I wanted to view this data on the 'pdf' page in our Bubble, we can:
- Set the 'Type of content' on the page to be 'Quotation'
- Set the 'Type of content' on the repeating group to be 'Product'
- Use a repeating group to show Current Page's Quotation Product's

If I navigate to the URL https://website.com/pdf, no data will appear (because the repeating group has no Quotation data to reference):]

But if we add the unique ID of the Quotation to the end of the URL, data will display - this is because we're effectively sending data to the page by adding the unique ID to the end of the URL:

The same concept applies to creating PDFs with PDF Potion. You can add dynamic data to the PDFs you're creating by adding a unique ID of a thing to the end of the 'Page Name' field:

Of course, in reality you're probably going to want to make this dynamic. You can do this by referencing a thing saved to your database in the 'Page Name' field. In many cases, this may be the 'thing' you create earlier in the workflow:

You can watch this video for an example of how to implement this.
Adding a loading screen for improved UX
It takes a few seconds for PDF Potion to generate a PDF and upload it to your Bubble database. To improve the experience of the end user, you may wish to add a loading screen while the PDF is being generated. This lets the user know that something is happening in the background and can avoid confusion.
Therefore, we showing a loading screen while PDF Potion is generating the PDF. There are a number of ways to do this, but the most straightforward is to simply show a floating group over all your elements while the PDF is being generated.



Further resources