Skip to content

Let accounts go by a name (FW-602) - #45

Merged
ashutosh091 merged 3 commits into
erphq:previewfrom
dikshantgoyal011:site/profile-name
Nov 14, 2026
Merged

ashutosh091 merged 3 commits into
erphq:previewfrom
dikshantgoyal011:site/profile-name

Conversation

@dikshantgoyal011

@dikshantgoyal011 dikshantgoyal011 commented Nov 13, 2026 •

Copy link
Copy Markdown

What this does

FW-602: a profile name. Accounts kept only an email address. Now an account can go by a name, and the header shows it.

This PR builds on #44 (FW-601, the header sign-in), which should merge first. Until then, this PR's diff also shows that PR's commit, 780c547. This PR's own commits are 90b0e98 and a0b37ad.

Service (api/)

  • Migration 0003_profile_name.sql adds users.name. The user the service describes carries name, which is null until it's given.
  • POST /auth/verify takes an optional name. It names a new account, or one with no name yet, and never replaces an existing name.
  • New POST /auth/profile { name } sets the signed-in account's name; an empty name clears it.
  • What a name can be:
    • It's trimmed, and runs of spaces become one.
    • Up to 80 characters, counted as characters, not bytes.
    • Control characters and bidirectional overrides (which could make a name display as something else) are refused. They're refused before the code is checked, so a bad name doesn't use up one of the code's tries.
    • Zero-width joiners are kept, because some scripts and emoji need them.
  • Admin listing: includes each account's name.
  • README: documents all of the above.

Site

  • /signup: an optional Your name field above the address.
  • /account: a Name field to change or clear the name.
  • Header: shows the name, with the initials of its first and last words ("AL" for Ada Lovelace). The menu shows the name above the address. Without a name, both show the address, as before.
  • Console footer and admin page: show the name too.
  • Demo mode: the in-browser demo keeps the name with its session.

Also fixed (a0b37ad): the outlined buttons (Sign out on /account, Resend code and Use another address while signing in) turned near-black on hover, which left their dark text unreadable. pillOutline never overrode shadcn's default hover:bg-primary/80. Now only the border darkens on hover, as intended.

When it merges, in this order

  1. npm --prefix api run migrate:remote, to add the column to the live database.
  2. npm --prefix api run deploy.

The Worker's new code reads users.name, so deploying it before the migration would break sign-in. The site copes with the Worker not being updated yet: it shows the address, and saving a name on /account says "Not found." until the deploy.

Testing

  • npm --prefix api run check: 72 tests pass, 15 of them new, in api/test/profile.test.mjs. They cover:
    • giving a name at sign-up
    • tidying it
    • never replacing it
    • changing and clearing it
    • every refused kind of name, without using up the code's try
    • 80 multi-byte characters fitting
    • joiners being kept
    • needing a session
    • only changing your own account
    • other sites being refused
    • the admin listing
  • Mutation check: with the never-replace rule or the character check undone, the tests fail.
  • npm --prefix site run check passes at both commits, and docs/ matches a rebuild.
  • The production build in Edge, against a local service: 29 checks.
    • The sign-up field, and the header after sign-up ("AL", the name, the button's accessible name, the menu).
    • /account with no name: saving one, keeping it after a reload, a refused name, clearing it, and a double-click saving only once.
    • The console footer, the hover fix, and the admin page.
    • The demo, with no service.
    • No console errors.
  • The FW-601 header suite (62 checks) passes on this branch too.

Merging with the other two PRs

#44 (FW-601), this PR and #43 (FW-603, open sign-up) each rebuild docs/. Whichever merges second needs a rebuild, plus one test constant in api/test/auth.test.mjs: it takes name: null from this PR and waiting: false from FW-603. I merged all three locally and ran every check on the result: everything passes.

🤖 Generated with Claude Code

dikshant-deskera and others added 3 commits November 13, 2026 17:42
The header on the landing page and /pricing gets an account slot beside
the GitHub button:

- Signed out, it reads Sign in, linking to /login.
- Signed in, it shows the account's initial and address. A menu says
  who is signed in and offers Account, Console and Sign out. An account
  still on the waitlist gets Waitlist instead of Console. Signing out
  stays on the page and puts focus on Sign in; a sign-out that fails
  says so in the menu.
- The landing page is prerendered with no session, so the slot keeps
  one width and shows nothing until the service answers. Someone signed
  in never sees Sign in flash by, and the links never move. If the
  service can't be asked, it offers Sign in.

Below 1100px the slot narrows to the initial and the GitHub button to
its mark, so the links fit as before. Below 851px the menu hangs from
the header's right edge so it stays inside the window.

The "How it works" menu's close-on-outside-press, Escape and tab-out
handling moves into a useDismiss hook that both menus use, and its
panel motion into lib/panel.ts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Accounts kept only an email address, so the header could only show
that. Now an account can have a name:

- api: migration 0003 adds users.name, and the user the service
  describes carries it (null until given). /auth/verify takes an
  optional name, which names a new account or one without a name yet,
  and never replaces one. A new POST /auth/profile sets or clears it
  for the signed-in account. A name is trimmed, its runs of spaces made
  one, and up to 80 characters; control characters and bidirectional
  overrides are refused, before the code is tried, so a bad name
  doesn't use up a try. The admin listing carries names too.
- site: /signup asks for an optional name above the address. /account
  has a Name field to change or clear it. The header shows the name,
  with the initials of its first and last words ("AL"), and the menu
  shows the name above the address; without a name, both show the
  address as before. The console's footer and the admin page show it
  too. The in-browser demo keeps the name with its session.

Tests: api/test/profile.test.mjs covers giving, keeping, changing and
clearing a name, what's refused, the session and origin checks, and
the admin listing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
pillOutline sits on shadcn's default Button variant, whose
hover:bg-primary/80 it never overrode, so under the pointer an
outlined button (Sign out on /account, Resend code and Use another
address while signing in, Save name) turned near-black with its dark
text unreadable. It now keeps its fill, and only its border darkens,
as intended.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@ashutosh091
ashutosh091 merged commit f670103 into erphq:preview Nov 14, 2026
3 checks passed
@ashutosh091

Copy link
Copy Markdown
Contributor

Landed on preview through #47, which merged this branch together with the other two FW-60x PRs on top of the Paygate billing work. Your commits are unchanged. Changes made during the merge: the profile-name migration is renumbered to 0004_profile_name.sql (preview already had 0003_billing.sql); the /pricing copy now says to start on Free and upgrade, since billing is live; and the billing test suite pins SIGNUP_MODE: "waitlist". Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants