{{define "title"}}Account settings · MeshTender{{end}} {{define "header"}}
Your account

Account settings

{{end}} {{/* Four cards, in the order people reason about them: what the world sees, then how the app treats you, then how you get in, then how you leave. Public profile is one form with one Save — every field on it is part of the same public page. Sign-in & security is the opposite shape: a row per credential, each stating its current state and hiding its own form behind a toggle, because those saves are genuinely separate acts and a page that shows four expanded forms at once buries the one fact people came for (do I have a password? is my email confirmed?). Public-profile fields carry no per-field "optional" tag: every field in that card is optional, and the subtitle already says so ("Leave a field blank to keep it off your page"). Four right-aligned repeats of the same word read as clutter, not information. */}} {{define "content"}} {{if .Error}}
{{.Error}}
{{end}} {{if .OK}}
{{.OK}}
{{end}}

Public profile

Everything here appears on {{.RootURL}}/u/{{.User.Username}}, which anyone can view. Leave a field blank to keep it off your page.

{{/* One form for the whole card: these fields are a single public page, and splitting them into three saves let someone rewrite their profile and walk away having stored a third of it. The link editor's data-link-editor hook goes on this form too — link-editor.js finds its rows from there. */}}
What other people see — on shares and in organizations. It can be anything, and it isn't tied to sign-in.

Links

Ways to reach or find you — social media, a website, or your MeshCore public key (shown as a QR code). Mark one non-MeshCore link as your primary contact so people know the best way to reach you.

{{range $i, $l := .Links}} {{end}}

Preferences

How MeshTender presents things to you.

{{/* Same shape as Public profile — fields in the body, one Save in the footer — so the two editable cards on this page behave alike. Time zone is the only preference today; the footer is what keeps that from needing a rewrite when there are three. */}}
{{/* The full IANA list is filled in by timezone-picker.js from the browser's own Intl database. These options are the no-JS fallback and preserve the current value on round-trip. data-current carries the saved zone so the script can reselect it. */}} Dates and times are shown in this zone, in your browser's locale format. Auto-detect uses whatever zone your browser reports.
{{/* Sign-in & security is a list of rows rather than stacked forms: each row states what's configured right now (the answer to the question people actually arrive with) and hides its controls behind a toggle. Username and email live here because both are credentials — one identifies the account at sign-in, the other is how it's recovered — not because they're settings. A row auto-expands when it carries a flash message, so the result of a save is never hidden behind a collapsed panel. */}}

Sign-in & security

How you get into this account, and how you get back in. Keep at least one sign-in method that works.

{{template "icon-user" ""}}

Username

@{{.User.Username}}

3–32 characters: letters, digits, _ . -. It's also the address of your public page. You can change it once every 30 days; your old username is then reserved for 90 days before anyone else can take it.

@
{{if .NextRename}} You changed your username recently. You can change it again on {{ts .NextRename "date"}}. {{end}}
{{/* Email row. Hidden entirely when no mail provider is configured: an address we can't send to would be a promise we can't keep. What it SAYS depends on three things — whether an address is set, whether it's confirmed, and whether there's a password to reset — because a passkey-only account's address genuinely can't recover it, and implying otherwise is the one thing worse than silence. */}} {{if .MailEnabled}}
{{template "icon-mail" ""}}

Email (private)

{{if .Email}} {{.Email}} {{if .EmailVerified}}confirmed{{else}}unconfirmed{{end}} {{else}}Not set — no way to recover this account{{end}}

Optional. Used to recover your account if you forget your password. It's never shown on your public profile, and we only email you about your account — never marketing.

{{if .EmErr}}
{{.EmErr}}
{{end}} {{if .EmMsg}}
{{.EmMsg}}
{{end}} {{if .Email}}
{{if .EmailVerified}} {{if .CanResetByMail}} You can reset your password by email. {{else}} This account has no password, so there's nothing to reset — sign-in is by passkey only. To keep access if you lose your device, add a passkey on a second device. {{end}} {{else}} Check your inbox for the confirmation link. Until it's confirmed, this address can't recover your account. {{end}}
{{if not .EmailVerified}}
{{end}}
{{end}}
We'll send a confirmation link. A new address has to be confirmed before it can recover your account.
{{end}}
{{template "icon-key" ""}}

Passkeys

{{if .Passkeys}} {{/* Underlined at rest, not just on hover, plus a chevron that flips with aria-expanded: a summary line that only looks like a link when you're already pointing at it isn't discoverable. */}} {{else}}Not set up — sign in is by password only{{end}}
{{if or .PKErr .PKMsg}}
{{if .PKErr}}
{{.PKErr}}
{{end}} {{if .PKMsg}}
{{.PKMsg}}
{{end}}
{{end}} {{if .Passkeys}}
{{range .Passkeys}}
{{if .Name}}{{.Name}}{{else}}Unnamed passkey{{end}}
{{.ShortID}}… · Added {{ts .Added "date"}}
{{end}}
{{end}}

Passkeys let you sign in with your device's fingerprint, face, or PIN — no password to remember or leak.

{{template "icon-lock" ""}}

Password

{{if .HasPassword}}Configured{{else}}Not set — sign in is by passkey only{{end}}
{{if not .HasPassword}}

A password is a fallback for when you can't use a passkey.

{{end}}
{{/* Current → new → confirm, stacked in that order: the arrangement every password form uses, so nobody has to read it to know what it wants. */}} {{if .HasPassword}}
{{end}}
{{if .HasPassword}}
{{/* Removing a password takes a fresh passkey assertion, not just a click: it is the one action here that permanently narrows how you can get back in, and a live session only proves somebody signed in at some point. The confirm text names the recovery consequence too — email reset only ever sets a password on an account that HAS one, so removing it silently turns a working recovery path into a dead end. */}}
{{if .Passkeys}}
{{else}} Add a passkey first — it would otherwise be your only way to sign in. {{end}} {{end}}
{{/* Deletion is a page, not a button here: what it removes depends on what you own, and that has to be shown before anyone commits to it. */}}

Delete account

Permanently delete your account, your public profile, and the repeaters you own. This can't be undone — the next page shows exactly what would go, and lets you hand any repeater to a steward first.

{{template "icon-trash" "me-1"}}Delete my account…
{{end}}