docs: audit corrections, coverage pages, screenshots, and em-dash removal

Finalizes the docs section after an adversarial audit (code review + per-page
fact-check + coherence critic) and two content requests.

- Accuracy: fixed 10 invented cross-link slugs, the admin-vs-board gating claims
  the verifiers caught (permissions matrix, /settings, invites, onboarding,
  connect-payments, proposal withdraw, Stripe reconciliation, member fields,
  door.operate), and 2 issues in the new pages (project area-at-creation, forum
  thread-delete role).
- Coverage: added 5 how-to pages so every module is documented (recurring Stripe
  dues, tasks & chores, projects, comms & forum, ops knowledge base + secrets
  vault). 34 pages total.
- Screenshots: 12 captioned app screenshots under public/docs-media/, embedded
  as figures. Each tutorial now has 2-3 step screenshots.
- Style: removed all em-dashes/en-dashes/ellipses from the docs (natural ASCII
  punctuation).
- Handoff (docs/HANDOFF-audit-cleanup.md) updated with the current state.

typecheck 0 · lint 0 errors · build ok (all 34 /docs pages prerendered)
This commit is contained in:
Moheeb Zara
2026-08-05 03:15:07 -07:00
parent 16229ae523
commit 8edc9da611
50 changed files with 610 additions and 202 deletions
+6 -4
View File
@@ -1,9 +1,11 @@
Bring an existing roster into your space in one pass. The [/import](/import) screen (titled **Import & Sync**) reads a CSV, lets you map its columns to member fields, previews the result, and upserts everyone into [/members](/members) with a tier and a status.
![The Import and Sync screen: a four-step wizard (upload, map columns, preview, import) for members or payments.](/docs-media/import.jpg)
## Before you start
- **Role required:** the Import & Sync screen opens for **admin**, **board**, and **treasurer**. The member import itself is gated tighter — the server action accepts only **admin** or **board**. A treasurer who runs a member import gets `Admin access required`.
- **File format:** a `.csv` (or `.txt`) file. There is no paste box — you upload or drag-and-drop a file. Quoted fields and embedded commas are handled.
- **Role required:** the Import & Sync screen opens for **admin**, **board**, and **treasurer**. The member import itself is gated tighter, the server action accepts only **admin** or **board**. A treasurer who runs a member import gets `Admin access required`.
- **File format:** a `.csv` (or `.txt`) file. There is no paste box, you upload or drag-and-drop a file. Quoted fields and embedded commas are handled.
- **Row limit:** 5000 members per import.
- One row per member; the first row must be a header row.
@@ -21,7 +23,7 @@ Only two columns are required. Header names are auto-detected on upload, so sens
| Last Paid Date | No | Any parseable date |
| Card Access | No | `yes`/`true`/`1`/`y` becomes true; anything else false |
The mapping dropdown also offers **Handle / Username**, but that column is not written to the member record — leave it on **Skip this column** or don't rely on it.
The mapping dropdown also offers **Handle / Username**, but that column is not written to the member record, leave it on **Skip this column** or don't rely on it.
Tier values are matched loosely and collapsed to the three real tiers:
@@ -55,7 +57,7 @@ Imported members start as **current** and unlinked to any login account. They li
## Edge cases
- **Re-importing updates, not duplicates.** Rows upsert on `(space_id, email)`. Importing an email that already exists in your space overwrites that member's mapped fields — a safe way to bulk-update. Rows with no matching email are inserted new.
- **Re-importing updates, not duplicates.** Rows upsert on `(space_id, email)`. Importing an email that already exists in your space overwrites that member's mapped fields, a safe way to bulk-update. Rows with no matching email are inserted new.
- **Bad rows are skipped, not fatal.** Each row is validated individually (invalid email, missing name, unknown tier, or unparseable date). Skipped rows are counted and reported; the rest still import.
- **A row missing name or email** is dropped before the server call and reported as `Row N: missing name or email` (N is the spreadsheet row).
- **Card access is granted in the record only.** Importing `has_card_access` marks the flag; it does not program a physical door card or card reader.