Build an Online Resume with an Auto-Updating PDF Version




1200 og

Want a resume that stands out but doesn’t cause too much trouble to edit? I have you covered.

In this tutorial, you’ll not only create a professional looking resume, but also learn about the basics of GitHub actions and Netlify.

By the end of the article, you’ll have a great looking resume with automated PDF versions in both Letter, and A4 format. And you can update it with a single text file and one commit to your GitHub repository.

What We’ll Use

For this tutorial, we will use

The Resume itself is based on the phantastic DevCard theme by Xiaoying Riley.

Let’s Go!

Get An Account on PDF.co

Sign up for an account on PDF.co and head to the Dashboard.
The service is not free per se, but comes with a generous offer of 600 credits. Enough for our resume project and a a few edits of our resume.

On the dashboard, select “View Your API key” and save it somewhere. It should look like this:




pdf co db

Get An Account on Netlify

Next, you’ll need an account at Netlify. Netlify is a hosting service for static sites and offers a good free tier.

Usually, you would use Netlify to run the build jobs for you. In our case, we will do the builds on GitHub actions.

To start a manually deployed site, just click on “Deploy manually” in the “Add new site” dropdown.




nf dep man

You need to upload a starter, so any folder with an empty index.html file is good to go.

In the config section for your new site, click on “Site settings” and copy your “Site ID”:




nf site id

Next, head over to your user’s settings and create a personal access token:




nf token 1





nf token 2

Fork the GitHub Repository

Had over to the GitHub repository and click the fork button. That should only take a few seconds.

Configure the Repository

Next, head over to the Repository settings page.




gh repo settings

Create a new repository secret called NETLIFY_TOKEN and put your Netlify personal access token in here.

Next, create another repository secret called PDFCO_KEY and paste your PDF.co API key.

In the “Variables” tab, create two repository variables:

NETLIFY_SITE_ID with the site ID from your Netlify settings, and RESUME_URL with the URL of your resume. It’s okay to use Netlify’s URL (something like majestic-chaja-1234.netlify.app) here for the moment.

In your GitHub’s repository settings, head over to “Actions” > “General” and make sure that “Read and write permissions” are set in the “Workflow Permissions” section.




gh wf perm

Configure Your Resume

Next, check out your forked repository and open it with your favourite IDE. The only file you need to edit is confg.toml which includes all the sections of your resume.

Once you commit and push your changes, the magic will start: GitHub Actions will wind a machine up to build your resume using hugo, upload it to netlify, have pdf.co create the PDF versions, then upload the PDFs to Netlify as well, and finally commit the final PDFs to your repos. Let’s see how that works in detail.

GitHub Actions

GitHub Actions are a free GitHub feature that automates tasks around your code. People use it, for example, to run automated tests on their code.

These actions are defined in a special file called .github/workflows/actions.yml in our repository.

The first two entries in the yaml file define the action’s name and an event that triggers the action to run. In our case, we want the actions to run on every push to the repository.

name: run main.py

on:
  push:
    branches:
      - main

The interesting part starts in the jobs section of the file. Jobs contain steps that run on virtual machine provided on demand by GitHub. These step build upon each other, so that the steps are like a script that automates something along the lines.

The first steps in the resume repo check out the repository itself and install Hugo, and a Python environment for us:

      - name: checkout repo content
        uses: actions/checkout@v3 # checkout the repository content to github runner

      - name: setup python
        uses: actions/setup-python@v4
        with:
          python-version: '3.9' # install the python version needed
          
      - name: install python packages
        run: |
          python -m pip install --upgrade pip
          pip install -r requirements.txt

      - name: Setup hugo
        uses: peaceiris/actions-hugo@v2
        with:
          hugo-version: "0.110.0"
          extended: true

With the next steps, we build the site using hugo and upload the public directory to Netlify:

      - name: Build Website
        run: hugo --minify

      - name: Deploy to Netlify
        run: netlify deploy --dir=public --message="Auto Deploy" --prod
        env: 
          NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_TOKEN }}
          NETLIFY_SITE_ID: ${{ vars.NETLIFY_SITE_ID }}

Here, we see why we needed the repository variables and secrets. They are used inside the job steps to authenticate where necessary.

