Skip to content
14 notesRSS

notes

Collections like this usually catalogue details spotted in other people's products. These are from mine. Things that cost something to learn, mostly by getting them wrong first, while shipping four SaaS products in a year.

Three sentences each. If it needs more than that, it is a build write-up, not a note.

14 of 14

  1. 14

    A score with no reason is a number you have to trust

    Embers ranks leads across five dimensions, and the first version just showed the rank. Nobody used it. Every row now carries the reason it scored what it did (engaged twice in six days, title and company size match), and the same number suddenly became actionable.

    from Embers2026-08
  2. 13

    Fifteen green ticks is homework, not an answer

    OutboundQA runs fifteen infrastructure checks. Showing fifteen results made the user do the synthesis themselves. Collapsing it to one verdict (Ready, Needs Fix, Do Not Launch) with the checks underneath is the same data doing the work instead of delegating it.

    from OutboundQA2026-06
  3. 12

    A tool that says your DNS is wrong should show you the record

    An audit that asserts without evidence is asking for trust it has not earned, and the first thing a sceptical user does is go check by hand. Printing the actual public record next to each verdict removed that step, and removed most of the support questions with it.

    from OutboundQA2026-06
  4. 11

    The onboarding wall is why the second device never gets used

    SnapCount is a shared counter, so it is worthless if only one person is counting. Requiring an account to join meant the person handed the second device just did not. Guest links with no signup was the single change that made it a multiplayer product rather than a single-player one with a sync feature.

    from SnapCount2026-06
  5. 10

    SSE, not sockets, when the traffic only goes one way

    Counts in SnapCount propagate server-to-client and almost never the other way. Server-sent events carry that shape natively and reconnect for free, where a socket layer would have meant writing and testing a reconnect path for a message flow that does not need one.

    from SnapCount2026-05
  6. 09

    Retried webhooks are not a rare case

    Payment providers retry on any non-2xx, including the ones caused by your own deploy. A handler that provisions on every delivery will double-provision eventually, not as an edge case but on a normal Tuesday. Idempotency keys on the handler cost an afternoon; finding out the other way costs a refund and the trust.

    from Embers2026-05
  7. 08

    Retrofitting tenancy onto a live compliance product is not a weekend

    Hood Cleaning Report had workspaces, roles and soft deletes in the schema before the first customer, which felt like over-building at the time. It was the cheapest decision in the project. Tenancy touches every query, and adding it later means touching every query while people are relying on the answers.

  8. 07

    Encrypt third-party tokens even when the database is private

    CompanyCam OAuth tokens grant access to someone else's account, so a database dump is not just your problem. Fernet encryption at rest means a leaked backup is inert, and the cost is one wrapper on read and write.

    from Hood Cleaning Report2026-04
  9. 06

    The audit log matters more than the share link

    Compliance reports go out as signed, expiring URLs, which is the obvious half. The half that actually gets asked about is who opened it and when. That is an inspector's question, months later, and the sharing mechanism alone cannot answer it.

    from Hood Cleaning Report2026-03
  10. 05

    Render PDFs as HTML, not coordinates

    Report layouts change constantly and every change in a coordinate-pushing PDF library is arithmetic. Composing typed blocks and rendering through Playwright means the layout is CSS: reviewable in a browser, and the same code path as the on-screen preview.

    from Hood Cleaning Report2026-03
  11. 04

    Prompts that run per row are a unit-cost decision

    Embers classifies every engager on every post, so prompt length is not a style question; it is multiplied by the entire dataset, forever. Designing the prompt against cost per row from the start is much easier than discovering the bill later and having to re-tune it against a live scoring model.

    from Embers2026-02
  12. 03

    Read the accessibility settings on mount, not in a settings screen

    The SnapCount iOS app reads Reduce Motion and Reduce Transparency when it launches and changes what actually renders. Treating them as a preference the user sets inside your app misses the point: they already told the system, and asking again is asking them to do it twice.

    from SnapCount2026-02
  13. 02

    Tabular figures, or the layout twitches

    Any number that updates live (a counter, a timer, a total) will shift its own width as glyphs change unless the figures are tabular. It reads as instability rather than as a typographic detail, and it is one CSS declaration.

    from SnapCount2026-01
  14. 01

    Quarterly tools do not retain

    OutboundQA worked. The checks were sound and the verdict model held up. But auditing sending domains is something a team does once a quarter, and a product people genuinely need four times a year is a hard business regardless of how good it is. Worth knowing before building the next one.

    from OutboundQA2026-06