Blog

Screens that arrive already wired

2026-07-29

An isometric illustration of an upright arcade cabinet with a screen and a sloped control panel

You have a backend with auth and payments. Now you need six screens that nobody enjoys building: sign in, enter a code, handle the callback, hit a paywall, see the plans, manage a subscription.

None of them is interesting. All of them are fiddly, because each one is mostly error states — an expired link, a code entered wrong three times, a payment that succeeded on the rail but has not resolved into an entitlement yet.

pithy add ui react scaffolds them.

What arrives depends on what you composed

This is the part that makes it more than a template menu:

pithy/sign-in.tsx        auth      magic link
pithy/otp.tsx            auth      code entry
pithy/callback.tsx       auth      the return leg
pithy/paywall.tsx        payments  gated content
pithy/pricing.tsx        payments  plans, priced live
pithy/subscription.tsx   payments  manage, cancel
index.tsx                          yours

Compose auth and you get the first three. Compose payments and you get the next three. Compose neither and you get a router and one screen of your own.

You are not picking screens from a list and then wiring them. The composition already happened on the server, and the front end reads it — through the virtual modules, so what a screen knows about your backend is a projection of your Worker’s actual config rather than a second copy of it.

import { auth } from "virtual:pithy/auth";
import { payments } from "virtual:pithy/payments";

export const pithy = { auth, payments };

Narrowed to exactly what this Worker composes, resolved in memory, never written to disk.

They are source, in your repository

The screens land in your project as React files you own. Not a component library you configure through props. Not a hosted widget in an iframe.

That distinction decides whether this is useful at month six. A component library gives you what its author anticipated, and the first thing your designer asks for is the thing outside that. Scaffolded source has no such ceiling — the file is yours, and changing it is editing a file.

The cost is the honest one: you own them, so upgrades do not reach them. A better sign-in screen in a later release is something you copy across, not something you receive. That is the correct trade for UI, and the wrong trade for the handler logic behind it — which is why that stays in the package and only the thin registration lands in your repo.

What they get right that a blank file does not

The value is not the happy path. It is everything else.

Magic link and OTP need a pending state that survives a page reload, a resend with a cooldown, and a clear story for a link opened in a different browser from the one that requested it.

A callback screen is almost entirely failure handling — an expired token, a token already used, an arrival with no pending sign-in at all.

A pricing screen has to render figures resolved live for wherever the visitor is billed, which means it must render before it has them, and it must not print a wrong number while it waits.

A subscription screen has to be honest about a cancellation that is scheduled rather than immediate, and about a purchase made on a different platform’s rail.

Every one of those is a paragraph of judgment you would otherwise write yourself, badly, at the end of the project.

What it is not

It is not a design system. The screens are deliberately plain, so restyling them is expected work rather than a fight with somebody else’s opinions.

It is not a framework choice you are locked into. It is React because that is what shipped first. The projections underneath are plain modules with no framework in them, so another renderer reads the same thing.

And it is not the whole application. index.tsx is yours, and it is the point. The kit gives you the screens that are the same in every product so that you spend your time on the one that is not.