The next step generates the PDFs for us:

      - name: generate PDFs # run main.py
        env:
          PDFCO_KEY: ${{ secrets.PDFCO_KEY }}
          RESUME_URL: ${{ vars.RESUME_URL }}
        run: |
          mkdir static_pdf
          python get_pdf.py
          cp static_pdf/*.pdf ./static/
          cp static_pdf/*.pdf ./public/

The generation process itself is done using a simple API call to pdf.co. The code for this resides in the get_pdf.py file:

import requests
from pathlib import Path
import os
import uuid

uid = uuid.uuid4()
from datetime import datetime
current_date = datetime.now()
at = current_date.isoformat()


API_KEY = os.environ.get("PDFCO_KEY")
URL = os.environ.get("RESUME_URL")

def get(fmt="Letter"):
    config = {
      ...
    }
    url = "https://api.pdf.co/v1/pdf/convert/from/url"
    r = requests.post(url, json=config, headers={"x-api-key": API_KEY})
    result = r.json()
    url = result["url"]
    r = requests.get(url)
    with open(f"resume.{fmt}.pdf", "wb") as f:
        f.write(r.content)
    return Path(f"resume.{fmt}.pdf")


if __name__ == "__main__":
    fmts = ['Letter', 'A4']
    for fmt in fmts:
        get(fmt=fmt).rename(f"static_pdf/resume.{fmt.lower()}.pdf")

Again, we see the usage of repository secrets and variables inside the Python script. We can access particular values with os.environ.get("..."). This way, we do not share sensitive information, such as API keys in our code.

The last steps of our job upload the fresh PDF files to Netlify, and pushes the changes to our repo.

      - name: Deploy to Netlify
        run: netlify deploy --dir=public --message="Auto Deploy with PDFs" --prod
        env: 
          NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_TOKEN }}
          NETLIFY_SITE_ID: ${{ vars.NETLIFY_SITE_ID }}
          
      - name: commit files
        run: |
          git config --local user.email "ac****@****ub.com"
          git config --local user.name "GitHub Action"
          git add static
          git diff-index --quiet HEAD || (git commit -a -m "updated PDFs" --allow-empty)
          
      - name: push changes
        uses: ad-m/github-push-action@v0.6.0
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          branch: main 

This is why the latest commit on the repo is always done by the Actions user




gh actions user

This should give you a quick overview about GitHub actions. Even though we just hadle a simple resume here, it gives a glimpse on how modern software development is done in the cloud.

The Result




resume result

I have created my own resume with this repo here: resume.bas.work.

Read More
Stephania Kazmierczak

Latest

Nestory Irankunda scores Australia’s first World Cup goal against Turkiye

Nestory Irankunda buried Australia’s opening goal of the 2026 FIFA World Cup on June 14, finishing a counter-attack in the 27th minute against Turkiye in Vancouver. At 20 years old, he became the youngest player in Socceroos history to score at a World Cup. The goal gave Australia a 1-0 lead in their Group D

Carlo Ancelotti takes responsibility for Brazil’s 1-1 draw with Morocco as crypto fan tokens enter the World Cup spotlight

Brazil opened their 2026 FIFA World Cup campaign with a 1-1 draw against Morocco on June 13, and Carlo Ancelotti accepted full responsibility for the tactical shortcomings that left the five-time champions splitting points in their Group C opener. Ancelotti promised improvement and reminded everyone that you don’t win a World Cup in your first

Scotland defeats Haiti 1-0 in World Cup opener, tops Group C

Scotland picked up their first World Cup victory in 28 years on June 13, beating Haiti 1-0 in their Group C opener at the 2026 FIFA World Cup. John McGinn scored the only goal of the match in the 28th minute, pouncing on a rebound after Haitian goalkeeper Johny Placide saved an initial effort from

Pyth Network Targets Bloomberg’s $50 Billion Market-Data Empire

Pyth Network is pushing deeper into the more than $50 billion market for financial data, launching 24/7 index products across metals, oil, and U.S. equities as it positions its onchain price feeds against incumbents like Bloomberg. Key Takeaways Pyth Network launched 24/7 indices for metals, oil, and U.S. equities, adopted by Coinbase and Kraken. Euronext

Newsletter

Don't miss

Nestory Irankunda scores Australia’s first World Cup goal against Turkiye

Nestory Irankunda buried Australia’s opening goal of the 2026 FIFA World Cup on June 14, finishing a counter-attack in the 27th minute against Turkiye in Vancouver. At 20 years old, he became the youngest player in Socceroos history to score at a World Cup. The goal gave Australia a 1-0 lead in their Group D

Carlo Ancelotti takes responsibility for Brazil’s 1-1 draw with Morocco as crypto fan tokens enter the World Cup spotlight

Brazil opened their 2026 FIFA World Cup campaign with a 1-1 draw against Morocco on June 13, and Carlo Ancelotti accepted full responsibility for the tactical shortcomings that left the five-time champions splitting points in their Group C opener. Ancelotti promised improvement and reminded everyone that you don’t win a World Cup in your first

Scotland defeats Haiti 1-0 in World Cup opener, tops Group C

Scotland picked up their first World Cup victory in 28 years on June 13, beating Haiti 1-0 in their Group C opener at the 2026 FIFA World Cup. John McGinn scored the only goal of the match in the 28th minute, pouncing on a rebound after Haitian goalkeeper Johny Placide saved an initial effort from

Pyth Network Targets Bloomberg’s $50 Billion Market-Data Empire

Pyth Network is pushing deeper into the more than $50 billion market for financial data, launching 24/7 index products across metals, oil, and U.S. equities as it positions its onchain price feeds against incumbents like Bloomberg. Key Takeaways Pyth Network launched 24/7 indices for metals, oil, and U.S. equities, adopted by Coinbase and Kraken. Euronext

Macron and Trump test their bruised bromance at G7 summit

For help please visit help.ft.com. We apologise for any inconvenience. The following information can help our support team to resolve this issue. Reason Challenge Request ID a0ba469e68afe135 Status Code 403

Your business texts could look like scam messages from July 1 if you don’t act now

From July 1, any branded SMS your business sends without a registered sender ID will be labelled “Unverified” and grouped with scam messages.  What’s happening: From 1 July 2026, any business or organisation that sends SMS using a branded name, such as “MyShop” or “AcmeServices”, instead of a phone number, must have that sender ID

Business groups are fighting Labor’s CGT changes. Here is where SMEs stand

Labor’s most contested tax reform in a generation cleared its first formal hurdle on Thursday and immediately ran into organised resistance. Treasurer Jim Chalmers introduced the government’s tax reform legislation to the House of Representatives on 28 May, bundling together four budget measures: the capital gains tax overhaul, new limits on negative gearing, a $250

Meet the most influential business owners from Southwest Nigeria

This article spotlights the most influential business owners from Southwest Nigeria, adjudged by their dominance in their respective sectors of the economy where they operate. The post Meet the most influential business owners from Southwest Nigeria appeared first on Nairametrics...