# Automate Your Résumé PDF Generation with AI: A FastAPI & WeasyPrint Tutorial

> Published 2025-02-22 · https://www.promptzone.com/resumeburger/automate-your-resume-pdf-generation-with-ai-a-fastapi-weasyprint-tutorial-k5e

In today’s digital age, your résumé isn’t just a static document—it’s a dynamic showcase of your professional potential. At ResumeBurger, we’re all about transforming your résumé into a polished, recruiter-approved PDF with minimal effort. In this tutorial, we’ll build an API endpoint using FastAPI that takes your résumé text, enhances it using OpenAI, formats it with HTML templates, and converts it into a high-quality PDF using WeasyPrint.

---

## What You’ll Need

- **Python 3.x** installed on your system  
- Basic knowledge of Python scripting  
- An OpenAI API key (store it securely in a `.env` file)  
- The following Python packages:
  - [FastAPI](https://fastapi.tiangolo.com/)
  - [uvicorn](https://www.uvicorn.org/) for serving the app
  - [openai](https://pypi.org/project/openai/)
  - [python-dotenv](https://pypi.org/project/python-dotenv/)
  - [Jinja2](https://pypi.org/project/Jinja2/) for templating  
  - [WeasyPrint](https://weasyprint.org/) for PDF generation

Install the dependencies with:

```bash
pip install fastapi uvicorn openai python-dotenv jinja2 WeasyPrint
```

---

## Step 1: Secure Your Credentials and Create a Template

### Create a `.env` File

Store your OpenAI API key in a `.env` file in your project directory:

```env
OPENAI_API_KEY=your_openai_api_key_here
```

### Create an HTML Template

Create a file named `resume_template.html` with the following content (feel free to style it with Tailwind CSS or custom CSS):

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Optimized Résumé</title>
    <style>
      body { font-family: Arial, sans-serif; margin: 40px; }
      h1 { font-size: 2em; border-bottom: 2px solid #333; padding-bottom: 0.5em; }
      p { line-height: 1.6; }
    </style>
  </head>
  <body>
    <h1>{{ name }}</h1>
    <h2>Professional Summary</h2>
    <p>{{ summary }}</p>
    <h2>Experience</h2>
    <p>{{ experience }}</p>
    <h2>Education</h2>
    <p>{{ education }}</p>
    <!-- Add more sections as needed -->
  </body>
</html>
```

This template will be used to generate a styled HTML résumé before converting it into a PDF.

---

## Step 2: Build the FastAPI Endpoint

We’ll create a FastAPI application that enhances the résumé text with OpenAI, renders the HTML template, and generates a PDF with WeasyPrint.

```python
import os
import openai
from dotenv import load_dotenv
from fastapi import FastAPI, HTTPException, Response
from fastapi.responses import StreamingResponse
from pydantic import BaseModel
from jinja2 import Environment, FileSystemLoader
from weasyprint import HTML
import io

# Load environment variables
load_dotenv()
openai.api_key = os.getenv("OPENAI_API_KEY")

app = FastAPI(title="ResumeBurger PDF Generator")

# Define request model
class ResumeData(BaseModel):
    name: str
    summary: str
    experience: str
    education: str
    job_description: str  # This could be used to tailor the résumé further

def enhance_resume_section(text: str, job_description: str) -> str:
    prompt = (
        f"Enhance the following résumé section to better align with the job description provided.\n\n"
        f"Section text:\n{text}\n\nJob description:\n{job_description}\n\n"
        "Provide a refined, professional version."
    )
    try:
        response = openai.ChatCompletion.create(
            model="gpt-3.5-turbo",
            messages=[{"role": "user", "content": prompt}],
            max_tokens=150,
            temperature=0.7,
        )
        return response.choices[0].message.content.strip()
    except Exception as e:
        raise Exception(f"OpenAI API error: {e}")

@app.post("/generate-resume-pdf")
async def generate_resume_pdf(data: ResumeData):
    try:
        # Enhance résumé sections using OpenAI
        enhanced_summary = enhance_resume_section(data.summary, data.job_description)
        enhanced_experience = enhance_resume_section(data.experience, data.job_description)
        enhanced_education = enhance_resume_section(data.education, data.job_description)
    except Exception as error:
        raise HTTPException(status_code=500, detail=str(error))

    # Set up Jinja2 environment to load HTML template
    env = Environment(loader=FileSystemLoader('.'))
    template = env.get_template("resume_template.html")
    html_content = template.render(
        name=data.name,
        summary=enhanced_summary,
        experience=enhanced_experience,
        education=enhanced_education
    )

    # Generate PDF using WeasyPrint
    pdf_file = HTML(string=html_content).write_pdf()
    pdf_stream = io.BytesIO(pdf_file)
    pdf_stream.seek(0)

    headers = {
        "Content-Disposition": f"attachment; filename={data.name.replace(' ', '_')}_Resume.pdf"
    }
    return StreamingResponse(pdf_stream, media_type="application/pdf", headers=headers)

if __name__ == "__main__":
    import uvicorn
    uvicorn.run("your_script_name:app", host="0.0.0.0", port=8000, reload=True)
```

Replace `"your_script_name"` with your file name (without the `.py` extension).

### How It Works

- **Enhancing Text:**  
  The `enhance_resume_section` function sends each résumé section (summary, experience, education) along with the job description to OpenAI. It refines the text for clarity and impact.

- **Template Rendering:**  
  The enhanced sections are injected into the `resume_template.html` file using Jinja2, producing a well-formatted HTML document.

- **PDF Generation:**  
  WeasyPrint converts the HTML into a PDF, which is then returned as a downloadable file via FastAPI.

---

## Step 3: Testing and Deployment

- **Local Testing:**  
  Run the application with:
  ```bash
  uvicorn your_script_name:app --reload
  ```
  Send a POST request to `http://localhost:8000/generate-resume-pdf` with a JSON body:
  ```json
  {
      "name": "Jane Doe",
      "summary": "Experienced software developer with a background in AI.",
      "experience": "5 years of experience at tech companies.",
      "education": "Bachelor's degree in Computer Science.",
      "job_description": "Looking for a candidate with strong AI, machine learning, and cloud computing skills."
  }
  ```
  The API will return a PDF file that you can download and review.

- **Docker Deployment (Optional):**  
  Containerize your application using a Dockerfile for scalable deployment.

---

## Conclusion

With this tutorial, you’ve built a powerful tool that automates the entire résumé PDF generation process—from AI-enhanced text refinement to PDF conversion. By leveraging FastAPI, OpenAI, Jinja2, and WeasyPrint, you can provide job seekers with professional, recruiter-approved résumés in minutes.

Customize the templates and enhancement prompts to best suit your audience, integrate with ResumeBurger’s platform, and empower users to stand out in today’s competitive job market.

Happy coding, and here’s to landing your dream job with a standout résumé!