# /sign-pdf

> Add Faris's handwritten-style signature + date (+ city) to one or more PDF documents at the correct field locations.


# /sign-pdf

Adds Faris's handwritten signature, date, and (optional) city to one or more PDFs at the **correct field locations**. Output goes to a sibling `_signed/` folder with `_signed.pdf` suffix on each filename.

## Trigger

- "sign these PDFs"
- "add my signature to <file>"
- "potpiši ove dokumente"
- User pastes/attaches German tax forms, declarations, contracts, etc.

## Defaults

| Field | Default |
|-------|---------|
| Name | `Faris Biogradlic` |
| Date | today's date (DD.MM.YYYY) |
| Place | `Hamburg` |
| Font | `PatrickHand-Regular.ttf` (clean handwriting, reliable letter spacing) |
| Ink color | dark blue `[0.05, 0.10, 0.55]` |
| Signature size | 24pt |
| Date/place size | 11pt Helvetica |

If the user wants Caveat (more cursive/loopy) say so explicitly: `--font Caveat-Regular.ttf`. **Do not use the variable-axis Caveat.ttf — its glyph metrics break and you get visible gaps inside words like "Biogradlic" → "Bio gr adl ic".**

## Workflow

### 1. Identify which documents need signing

Before signing, **classify each PDF**:

- **Sign**: tax returns, declarations, contracts, offers/Angebote, balance sheets requiring Unterschrift der Geschäftsführung, lease agreements, Vollmachten, etc.
- **DO NOT sign — flag to user**:
  - Invoices *received from* a third party (e.g. tax advisor's invoice to you)
  - Electronic-submission pACME Agencyws (`E-Bilanz-Vorschau`, ELSTER-Vorschau) — those go through ERiC authenticated by the advisor's software
  - Bank statements, receipts, info letters

If the user said "all of them" but some clearly don't need signing, **tell them which two and why** before processing — let them confirm. Don't silently sign everything.

### 2. Discover signature label positions

For every PDF that will be signed, run:

```bash
node .claude/skills/sign-pdf/scripts/find_sig_positions.mjs "<absolute-path-to.pdf>"
```

This outputs JSON listing every match for keywords like `Unterschrift`, `Datum`, `Ort, Datum`, `Datum, eigenhändige Unterschrift`, `Best regards` — with `{page, text, x, y}` coordinates. Coordinates use pdf-lib's bottom-left origin.

### 3. Decide placement (the rule)

German tax forms put the **label BELOW the entry field**. So if you find a label at `y=440`, you write the signature at roughly `y=420` (~20pt above the label, inside the cell).

Common patterns:

| Layout | Where to write |
|--------|---------------|
| `Unterschrift` heading + `Ort \| Datum` row + entry row + `Unterschrift` row + entry row + disclaimer | Place inside each entry row (~20pt above each label) |
| Single horizontal line above `Datum, Unterschrift` label | Date on left, name on right, both ~5-10pt above the label baseline |
| Letter sign-off (`Best regards / [Company]`) with no signature line | Place handwritten name BELOW the closing block, optionally with "City, Date" line above |
| Combined `Datum, eigenhändige Unterschrift` field | Date (Helvetica) + name (handwriting) on same line, ~30pt above the label |

For each placement object you output:

```jsonc
{
  "page": 6,
  "name_xy":  [274, 252],   // signature (handwriting font)
  "date_xy":  [82, 256],    // standalone date (Helvetica)
  // OR for single-cell place+date fields:
  "<id>": [85, 100],
  // OR for separate cells:
  "place_xy": [95, 420]
}
```

### 4. Build a config and run the signer

Write a config to `.tmp/sign-job-<timestamp>.json`:

```json
{
  "name":  "Faris Biogradlic",
  "date":  "29.04.2026",
  "place": "Hamburg",
  "font":  "PatrickHand-Regular.ttf",
  "outDir": "C:/Users/faris/Downloads/_signed",
  "files": [
    {
      "in": "C:/Users/faris/Downloads/Foo.pdf",
      "placements": [
        { "page": 6, "<id>": [72, 258], "name_xy": [274, 252] }
      ]
    }
  ]
}
```

Then run:

```bash
node .claude/skills/sign-pdf/scripts/sign_pdf.mjs .tmp/sign-job-<ts>.json
```

Outputs each file as `<original>_signed.pdf` in `outDir`.

### 5. Report back

- List the signed file paths.
- Flag any PDFs you skipped (with the reason).
- Tell the user to **open one and verify placement** before sending — coordinates are derived but font baselines can sit slightly differently than expected. Offer to nudge if anything's off (specify direction: up/down/left/right by N points).

## Dependencies

Already installed in repo node_modules: `pdf-lib`, `@pdf-lib/fontkit`, `pdfjs-dist`. If missing:

```bash
npm install --no-save pdf-lib @pdf-lib/fontkit pdfjs-dist
```

Bundled fonts in `.claude/skills/sign-pdf/fonts/`:
- `PatrickHand-Regular.ttf` (default — print-style handwriting, reliable metrics)
- `Caveat-Regular.ttf` (cursive — use only if user requests)

## Common gotchas

- **Variable fonts break letter spacing.** Use the static `*-Regular.ttf` files only.
- **Subsetting can drop kerning.** The signer passes `{ subset: false }` when embedding. Don't change that.
- **First-pass coordinates may need a small nudge.** Always tell the user to spot-check before sending. Save the working config to `.tmp/` so re-runs are cheap.
- **Don't add a signature to invoices you received** or electronic-submission pACME Agencyws — flag them and skip.
- **Date format:** German tax forms expect `DD.MM.YYYY`. Default to that unless told otherwise.

## Reference: the original 8-document run

Live config used for the 2024 Iqramal Solution UG Jahresabschluss + Steuererklärungen package: see `examples/<id>.json`. Reuse those placements as a template for next year's filing.
