Skip to main content
Wintertrace

Blog · Release notes

How a documents module turned into building my own signing engine

The Documents module for Wintertrace has shipped — and getting online signing right meant building a separate signing engine, NoSign, from scratch. The story of how a simple module spiralled, and what an operator actually gets out of it.

By Michael 10 min read

A few weeks ago I wrote about a module I was building to bring contracts into Wintertrace, and I ended that piece with a promise: when it was ready for real use, I’d write about it again — with the parts that survived testing, and the parts that changed.

It’s ready. So here’s the follow-up. And there’s a real “part that changed”, because one piece of it went quite differently from the plan.

The module is called Documents. I know — naming has never been my strong suit, and I won’t pretend that one came out of a workshop. But the module behind the dull name turned into one of the larger things I’ve built for Wintertrace, and most of that is down to a single feature that refused to be simple.

What it’s actually for

The point of the module is to take paperwork off the operator’s plate and, at the same time, make a small winter service look a bit more organised from the customer’s side.

I think about my colleague Julian here, the one this whole project started as a favour for. How does he handle a customer’s paperwork today? On a handshake? Over WhatsApp? A contract typed up on the computer, then a meeting or a trip to the post office? It can end up in a mailbox, a chat, somewhere in the office — and then, ideally, scanned back in. Several routes, several places. Awkward.

So the module does the obvious, useful thing first:

  • You upload documents of various kinds — existing contracts, proofs, invoices — and assign each one to a customer, and if you want, to a specific property or job. It’s all done in the admin dashboard, and the customer sees their own documents in the customer portal.
  • You can also request a document from a customer — a proof of insurance, say, or whatever you happen to need. The customer is notified, uploads it in their portal, and you have it. No email thread to chase.

That half is genuinely simple, and it was simple to build. It’s the other half that got out of hand.

The feature that spiralled

I also wanted operators to be able to draft a contract directly inside Wintertrace and have the customer sign it online.

Drafting was no problem. You write a contract from a template — there’ll be more of those later — or as your own free text, with placeholders filled in automatically for the customer, the property, the company, the date. It renders to a PDF. Fine.

Signing online was not fine.

I didn’t want to reinvent the wheel, so I started where anyone sensible would: with existing open-source signing tools. I tried several. And one after another, they fell down on the same things. Either the project was only partly open source and the genuinely useful parts sat behind a paywall, or the features I needed simply weren’t there.

What I needed was specific, and it came from what I want to offer rather than from what’s easiest to ship:

  • A free way to do this — which, since I’m the one offering it, means the software runs on my infrastructure, not on a bill the operator has to pick up.
  • An API, so the module could talk to it instead of sending people off to a separate website.
  • No hoarding of contracts. Hand the document over, sign it, send it back, delete it. Done.
  • The freedom to send a contract the operator wrote themselves — not forcing everyone who wants the feature onto a fixed set of templates.

After enough evenings of trying other people’s tools and coming up short, I stopped looking and built my own.

NoSign

That’s the part that changed. In the earlier post I floated the idea of plugging in something like Documenso or DocuSeal later. Instead I built a signing engine from scratch, and it became its own piece of software — the way Schneespur and Wintertrace are their own thing.

It’s called NoSign. Like the rest, it’ll be released as open source in its own right one day, at nosign.dev. The hosted version that the module talks to runs at nosign.app.

NoSign is API-first, and I mean that fairly strictly: there’s no sign-up, no login, no user management inside it. It takes a document and a list of signers over an API, runs the signing process, and hands back a sealed PDF. That was a deliberate choice — the fewer accounts and dashboards a thing like this has, the less there is to get wrong. (A frontend for it is, inevitably, already creeping onto the plan. These things never stay small.)

It was built the same way as everything else here: with Claude Code, across weeks of work, and a quantity of tokens I’d rather not total up. If you’ve ever wondered what that kind of build actually costs, riptokens.com paints a fairly honest picture.

When NoSign was finished, it still wasn’t usable on its own — because the module is deliberately not allowed to talk to it directly.

The piece in the middle

Between the module and NoSign sits my own API. The module never calls NoSign itself; it always goes through that API.

