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