Skip to content

PDF Resource

The PDF resource generates a PDF file from HTML or Markdown content using one of three rendering backends. It can be used as a primary resource or as an inline resource inside before / after blocks.

Basic Usage

yaml
apiVersion: kdeps.io/v1
kind: Resource

metadata:
  actionId: generateReport
  name: Generate Report

run:
  pdf:
    content: "<h1>Hello, World!</h1><p>This is a PDF report.</p>"
    contentType: html
    backend: wkhtmltopdf

Configuration Options

OptionTypeDescription
contentstringRequired. The HTML or Markdown source to render. Supports expressions.
contentTypestringhtml (default) or markdown.
backendstringwkhtmltopdf (default), pandoc, or weasyprint.
outputFilestringExplicit output path for the PDF. If omitted, a path under /tmp/kdeps-pdf/ is auto-generated.
optionslistExtra CLI flags passed directly to the backend binary.
timeoutDurationstringMaximum time allowed for the backend to run (e.g. 120s, 2m). Default: 60s.

Backends

wkhtmltopdf (default)

Renders HTML to PDF using the wkhtmltopdf CLI. When contentType: markdown, the Markdown is wrapped in a minimal HTML skeleton before rendering.

Install:

bash
# macOS
brew install wkhtmltopdf

# Debian/Ubuntu
apt install wkhtmltopdf
yaml
run:
  pdf:
    content: "<h1>Report</h1><p>Generated by KDeps.</p>"
    contentType: html
    backend: wkhtmltopdf
    options:
      - "--page-size"
      - "A4"
      - "--margin-top"
      - "10mm"

pandoc

Converts HTML or Markdown to PDF via pandoc + a LaTeX engine (e.g. pdflatex or xelatex). Best choice for Markdown-heavy documents and academic/technical reports.

Install:

bash
# macOS
brew install pandoc mactex

# Debian/Ubuntu
apt install pandoc texlive-xetex
yaml
run:
  pdf:
    content: |
      # My Report

      This is a **Markdown** report with _formatting_.

      - Item one
      - Item two
    contentType: markdown
    backend: pandoc
    options:
      - "--pdf-engine=xelatex"
      - "--variable"
      - "geometry:margin=1in"

weasyprint

Renders HTML/CSS to PDF using the WeasyPrint Python library. Excellent CSS support; good for styled reports and invoices.

Install:

bash
pip install weasyprint
yaml
run:
  pdf:
    content: |
      <html>
      <head><style>
        body { font-family: Arial, sans-serif; }
        h1 { color: #333; }
      </style></head>
      <body><h1>Styled Report</h1><p>Beautiful CSS-rendered PDF.</p></body>
      </html>
    contentType: html
    backend: weasyprint

Accessing the Output File

After the PDF resource runs, the result map is available via get('actionId'):

KeyTypeDescription
successbooltrue if the PDF was generated successfully.
outputFilestringAbsolute path to the generated PDF file.
backendstringBackend used (e.g. wkhtmltopdf).
contentTypestringContent type used (html or markdown).
sizeBytesintFile size of the generated PDF in bytes.
yaml
resources:
  - metadata:
      actionId: generateReport
    run:
      pdf:
        content: "<h1>Report</h1>"
        backend: wkhtmltopdf

  - metadata:
      actionId: sendReport
      requires: [generateReport]
    run:
      apiResponse:
        success: true
        response:
          pdfPath: "{{ get('generateReport').outputFile }}"
          sizeBytes: "{{ get('generateReport').sizeBytes }}"

PDF as an Inline Resource

PDF generation can run before or after the main resource action:

yaml
run:
  before:
    - pdf:
        content: "<h1>Pre-flight doc</h1>"
        backend: wkhtmltopdf

  chat:
    model: llama3
    prompt: "{{ input() }}"

  after:
    - pdf:
        content: "<h1>Summary</h1><p>{{ get('chat') }}</p>"
        backend: wkhtmltopdf
        outputFile: /tmp/summary.pdf

Using Expressions in content

The content field supports KDeps expressions:

yaml
run:
  pdf:
    content: |
      <h1>Report for {{ get("name") }}</h1>
      <p>Score: <strong>{{ get("score") }}</strong> / 100</p>
      <p>Generated: {{ info("timestamp") }}</p>
    contentType: html
    backend: wkhtmltopdf

Example: CV/JD Match Report

Full pipeline: scrape a job description, score the match, generate a PDF report.

yaml
# resources/scrapeJD.yaml
metadata:
  actionId: scrapeJD
run:
  scraper:
    url: "{{ get('jd_url') }}"

# resources/scoreMatch.yaml
metadata:
  actionId: scoreMatch
  requires: [scrapeJD]
run:
  chat:
    model: gpt-4o
    prompt: |
      CV: {{ get('cv_text') }}
      Job Description: {{ get('scrapeJD') }}
      Rate the match from 0-100 and explain the top 3 strengths and gaps. Output JSON.

# resources/generateReport.yaml
metadata:
  actionId: generateReport
  requires: [scoreMatch]
run:
  pdf:
    content: |
      <html>
      <head><style>
        body { font-family: Arial, sans-serif; max-width: 800px; margin: auto; padding: 2em; }
        h1 { color: #1a1a2e; }
        .score { font-size: 2em; font-weight: bold; color: #16213e; }
      </style></head>
      <body>
        <h1>Match Report</h1>
        <p class="score">Score: {{ get('scoreMatch').score }} / 100</p>
        <h2>Strengths</h2>
        <ul>{{ get('scoreMatch').strengths }}</ul>
        <h2>Gaps</h2>
        <ul>{{ get('scoreMatch').gaps }}</ul>
      </body>
      </html>
    contentType: html
    backend: wkhtmltopdf
    outputFile: /tmp/match-report.pdf

Example: Motivation Letter

Generate a personalized motivation letter as a PDF using an LLM:

yaml
# resources/writeLetter.yaml
metadata:
  actionId: writeLetter
run:
  chat:
    model: gpt-4o
    prompt: |
      Write a professional motivation letter for this candidate applying to this role.
      CV: {{ get('cv_text') }}
      Job: {{ get('jd_text') }}
      Format as clean HTML with <h1>, <p> tags only.

# resources/letterPDF.yaml
metadata:
  actionId: letterPDF
  requires: [writeLetter]
run:
  pdf:
    content: "{{ get('writeLetter') }}"
    contentType: html
    backend: weasyprint
    outputFile: /tmp/motivation-letter.pdf

Backend Comparison

Featurewkhtmltopdfpandocweasyprint
HTML inputYesYesYes
Markdown inputBasic (via skeleton)NativeBasic (via skeleton)
CSS supportGoodLimitedExcellent
LaTeX requiredNoYesNo
JavaScriptYesNoNo
Install sizeMediumLargeSmall (pip)
Best forHTML reports, invoicesAcademic/tech docsStyled reports

Validator Rules

The pdf resource is validated before execution:

  • content must not be empty.
  • contentType must be html or markdown (if set).
  • backend must be wkhtmltopdf, pandoc, or weasyprint (if set).
  • A resource may only declare one primary executor (pdf, chat, exec, etc.).

Next Steps

Released under the Apache 2.0 License.