PDFPipe

Field operations / A4

Incident report HTML template

A factual record of what happened, kept separate from any judgement about why, with corrective actions that have an owner and a date.

When this document is the right one

Something went wrong: an injury, a near miss, damage, an evacuation. The document is written within hours and read months later by someone deciding whether the organisation acted reasonably.

Why each part is there

The fields are visible in the markup. What is not visible is why they are present, which is the part that gets removed first when someone adapts a template for their own use.

  • The account written as a plain sequence with times, in its own block, separated from any statement about cause.
  • Contributing factors as a separate section, so an opinion about why is never mistaken for a statement of what happened.
  • Classification tick boxes including whether the incident is reportable, since that decision has a legal deadline attached to it.
  • Corrective actions with an owner and a date, because an incident report with recommendations and no owners is a document that changes nothing.
  • An explicit prompt to record the decision not to report externally, since an unanswered question looks worse afterwards than a documented judgement.

The template

A complete file. Doctype, stylesheet, body: paste it into a renderer unchanged and it produces a finished A4 page. Replace the sample data and the styling holds.

html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Incident report INC-2026-0058</title>
<style>
  @page { size: A4; margin: 15mm; }
  * { box-sizing: border-box; }
  body { margin: 0; font: 9.5pt/1.45 Arial, sans-serif; color: #111; }

  header { display: flex; justify-content: space-between; align-items: flex-start;
           border-bottom: 2px solid #111; padding-bottom: 5mm; }
  h1 { margin: 0; font-size: 17pt; }
  .ref { text-align: right; font-size: 9pt; }
  .ref .no { font-size: 12pt; font-weight: 700; }

  .facts { display: grid; grid-template-columns: repeat(4, 1fr); gap: 5mm; margin: 6mm 0;
           break-inside: avoid; }
  .facts div { border-bottom: 1.5px solid #111; padding-bottom: 1.5mm; }
  .facts .k { font-size: 7.5pt; text-transform: uppercase; letter-spacing: 0.06em;
              color: #666; }
  .facts .v { margin-top: 1mm; font-weight: 700; }

  h2 { font-size: 9pt; text-transform: uppercase; letter-spacing: 0.08em;
       border-bottom: 1px solid #111; padding-bottom: 1.5mm; margin: 7mm 0 3mm;
       break-after: avoid; }
  p { margin: 0 0 3mm; }

  /* The account is written in plain sequence with times, and separated from
     any judgement about cause. Mixing the two is how an incident report
     becomes an argument rather than a record. */
  .account { border-left: 3px solid #111; padding: 1mm 0 1mm 5mm; }

  .classify { display: flex; flex-wrap: wrap; gap: 3mm 8mm; margin: 3mm 0; }
  .classify label { display: flex; align-items: center; gap: 2mm; font-size: 9pt; }
  .box { display: inline-block; width: 4mm; height: 4mm; border: 1.5px solid #111; }

  table { width: 100%; border-collapse: collapse; margin-top: 3mm; }
  thead { display: table-header-group; }
  th { text-align: left; font-size: 7.5pt; text-transform: uppercase; letter-spacing: 0.05em;
       color: #666; border-bottom: 1.5px solid #111; padding-bottom: 2mm; }
  td { padding: 2.5mm 3mm 2.5mm 0; border-bottom: 1px solid #eee; vertical-align: top; }
  tr { break-inside: avoid; }

  .notify { background: #fdeceb; border-left: 4px solid #b3261e; padding: 4mm 5mm;
            margin-top: 6mm; font-size: 8.5pt; break-inside: avoid; }

  .sign { margin-top: 7mm; display: grid; grid-template-columns: repeat(3, 1fr); gap: 8mm;
          break-inside: avoid; }
  .sign div { border-top: 1px solid #111; padding-top: 1.5mm; margin-top: 13mm;
              font-size: 8pt; color: #666; }
</style>
</head>
<body>
  <header>
    <div>
      <h1>Incident report</h1>
      <div style="margin-top:1.5mm">Ravenshill Hotel Group &middot; Bath property</div>
    </div>
    <div class="ref">
      <div class="no">INC-2026-0058</div>
      Reported 14 May 2026, 17:40<br>
      By T. Whelan, contractor supervisor
    </div>
  </header>

  <section class="facts">
    <div><div class="k">Date and time</div><div class="v">14 May 2026, 16:20</div></div>
    <div><div class="k">Location</div><div class="v">Basement plant room</div></div>
    <div><div class="k">People involved</div><div class="v">2</div></div>
    <div><div class="k">Injuries</div><div class="v">None</div></div>
  </section>

  <h2>Classification</h2>
  <div class="classify">
    <label><span class="box"></span> Injury</label>
    <label><span class="box"></span> Near miss</label>
    <label><span class="box"></span> Property damage</label>
    <label><span class="box"></span> Environmental</label>
    <label><span class="box"></span> Security</label>
    <label><span class="box"></span> Reportable to the regulator</label>
  </div>

  <h2>What happened</h2>
  <div class="account">
    <p>
      At approximately 16:10 the brazing work covered by permit HW-2026-0442 was
      completed and the operatives began packing up. The fire watch required by the
      permit was not started, because both operatives understood the other to be doing it.
    </p>
    <p>
      At 16:20 a smoke detector in the corridor outside the plant room, which had not
      been isolated, activated and put the building into an evacuation alarm. Around 90
      guests and staff left the building. The fire and rescue service attended.
    </p>
    <p>
      No fire was found. The activation was caused by residual smoke from the brazing
      drifting through a cable penetration that had not been sealed, into the corridor.
      The building was reoccupied at 16:55.
    </p>
  </div>

  <h2>Immediate action taken</h2>
  <p>
    Work stopped. The permit was cancelled at 16:25. A one hour re-inspection was carried
    out at 17:30 and found nothing. The cable penetration was sealed the same evening.
  </p>

  <h2>Contributing factors</h2>
  <p>
    The permit required both a fire watch and the sealing of openings within ten metres.
    Neither was done, and the permit was signed as though both had been. The permit
    check is being treated as a single supervisor signature when it is intended as an
    inspection, which is a process failure rather than an individual one.
  </p>

  <h2>Corrective actions</h2>
  <table>
    <thead>
      <tr><th>Action</th><th>Owner</th><th>By</th></tr>
    </thead>
    <tbody>
      <tr><td>Permit precautions to be physically verified by the issuing person before
        signature, not accepted on report</td><td>Facilities manager</td><td>21 May</td></tr>
      <tr><td>Fire watch to be named on the permit at issue rather than assigned at the
        end of the work</td><td>Facilities manager</td><td>21 May</td></tr>
      <tr><td>Survey and seal all cable penetrations between the plant room and the
        corridor</td><td>Meridian Mechanical</td><td>05 Jun</td></tr>
      <tr><td>Toolbox talk on hot work permits for all mechanical contractors on site</td>
        <td>T. Whelan</td><td>28 May</td></tr>
    </tbody>
  </table>

  <p class="notify">
    <strong>External notification.</strong> Consider whether this incident is reportable
    under the applicable health and safety regulations, and record the decision and who
    made it. Deciding not to report is a decision that has to be documented; leaving the
    question unanswered is not.
  </p>

  <div class="sign">
    <div>Reported by</div>
    <div>Investigated by</div>
    <div>Closed by, and date</div>
  </div>
</body>
</html>

The layout decision worth understanding

The account is set in a left-bordered block and the contributing factors are not. That visual separation is the most important thing on the page: mixing narrative with blame is how an incident report becomes an argument, and an argument is not admissible evidence that the organisation responded properly.

The mistake people make adapting it

Naming individuals in the contributing factors. A report that identifies a person as the cause stops people reporting near misses, which removes the early warnings and leaves only the injuries. Describe the process failure, and handle the individual separately if there is one.

Rendering it

The page box is declared in the template's own CSS as A4, so the size travels with the markup rather than living in the code that calls the renderer. A4 is also one of the six named formats the API accepts, so it can be passed in the request options instead if that suits your setup better.

bash
curl -X POST https://api.pdfpipe.xyz/v1/pdf \
  -H "Authorization: Bearer $PDFPIPE_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "html": "<!doctype html>...",
    "options": { "format": "A4" }
  }' \
  --output incident-report.pdf

Frequently asked

Can I use this template commercially?

Yes. Copy it, change it, ship it. It is sample markup written to be taken, and the sample data in it is invented, so replace the names and the numbers before anyone sees it.

Why is the page size in the CSS rather than in the API call?

Because a incident report is a A4 document, and that is a property of the document rather than of the code that renders it. Declaring it in the page box means the size cannot be lost between the template and the call, which is the usual way a document ends up on the wrong paper.

Will it look the same in every renderer?

The layout will, because it uses ordinary CSS. The page break behaviour will not: break-inside and break-after are implemented differently by browser engines and by dedicated print engines, and some of the paged media specification is not implemented in browser renders at all. That difference is documented per property in the paged CSS reference.

Other templates

Documents from the same part of a business, and one from each of the other groups.

Paste the template into the playground and get the PDF back. No signup, no key.