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:
@@ -8,16 +8,18 @@ You need the right role for each part:
|
||||
|
||||
| Task | Required role |
|
||||
| --- | --- |
|
||||
| Add or edit a pay-here link | admin or board |
|
||||
| Add or edit a pay-here link | admin (the Settings screen is admin-only) |
|
||||
| Import and reconcile payments | admin, board, or treasurer |
|
||||
|
||||
This example uses Venmo, but PayPal and Zeffy work exactly the same way.
|
||||
|
||||
## Step 1: Add a pay-here link
|
||||
|
||||

|
||||
|
||||
1. Go to [/settings](/settings) and open the **Dues** tab.
|
||||
2. Under **Other ways to pay dues** you will see a card for each platform: PayPal, Zeffy, and Venmo. Find the **Venmo** card.
|
||||
3. Paste your payment link into the **URL** field. It must be an absolute `https://` URL — anything else is rejected.
|
||||
3. Paste your payment link into the **URL** field. It must be an absolute `https://` URL, anything else is rejected.
|
||||
4. Optionally add an instruction, for example `Put your member name in the note`. This is a hint that helps you match the payment later.
|
||||
5. Leave the toggle set to **shown** so members can see it.
|
||||
6. Click **Save**.
|
||||
@@ -26,16 +28,18 @@ The link is now live for your space. You can add all three platforms, and hide a
|
||||
|
||||
## Step 2: The member pays externally
|
||||
|
||||
There is nothing for you to do here — this is what the member sees.
|
||||
There is nothing for you to do here, this is what the member sees.
|
||||
|
||||
1. The member opens their [/me](/me) page and looks at the **Dues** section.
|
||||
2. While they still owe dues, the card shows your active links under **Other ways to pay** (or **Pay your dues** if your space has no card billing set up).
|
||||
3. They click **Pay with Venmo**, which opens your external payment page in a new tab, and they pay you there — adding their name in the note if you asked them to.
|
||||
3. They click **Pay with Venmo**, which opens your external payment page in a new tab, and they pay you there, adding their name in the note if you asked them to.
|
||||
|
||||
The platform does not record this payment automatically. That is the next step.
|
||||
|
||||
## Step 3: Record the payment
|
||||
|
||||

|
||||
|
||||
When your Venmo activity is available, export it as a CSV and import it.
|
||||
|
||||
1. Go to [/import](/import) and switch the **Import type** to **Payments**.
|
||||
@@ -45,10 +49,12 @@ When your Venmo activity is available, export it as a CSV and import it.
|
||||
|
||||
Every imported row lands as an `unlinked` payment. Rows with a bad amount, platform, or date are skipped and counted, so nothing invalid is silently added.
|
||||
|
||||
> Recording a single hand-received payment instead? Use the **Log Cash** button on [/payments](/payments) — but note it always records the platform as `cash`.
|
||||
> Recording a single hand-received payment instead? Use the **Log Cash** button on [/payments](/payments), but note it always records the platform as `cash`.
|
||||
|
||||
## Step 4: Reconcile the payment to the member
|
||||
|
||||

|
||||
|
||||
1. Go to [/payments](/payments). The header shows a count like **1 unlinked** whenever payments still need a member.
|
||||
2. Find your Venmo row. You can narrow the list with the **All Platforms** and **All Status** filters at the top of the transactions table.
|
||||
3. Click **+ Link member** on that row.
|
||||
@@ -61,7 +67,7 @@ The row flips to `linked` and shows the member's name with a check mark.
|
||||
Linking a payment does two things automatically:
|
||||
|
||||
- It advances the member's **last paid** date to the payment's date.
|
||||
- It sets the member's status to `current` — as long as this payment is the most recent one on file for them.
|
||||
- It sets the member's status to `current`, as long as this payment is the most recent one on file for them.
|
||||
|
||||
This is **advance-only**: recording an older or backdated payment never moves a member's dues backward. If the member already has a newer payment recorded, linking an older one leaves their status untouched.
|
||||
|
||||
@@ -69,4 +75,4 @@ To verify, open the member on [/members](/members) and check their status, or ha
|
||||
|
||||
## What you did
|
||||
|
||||
You added an external pay-here link, a member paid through it, you imported the payment as an `unlinked` row, and you reconciled it to the member — advancing their dues to `current`. Repeat Step 3 and Step 4 whenever new external payments come in.
|
||||
You added an external pay-here link, a member paid through it, you imported the payment as an `unlinked` row, and you reconciled it to the member, advancing their dues to `current`. Repeat Step 3 and Step 4 whenever new external payments come in.
|
||||
|
||||
@@ -9,6 +9,8 @@ Set aside about fifteen minutes. You will need the `classes.manage` permission t
|
||||
|
||||
## Step 1: Create a class
|
||||
|
||||

