Pointegrity
Journal

What we built while the journal was quiet

Published · Back to journal

It's been ten days since the last post. The gap was on purpose — we were on the floor of the workshop, not at the desk where the journal lives. This is a status report from that floor, and a small admission: there's a backlog of "we should write about that" topics from the last two weeks, and we're not going to backfill them. They'll surface in future posts when the moment is right. For now, what got done.

A visual identity for the family

Pointegrity ships several small apps, and until recently each one looked like its own thing — different greens, different type, different button shapes. That's normal early on. It also stops being normal at some point.

We built a "family voice" system on top of our motif design library: a single attribute on the page (data-family) that swaps in a coherent palette + typography + decoration set across an entire app. Three voices live there now:

pi Personal & quiet — paper-cream surfaces, Plex Serif titles, sage primary. Used by pouch.
cura Caring & warm — pi's silhouette in terracotta. Used by familiar and recital.
sc Editorial-academic — sage gradient header bands, italic Plex Serif kickers, amber rules. Used by trellis.

Adding a fourth app to one of these voices is now one line in its boot config: webCfg.Family = "pi". The whole app — auth pages, marketing pages, the SPA shell — picks up the voice. The reason this matters is mostly about not making four separate visual-design decisions every time a small app gets written. The reason it took so long is that getting the palette + decoration + structural decisions right for two voices, then forking gracefully into a third, was more work than it looked.

Schema housekeeping that nobody saw

The auth library — shared across pouch, familiar, recital, and our K-12 sister site trellis — was naming its session table just sessions. Several of our apps have their own domain concept of "sessions" (familiar's flashcard practice, recital's recitation, future apps surely too), and SQLite's CREATE TABLE IF NOT EXISTS turns a name collision into a runtime mystery later.

We renamed the auth-library tables to auth_sessions and auth_sessions_kv. Hard rename, no shims, no real users yet. It's the kind of work that is invisible if it goes well and crippling if it goes badly; we wrote the tests to make sure it goes well, then ran the migration on the prod database in a single ALTER TABLE. The whole thing was anticlimactic, which is the goal.

Tests where there weren't any

The auth library's HTTP layer (the actual login/register pages) and its SMTP message construction were both uncovered by tests. Several recent bug-shaped scares hadn't been caught by the existing service-level tests because those tests use mocks that don't validate the output URL or the email body.

The new tests cover: full register-and-verify flow against the real handler stack, password-mismatch + missing-CSRF branches, anti-enumeration on forgot-password, the SMTP message bytes (headers, MIME version, line endings, body content), and a guard that the family-voice attribute actually lands in rendered HTML. Every previously-passing test still passes; auth/web and auth/email moved from "no test files" to green.

The marketing question

We've also been thinking — quietly, mostly to each other — about distribution. The honest summary: we don't have a marketing problem yet, we have a "do we have product-market fit on any of these apps" question. Trellis has a few users. Pouch has near-zero. Familiar and recital are usable. The right move isn't to push harder on marketing, it's to keep building, keep the journal going, and trust that the people we'd actually want to reach will find the work eventually.

That said, we do need somewhere for the early arrivals to leave their email if they want a heads-up when something meaningful ships. So we built a tiny self-hosted subscribe service called letterbox — a Go binary, a SQLite file, a single form, no third-party trackers. The form is at the bottom of the journal index now. Plain HTML, no JavaScript, no cookies. The list dump is a CSV. When it's time to send a letter, we'll send a letter — by hand, the first few times.

What's next

The next app on the floor is mytraces — a personal trip-planning tool, in the "tools for your data" cluster with pouch. We're building it because we want to use it ourselves, which is the strongest signal a tool can give you. The journal will document the build as it happens.

In parallel: the journal cadence we're aiming for is roughly biweekly — short when there's not much to say, long when there is. The first monthly letter will go out at the end of May, summarizing what shipped and pointing at the month's posts. Subscribe below if that sounds useful.

← All journal posts