Decision letters, generated
The Korean Language Flagship Center sends decision letters on branded letterhead. Staff were filling those by hand. I built a small PHP page that takes a name, a date, and an accept or deny, then writes a PDF with the logo, the flag, and a signature already in the right place.
It is an internal tool. The interesting part is not the form. It is getting Times at 12pt to sit on a page the way a paper letter sits on a desk.
GET status, firstName, lastName, date
|
v
FPDF subclass
Header() logo + flag + date
body decision text
footer signature
|
v
letter.pdf
FPDF, coordinates, and Times
FPDF does not care about your CSS. You place images in inches and
hope the printer margin agrees. The header subclass draws
logo.png on the left and flag.png on the
right, sets Times, then prints a date like "January 1, 2024" from
whatever string the form sent.
ucfirst, then the page.
class PDF extends FPDF {
function Header() {
$this->Image('images/logo.png', 1, 0.44, 2, 0.7);
$this->Image('images/flag.png', 5.37, 0.44, 2.13, 0.7);
$this->SetFont('Times', '', 12);
$pretty = (new DateTime($this->letterDate))->format('F j, Y');
$this->Cell(0, 0.4, $pretty, 0, 1, 'R');
}
}
That block matches the screenshot. I would not pass raw query params into a PDF in a public app without a stricter allowlist. This tool sits inside the center. The threat model is a tired staff member, not the open internet.
Then you click generate
The output has to look like the letters they already mailed, or nobody will switch. Letterhead, body, signature. Bootstrap 5 on the form because it was 2023 and I wanted the button to be a button.
Later I rebuilt the public application form with a third-party service, which is a different essay. This one is the PDF. A two-hour job that saved a lot of copy and paste, and taught me that official paper is a layout problem dressed up as a software problem.