|
||||
|
||||
A class is the reusable offering ("Woodshop Basics"). Sessions are the individual scheduled occurrences you will add later.
|
||||
|
||||
1. Go to [/classes/manage](/classes/manage).
|
||||
@@ -33,6 +35,8 @@ The session appears under the class with its start time and a **Scheduled** stat
|
||||
|
||||
## Step 3: Members sign up
|
||||
|
||||

|
||||
|
||||
Members do not need any special permission to sign up, only membership in the space.
|
||||
|
||||
1. As a member, go to [/classes](/classes). Upcoming, non-cancelled sessions appear with "X of N spots left" (or "open" when unlimited).
|
||||
@@ -42,7 +46,7 @@ When registered signups reach capacity, the button reads **Join waitlist** inste
|
||||
|
||||
## Step 4: Mark attendance
|
||||
|
||||
Now switch back to someone with `classes.instruct`. (A user with only `classes.manage` can open the roster and see who signed up, but cannot check **attended** or run **Complete session** — both require `classes.instruct`.)
|
||||
Now switch back to someone with `classes.instruct`. (A user with only `classes.manage` can open the roster and see who signed up, but cannot check **attended** or run **Complete session**, both require `classes.instruct`.)
|
||||
|
||||
1. On [/classes/manage](/classes/manage), find the session and select **Signups**. (Instructors browsing [/classes](/classes) can use **Attendees** on the session instead.)
|
||||
2. The roster lists each signup with its status. Check the **attended** box next to each member who showed up.
|
||||
@@ -54,7 +58,7 @@ Attendance is what determines who receives a certification in the next step, so
|
||||
1. In the same attendees panel, select **Complete session**.
|
||||
2. The session status changes to **Completed**.
|
||||
|
||||
If the class grants a certification, completion awards it to every member you marked as attended. The result confirms how many certificates were issued. If the instructor lacks `certifications.grant`, the session still completes but you will see "Certificates were NOT issued (requires the certifications.grant permission)" — grant that permission and the members can be certified through [/certifications](/certifications).
|
||||
If the class grants a certification, completion awards it to every member you marked as attended. The result confirms how many certificates were issued. If the instructor lacks `certifications.grant`, the session still completes but you will see "Certificates were NOT issued (requires the certifications.grant permission)", grant that permission and the members can be certified through [/certifications](/certifications).
|
||||
|
||||
Members can see their signups and completed sessions on their own page at [/me](/me), and any certification they earned appears in their certifications.
|
||||
|
||||
@@ -62,8 +66,8 @@ Members can see their signups and completed sessions on their own page at [/me](
|
||||
|
||||
You now have a class with one completed session, an attendance record, and (optionally) certifications awarded to attendees. From here you can:
|
||||
|
||||
- Schedule more sessions of the same class — the offering is reusable.
|
||||
- Schedule more sessions of the same class, the offering is reusable.
|
||||
- **Archive** a class you no longer offer instead of deleting it (deleting is only allowed when a class has no sessions).
|
||||
- **Cancel** a session instead of deleting it to keep the signup history; every signed-up member is emailed when you do.
|
||||
|
||||
See the [classes reference](/docs/reference/classes) for every field, status, and permission, and [manage certifications](/docs/how-to/manage-certifications) for setting up the certification types classes can grant.
|
||||
See the [classes, certifications & equipment reference](/docs/reference/classes-and-equipment) for every field, status, and permission, including how certification types are defined and granted on class completion.
|
||||
|
||||
@@ -2,6 +2,8 @@ This tutorial walks you from a blank signup form to a working space where you la
|
||||
|
||||
By the end you will have a space of your own, an admin membership inside it, and a mental map of the sidebar.
|
||||
|
||||

|
||||
|
||||
## Before you start
|
||||
|
||||
You need an email address and a password of at least 8 characters. If someone has already set up a space for your group and given you an invite code, skip ahead to [Joining an existing space](#joining-an-existing-space) instead.
|
||||
@@ -17,7 +19,7 @@ You need an email address and a password of at least 8 characters. If someone ha
|
||||
|
||||
Now you are on the **Set up your Space** step.
|
||||
|
||||
1. Enter a **Space Name**, such as `HeatSync Labs`. As you type, a **Slug** is filled in for you automatically — it is the lowercase, letters-and-numbers-only handle for your space (for example `heatsynclabs`). You can edit it.
|
||||
1. Enter a **Space Name**, such as `HeatSync Labs`. As you type, a **Slug** is filled in for you automatically, it is the lowercase, letters-and-numbers-only handle for your space (for example `heatsynclabs`). You can edit it.
|
||||
2. Optionally enter a **City / Location**.
|
||||
3. Read the note: you will be the admin of this space, and default channels (general, announcements, ops) are created for you.
|
||||
4. Click **Create Space →**.
|
||||
@@ -27,7 +29,7 @@ Depending on how email confirmation is configured, one of two things happens:
|
||||
- You go straight to `/dashboard`, already signed in.
|
||||
- You are sent to `/signup/confirm` to verify your email first. Open the link in that email, and you will land on the dashboard afterward.
|
||||
|
||||
That is it — your space exists. As the founder you are set up as an **admin** on the **plus** tier with a **current** status, and you skip the member onboarding flow entirely.
|
||||
That is it, your space exists. As the founder you are set up as an **admin** on the **plus** tier with a **current** status, and you skip the member onboarding flow entirely.
|
||||
|
||||
## Step 3: Get your bearings on the dashboard
|
||||
|
||||
@@ -40,21 +42,23 @@ The first time you open `/dashboard` in an empty space, you see a **"Let's set u
|
||||
| Create your first task or chore | `/tasks` |
|
||||
| Connect payments | `/settings` |
|
||||
|
||||
That panel disappears on its own once there is real activity. After that, the dashboard shows a stat row — **Active Members**, **Dues Current**, **Open Tasks**, **Unlinked Payments** — plus quick chores, active projects, who is present now, and recent activity. The **Quick Task** button in the header jumps to `/tasks`.
|
||||
That panel disappears on its own once there is real activity. After that, the dashboard shows a stat row (**Active Members**, **Dues Current**, **Open Tasks**, **Unlinked Payments**) plus quick chores, active projects, who is present now, and recent activity. The **Quick Task** button in the header jumps to `/tasks`.
|
||||
|
||||
## Step 4: Explore the left navigation
|
||||
|
||||

|
||||
|
||||
The sidebar groups every screen into sections. As an admin you see all of them:
|
||||
|
||||
- **Workspace** — Dashboard, Tasks & Chores, Projects, Ops & Facilities, Comms, Forum
|
||||
- **Governance** — Proposals, Incidents, Policies
|
||||
- **Access & Resources** — Classes, Equipment, Doors, Forms
|
||||
- **People** — Members, Attendance, Contacts, Recruitment
|
||||
- **Finance** — Payments, Financials
|
||||
- **Account** — My membership
|
||||
- **Admin** — Customize, Settings, Import / Sync, and the management screens for forms, certifications, classes, equipment, and doors
|
||||
- **Workspace**, Dashboard, Tasks & Chores, Projects, Ops & Facilities, Comms, Forum
|
||||
- **Governance**, Proposals, Incidents, Policies
|
||||
- **Access & Resources**, Classes, Equipment, Doors, Forms
|
||||
- **People**, Members, Attendance, Contacts, Recruitment
|
||||
- **Finance**, Payments, Financials
|
||||
- **Account**, My membership
|
||||
- **Admin**, Customize, Settings, Import / Sync, and the management screens for forms, certifications, classes, equipment, and doors
|
||||
|
||||
The **Admin** section only appears for admins, board members, or members you have granted a specific manage permission. There is also a **Jump to…** button at the top of the sidebar (or press ⌘K) that opens a command palette for fast navigation.
|
||||
The **Admin** section only appears for admins, board members, or members you have granted a specific manage permission. There is also a **Jump to...** button at the top of the sidebar (or press ⌘K) that opens a command palette for fast navigation.
|
||||
|
||||
A good next stop is [inviting your first members](/members), or `/customize` to shape what new members see when they join.
|
||||
|
||||
@@ -64,10 +68,10 @@ If you were given an invite code instead of starting a new space:
|
||||
|
||||
1. Go to `/signup` (or open the `/signup?invite=CODE` link your admin shared, which prefills the code for you).
|
||||
2. Fill in your account details and click the **Join a Space** card, then **Continue →**.
|
||||
3. Enter the **Invite Code** — it looks like `HSL-2025-XXXX`. Ask your space admin for it if you do not have one; they can find the space's default code under Settings.
|
||||
3. Enter the **Invite Code**, it looks like `HSL-2025-XXXX`. Ask your space admin for it if you do not have one; they can find the space's default code under Settings.
|
||||
4. Click **Join Space →**.
|
||||
|
||||
You join as a **member**. If the space requires approval (the default), your status starts as **unverified** and an admin approves you before you gain full access — until then the dashboard is still yours to look around. If the space does not require approval, you are **current** right away.
|
||||
You join as a **member**. If the space requires approval (the default), your status starts as **unverified** and an admin approves you before you gain full access, until then the dashboard is still yours to look around. If the space does not require approval, you are **current** right away.
|
||||
|
||||
## What you did
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
In this tutorial you will bring your first people into your space two ways — a shareable join link and a manual add — shape what a new member sees when they first open the app, and move everyone to `current` status. Work through it as a space admin; by the end you will have a repeatable way to grow your roster.
|
||||
In this tutorial you will bring your first people into your space two ways (a shareable join link and a manual add), shape what a new member sees when they first open the app, and move everyone to `current` status. Work through it as a space admin; by the end you will have a repeatable way to grow your roster.
|
||||
|
||||

|
||||
|
||||
## Before you start
|
||||
|
||||
@@ -6,8 +8,8 @@ You need the **admin** role (a **board** member can copy and share existing invi
|
||||
|
||||
There are two ways in:
|
||||
|
||||
- **Invite code / join link** — people sign themselves up, then you approve them.
|
||||
- **Add member** — you enter someone directly and they are active immediately.
|
||||
- **Invite code / join link**, people sign themselves up, then you approve them.
|
||||
- **Add member**, you enter someone directly and they are active immediately.
|
||||
|
||||
You will use both.
|
||||
|
||||
@@ -16,7 +18,7 @@ You will use both.
|
||||
1. Open [/members](/members) and find the **Invite codes** card.
|
||||
2. Click **+ New invite**.
|
||||
3. Leave the code blank to auto-generate one, or type your own. Optionally set a **Label**, an expiry, and a **Max uses** cap. Leave both blank for a permanent code.
|
||||
4. Pick what the code **grants** — for new members, choose `member`.
|
||||
4. Pick what the code **grants**, for new members, choose `member`.
|
||||
5. Tick **Single use** if the code should auto-disable after one join.
|
||||
6. Click **Create invite**.
|
||||
|
||||
@@ -26,16 +28,16 @@ Your code appears in the list with a `grants member` tag and a live use count.
|
||||
|
||||
On the new code's row you have two buttons:
|
||||
|
||||
- **Copy code** — copies just the code (for people who will type it during signup).
|
||||
- **Copy link** — copies the one-click join link, which looks like:
|
||||
- **Copy code**, copies just the code (for people who will type it during signup).
|
||||
- **Copy link**, copies the one-click join link, which looks like:
|
||||
|
||||
```
|
||||
https://your-space.example/join/your-space?code=ABC23XYZ
|
||||
```
|
||||
|
||||
Send the link. Whoever opens it lands on a **Join** page for your space, creates an account, and is added as a member with `unverified` status — waiting for your approval.
|
||||
Send the link. Whoever opens it lands on a **Join** page for your space, creates an account, and is added as a member with `unverified` status, waiting for your approval.
|
||||
|
||||
If a code is ever shared too widely, an admin can click **Disable** to revoke it, or **Delete** to remove it outright — both controls are admin-only.
|
||||
If a code is ever shared too widely, an admin can click **Disable** to revoke it, or **Delete** to remove it outright, both controls are admin-only.
|
||||
|
||||
## Step 3: Approve people who joined
|
||||
|
||||
@@ -49,7 +51,7 @@ Approving flips the member to `current` and marks them approved, so they count t
|
||||
|
||||
## Step 4: Add a member manually
|
||||
|
||||
Some people you will enter yourself — a founding member, someone who paid at the door.
|
||||
Some people you will enter yourself, a founding member, someone who paid at the door.
|
||||
|
||||
1. On [/members](/members), click **Add Member**.
|
||||
2. Fill in **Full Name** and **Email** (both required). Phone and handle are optional.
|
||||
@@ -57,7 +59,7 @@ Some people you will enter yourself — a founding member, someone who paid at t
|
||||
4. Optionally set **Joined At** and tick **Card Access**.
|
||||
5. Click **Add Member**.
|
||||
|
||||
A manually added member starts at `current` immediately — no approval step needed.
|
||||
A manually added member starts at `current` immediately, no approval step needed.
|
||||
|
||||
## Step 5: Shape the onboarding flow
|
||||
|
||||
@@ -65,7 +67,7 @@ Now decide what a member sees the first time they open the app.
|
||||
|
||||
1. Go to [/customize](/customize) and find the **New member onboarding** card.
|
||||
2. Every new space starts with four built-in steps in order: **Welcome**, **Code of Conduct** (a required acknowledgement), **Complete your profile**, and **Set up your dues**.
|
||||
3. Edit any step's title inline, and its body where the step has one (body supports Markdown) — the built-in **Complete your profile** step has only an editable title, no body. Change the order with the number box, and untick **Enabled** to hide a step.
|
||||
3. Edit any step's title inline, and its body where the step has one (body supports Markdown), the built-in **Complete your profile** step has only an editable title, no body. Change the order with the number box, and untick **Enabled** to hide a step.
|
||||
4. On the **Set up your dues** step, paste your **Payment link** so the member gets a working "Set up payment" button.
|
||||
5. Add your own with **+ Custom step**, or use **+ Form step** to make members sign a published form or waiver as part of onboarding.
|
||||
|
||||
@@ -73,7 +75,9 @@ Built-in steps can be disabled and reordered but not deleted. Only steps you mar
|
||||
|
||||
## Step 6: See what the new member sees
|
||||
|
||||
The first time an approved member opens the app they are routed to [/onboarding](/onboarding) and walk your enabled steps in order — a progress bar tracks **Step X of Y**. They must tick the code-of-conduct box and any other required step before the final **Finish** button lets them through to the [/dashboard](/dashboard). If no step is required, a **Skip for now** link is available.
|
||||

|
||||
|
||||
The first time an approved member opens the app they are routed to [/onboarding](/onboarding) and walk your enabled steps in order, a progress bar tracks **Step X of Y**. They must tick the code-of-conduct box and any other required step before the final **Finish** button lets them through to the [/dashboard](/dashboard). If no step is required, a **Skip for now** link is available.
|
||||
|
||||
## You are done
|
||||
|
||||
|
||||
Reference in New Issue
Block a user