The API does two jobs the module shouldn’t have to. It handles the one-time registration with NoSign, and it enforces how many contracts an installation is allowed to send for signing each month. It’s also where the same principle from the last post lives: the API keeps nothing of substance. It routes the document and, at the end, assembles the audit record and triggers deletion. A pipe, not a filing cabinet.

So building “online signing” was really building three things at once: NoSign itself, the API in the middle, and the module that ties it into Wintertrace. Each one roughly the size of the others. That’s the honest reason a documents module took as long as it did.

What an operator actually experiences

For all that machinery underneath, the path through it is straightforward:

  1. You install the module. If you want online signing, you register for it — through the module itself.
  2. As part of that, you sign NoSign’s own terms on nosign.app: the terms of use, a privacy notice, a data processing agreement. Doing it yourself once is also the point — you see the whole signing flow from the customer’s side before you ever send one out.
  3. You draft a contract and define who signs, and where on the document each signature goes.
  4. You hand it to NoSign. It creates the signing request and sends a signing link back, through the API, to your installation.
  5. Your installation tells the customer there’s something to sign.
  6. The customer verifies their email address with NoSign, then signs on screen — no account, no printout.
  7. The sealed contract comes back, with an audit.pdf, into your installation and the customer portal. NoSign deletes its copy.

After that, the signed contract sits where the work it relates to already sits — next to that customer’s operations and service proofs, visible to everyone who’s party to it.

The audit record, and the seal

Two things travel back with the signed document, and both matter if anyone ever disputes it later.

The audit.pdf records the parts that are easy to argue about: when email verification was requested, when the signer confirmed their address, when they signed, who signed (their email, and a hashed version of their IP address), and when the signed document came back. It’s a timeline of the process, attached to the document the process produced.

The signed PDF itself is sealed following PAdES — the standard for signed PDFs — and carries a trusted timestamp. In plain terms: if the file is altered afterwards, that’s detectable. The seal is about the integrity of the document, the audit record is about the integrity of the process, and together they make “I never agreed to that” considerably harder to sustain.

I’ll borrow the honesty I try to apply to everything else here: that’s what the record is, and it’s useful. What it is not is a legal verdict. It’s documentation — a record that’s hard to wave away, not a guarantee about how any particular signature will be treated in any particular place.

A simple signature, not a qualified one

Worth being precise about, because the words mean specific things: NoSign produces a simple electronic signature. Not a qualified one. A qualified electronic signature involves verifying the signer’s identity in a much heavier way — video identification, or a check against an ID document — and that’s a different undertaking entirely.

For the everyday service agreements a winter service deals in, a simple electronic signature is usually enough. But “usually” is doing real work in that sentence, and electronic-signing rules differ from country to country. If a contract carries genuine weight for your business, that’s a conversation for someone qualified in your jurisdiction — not for a blog post.

What it means for Julian

Here’s the whole point, stripped of the plumbing.

Julian can now set up a contract online, send it, and tell his customer: “just sign it online.” No printer, no trip to the post office, no “yeah, sounds good” in a chat that nobody can point to three months later. The work and the agreement behind it end up in the same place, under the same customer.

Less work for him — and, I think, a tidier impression on the other side. Better than a handshake or a WhatsApp message, anyway.

Where it stands

A few honest boundaries, as usual:

  • It’s free, with no subscription — consistent with the rest of Wintertrace without a subscription.
  • There’s a rate limit to start — around 20 contracts per month. It can be raised; I want to watch how the service behaves under real use first. Starting cautious is easier than walking something back.
  • The document side works on its own. Storing, assigning and requesting documents needs none of the signing setup — you only register for NoSign if you actually want online signatures.
  • NoSign will be open-sourced in its own right at nosign.dev, the same way the rest of this is built in the open.

If you want to look closer, the Documents module has its own page, you can follow what’s planned on the roadmap, and the feedback form still goes straight to me. If you run winter service yourself, that’s the fastest way to tell me what this module is missing.

Note: Wintertrace provides documentation support. It is not a substitute for legal advice. Specific compliance assessments — including questions about electronic signatures and how they’re treated — should be made in consultation with qualified counsel in your jurisdiction.

Wintertrace is early and shaped by real winter service work. Share your feedback →