Skip to content

The NextPDF design philosophy

Spec: ISO/IEC 25010 Spec: ISO 32000-2 Evidence: Design principle

This page states the principles every NextPDF API decision is held against. They are deliberately few, because a principle you cannot recite is one you cannot apply under pressure.

It is the page to read first. The other Insider_ pages show these principles at work in specific places. This one names them so the rest make sense.

PDF is old enough to have opinions, and strict enough to punish guesses. A signature covers exactly the bytes it covers. A font is either embedded or it is not. An archival profile either holds or fails an audit months later, in front of someone who needs evidence.

A library has a choice when the inputs are ambiguous. It can guess and stay quiet, or it can stop and say so. The first feels friendlier in a demo. It can also cost you a production incident with no trace of what went wrong. NextPDF chooses the second. It accepts a less reassuring first impression in exchange for a defensible one. Software quality standards name this trade directly. Fail-safe behaviour is the capability of a product to revert to a safe state on failure rather than continue in an undefined one ( Spec: ISO/IEC 25010, §3 ).

NextPDF is built on five principles, in priority order:

  1. Explicit beats implicit. If intent matters, you state it. The engine does not infer a signature level, an output mode, or a conformance target from context.
  2. Fail fast, fail loud, fail early. An invalid input is rejected before a byte is written, with a message that names the cause.
  3. Errors are an API surface. Failures are specific, typed, and carry structured context — designed, not incidental.
  4. Boundaries are stated, not discovered. Every claim says where it stops. “Necessary, not sufficient” is a phrase NextPDF states on purpose.
  5. Nothing silently degrades. The engine does not return a half-correct artifact that looks finished.

Everything else — the fluent builder, the disposable document, strict typing — is downstream of these.

The principles are not slogans. They show up as concrete shapes in the source, and they reinforce one another.

The table below maps each principle to where you can see it in the engine and what it costs if it is absent.

PrincipleHow it shows up in NextPDFThe cost of the opposite
Explicit beats implicitsetSignature(certInfo:, level:) takes the PAdES level as a required, named argument — there is no “auto” levelA document signed at a profile the obligation did not require, discovered at validation time
Fail fast, fail loudsave() rejects a stream-wrapper or null-byte path before rendering; setSignature() followed by save() throws rather than emit an unsigned fileA path-traversal write, or an “unsigned but believed signed” PDF in an archive
Errors are an API surfaceOne abstract base exception, specific typed subclasses, each exposing structured getContext() for logs and APMA generic stack trace and a long afternoon of guessing
Boundaries are statedIn-process conformance checks return findings and say in words that the verdict belongs to an independent validatorA “no exception, so it must be conformant” conclusion that an auditor disproves
Nothing silently degradesThe archival-timestamp path refuses to return a half-written profile rather than emit one missing its required dictionaryA long-term-validation profile that quietly is not one

Read the principles together and a single stance emerges: the engine would rather give you an honest “no” than a confident “maybe”. That is not pessimism. It recognizes that a PDF is often a legal artifact. A legal artifact that is wrong is worse than one that was never produced.

This page is a Evidence: Design principle statement: the principles are deliberate decisions, argued rather than measured. Where a principle has a name in an external discipline, the page anchors to it so the reasoning is not merely an in-house opinion.

  • The “refuse rather than continue in an undefined state” stance is the fail-safe quality property in Spec: ISO/IEC 25010 §3 — a product that places itself in a safe condition on failure. Fault tolerance, in the same family, is the degree to which a system keeps behaving as intended despite faults. NextPDF directs that effort toward detecting and stopping, not toward concealing the fault.
  • The “state the boundary before adoption” stance is appropriateness recognizability ( Spec: ISO/IEC 25010, §3.26 ): the ability to judge fit from documentation and first impressions.
  • The PDF-specific reason any of this matters is Spec: ISO 32000-2, §12.8 : a signature’s byte range protects exactly the bytes it covers and nothing more, so an engine that “helpfully” rewrites or guesses around a signed document has not helped at all.

The individual principles are demonstrated against real engine source on their own pages — An API that refuses to guess and Errors as a feature carry the Evidence: Code-backed proof. This page is the why; those pages are the what.

The principles are visible in a few lines of ordinary use. The signature call states intent explicitly. The engine refuses early rather than emit something misleading.

<?php
declare(strict_types=1);
use NextPDF\Core\Document;
use NextPDF\Exception\NotImplementedException;
use NextPDF\Security\Signature\CertificateInfo;
use NextPDF\Security\Signature\SignatureLevel;
$document = Document::createStandalone();
$document->setTitle('Service Agreement 2026-0042');
$document->addPage();
$document->setFont('helvetica', '', 12);
$document->cell(0, 10, 'This agreement is configured for a PAdES signature.', newLine: true);
// Explicit beats implicit: the PAdES level is a required, named argument.
// There is no inferred or "auto" level.
$document->setSignature(
certInfo: new CertificateInfo(
certificate: $certificatePem,
privateKey: $privateKeyPem,
),
level: SignatureLevel::PAdES_B_B,
);
try {
// Fail fast, no silent degradation: rather than emit an UNSIGNED file
// that the caller believes setSignature() signed, the high-level path
// refuses and names the supported route.
$document->save('/srv/output/agreement.pdf');
} catch (NotImplementedException $e) {
// The message identifies the feature and the follow-up, not a stack
// trace: "... is not implemented in this release. <actionable follow-up>"
error_log($e->getMessage());
}

The point is not the signature mechanics. Three principles are observable in one snippet: intent is stated (level:), the failure is early and named, and the engine declines to produce a document that would lie about its own state.

The most common misreading is that these principles make NextPDF “harder to use”. They make it harder to use wrongly. A required argument is one fewer silent default to be surprised by. An early exception is one fewer corrupt artifact in an archive. The friction is deliberately placed where a mistake is cheap — at the call site, in development — instead of where it is expensive: in production, in an audit, in court.

A second misreading is that “opinionated” means “inflexible”. It does not. The engine has opinions about correctness and intent, not about your document. You still control layout, content, fonts, and structure completely. The opinions are about not guessing on your behalf where a guess would be unsafe.

This page states design intent. It is not itself a behavioural specification. The principles describe how decisions are made, not a guarantee about any one method. Each method’s exact contract lives in the reference and in its own Insider_ page with that page’s evidence level.

The principles are also not absolute laws of physics. They are priorities, applied with judgement. Where two principles conflict (a stricter refusal versus a more forgiving default), the priority order above is the tie-breaker. A specific module may still document a reasoned exception. When it does, that exception is written down, not assumed.

Finally, “design principle” is the evidence basis here by design. This page argues. It does not benchmark. Claims that need a number, a test, or a clause to be supported are made on the pages that own that evidence, not here.

  • Design principle (evidence level) — a page whose claims are deliberate design decisions, argued from intent and corroborating standards rather than measured by a benchmark or a single test.
  • Fail-safe — a software-quality property: on failure, the product reverts to a safe state instead of continuing in an undefined one. The reason NextPDF refuses rather than guesses.
  • Fail fast — rejecting an invalid input at the earliest possible point, with a clear cause, instead of proceeding and failing obscurely later.
  • PAdES — PDF Advanced Electronic Signatures, the ETSI profile family for signing PDF documents (B-B, B-T, B-LT, B-LTA). Expanded here on first use; covered in depth on the signing pages.
  • Necessary, not sufficient — a deliberate phrasing used when an in-process check is a real signal but not a conformance verdict; the authoritative decision belongs to an independent validator.