ThreadCount Community edition
Uniform stock management for healthcare linen rooms: the coordinator app, the phone counter and the staff app, for your own server. Built from a113353 on 2026-09-15. Licensed under the Functional Source License (FSL-1.1-ALv2).
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
---
|
||||
title: The counter app
|
||||
section: apps
|
||||
order: 1
|
||||
summary: The linen room's phone app, on Android and in a phone browser. Choosing a server, signing in, the screens, and what it keeps on the phone.
|
||||
screen: /m
|
||||
role: Admin or Issuer
|
||||
keywords: counter app, android, phone, mobile, play store, install, sign in, server, self-hosted, community, offline, camera, stocktake, count, issue
|
||||
---
|
||||
|
||||
The counter app is the coordinator's side of ThreadCount on a phone. You sign in with the same Admin or Issuer account as the website and see the same records, served at `/m`.
|
||||
|
||||
## Two ways to open it
|
||||
|
||||
- **In a phone browser.** Go to `https://threadcount.tech/m`, or `https://your-host/m` on your own server. You don't need to install anything.
|
||||
- **The Android app.** It is called **ThreadCount** on Google Play. It shows the same `/m` screens inside the app and adds the phone's own barcode scanner (see [Scanning and browsers](/docs/apps/scanning-and-browsers)).
|
||||
|
||||
There is no iOS app. On an iPhone or iPad, open `/m` in the browser.
|
||||
|
||||
## The first screen and choosing a server
|
||||
|
||||
The first time you open the Android app, the welcome screen shows **Sign in**, **Sign up** and a line reading `Server: threadcount.tech · Change`.
|
||||
|
||||
Most rooms use the hosted service and leave that line alone. A room running the Community edition on its own server changes it, once, on each phone:
|
||||
|
||||
1. **Tap `Server: threadcount.tech · Change`.** The `Which server?` screen opens.
|
||||
2. **Choose `Self-hosted`** and type the server's address, for example `uniforms.example.com`.
|
||||
3. **Tap `Check and use this server`.** The app checks the server's `/api/app-info` to confirm it is a ThreadCount server.
|
||||
|
||||
The app refuses an address that doesn't answer over https within 8 seconds, or that answers but isn't a ThreadCount server. Once the check passes, the app saves the address on that phone and opens that server from then on. Choosing `ThreadCount hosted` puts the phone back on `threadcount.tech`.
|
||||
|
||||
Once you have tapped `Sign in` or `Sign up` on that phone, the app skips the welcome screen and goes straight to `/m`.
|
||||
|
||||
## Signing in and signing up
|
||||
|
||||
`Sign in` asks for your work email and password. If your account has two-factor turned on, it then asks for the six-digit code from your authenticator app. A recovery code also works. `Forgot password` emails a reset link that works once and expires after an hour. See [Two-factor](/docs/account/two-factor).
|
||||
|
||||
`Sign up` creates a new facility. It doesn't add you to an existing one. The person who signs up becomes the new facility's first Admin. To add someone to an existing facility, an Admin sets up their account on the website: see [Users](/docs/account/users).
|
||||
|
||||
## The screens
|
||||
|
||||
The bar at the bottom has four tabs.
|
||||
|
||||
| Tab | What it does |
|
||||
|---|---|
|
||||
| Home | Today's issued and returned counts, lines below par, days since the last count, recent activity |
|
||||
| Count | Pick a shelf and count it by scanning; gaps go to a variance screen before the count is filed |
|
||||
| Stock | On hand against par, worst first, with a reorder draft |
|
||||
| Search | People and stock in one box, or scan a garment to find it |
|
||||
|
||||
Home also has `Issue to someone`, and `Deliveries, pickups, rounds and more` opens `More`:
|
||||
|
||||
- `Receive a delivery`
|
||||
- `Pickup call list`
|
||||
- `Delivery round`, with a signature on the phone
|
||||
- `Reprint a label`
|
||||
- `Variance over time`
|
||||
- `Catalogue`, where an Admin can add and edit garments
|
||||
- `Settings`
|
||||
|
||||
Open a person's record from Search or Issue to issue to them, take a return or swap a size. [Issue a garment](/docs/counter/issue-a-garment) and [Exchanges and returns](/docs/counter/exchanges-and-returns) say what each of those writes.
|
||||
|
||||
`More › Settings` holds only what the phone controls:
|
||||
|
||||
- `Beep and buzz on a scan`, which applies to this device only
|
||||
- `Reason required at`, the count gap that needs a reason. An Admin can change it; an Issuer can only see it.
|
||||
- links to the privacy policy, the terms and account deletion
|
||||
- `Sign out`
|
||||
|
||||
The staff register, reports, ordering and facility settings are on the desktop site.
|
||||
|
||||
## What it keeps on the phone
|
||||
|
||||
The app keeps only these on the phone:
|
||||
|
||||
- your session
|
||||
- any shelf count you have started but not filed. It is kept under your own account, so the next person on a shared phone never sees it. Filing the count deletes it, and signing out deletes all your open counts.
|
||||
- the beep setting, the chosen server, and whether the welcome screen has been seen
|
||||
|
||||
Issues, returns, stock, the staff register and every other record stay on the server.
|
||||
|
||||
## Permissions and connection
|
||||
|
||||
The Android app asks for one permission, the camera, and uses it only to read barcodes. No picture from scanning is stored or sent.
|
||||
|
||||
The app works online only. With no connection it shows `No connection.` and a `Try again` button, and it won't let you issue or count anything. Nothing is queued to send later. A count you hadn't filed stays on the phone until you're back online.
|
||||
|
||||
> **Careful** Signing out deletes any shelf count you haven't filed. File it first, or you'll have to count that shelf again.
|
||||
@@ -0,0 +1,82 @@
|
||||
---
|
||||
title: Scanning and browsers
|
||||
section: apps
|
||||
order: 3
|
||||
summary: USB scanners, the barcode formats ThreadCount reads, which browsers can scan with the camera, the Android scanner, and what happens with a code it doesn't know.
|
||||
role: Admin or Issuer
|
||||
keywords: scan, scanner, barcode, usb, camera, chrome, edge, safari, firefox, iphone, ean, upc, code 128, unknown barcode, bind, label, print
|
||||
---
|
||||
|
||||
ThreadCount reads a barcode in one of three ways: a USB scanner typing into a box, the camera in a supported browser, or the scanner built into the Android counter app. All three give the same result, and wherever you can scan, you can also type the code.
|
||||
|
||||
## USB scanners
|
||||
|
||||
A USB scanner that types the code and then presses Enter works with any browser. These desktop boxes accept one:
|
||||
|
||||
| Screen | Box |
|
||||
|---|---|
|
||||
| `Stock › Count` | `Scan barcode to count +1, then Enter` |
|
||||
| `Counter` | `Scan barcode, then Enter`, under `2 · Scan items` |
|
||||
| `Stock › On hand › Scan to add` | `Scan with a USB scanner, or type the code and press Enter` |
|
||||
| A garment's `Scan sizes` | The prompt names the size to scan next |
|
||||
|
||||
`Scan to add` and `Scan sizes` bind codes to the catalogue; the `Scan to add` button is shown to Admins only. Click into the box first. See [Keyboard and scanner](/docs/reference/keyboard-and-scanner).
|
||||
|
||||
## Formats it reads
|
||||
|
||||
Camera scanning, in the browser and in the Android app, reads these formats only:
|
||||
|
||||
- EAN-13 and EAN-8
|
||||
- UPC-A and UPC-E
|
||||
- Code 128, Code 39 and Code 93
|
||||
|
||||
ITF and Codabar are left out because they carry no check digit, so a partial read can pass as a different valid code. No 2D codes are read.
|
||||
|
||||
A USB scanner or a typed code isn't limited to that list, because the box just receives characters. In `Scan to add`, a 13-, 12-, 8- or 14-digit code has its check digit tested. If it fails, you see `check digit doesn't match — the scan may have mis-read`.
|
||||
|
||||
## Camera scanning in a browser
|
||||
|
||||
In a browser, the camera reads barcodes with the browser's built-in barcode detector.
|
||||
|
||||
| Browser | Camera scanning |
|
||||
|---|---|
|
||||
| Chrome | Yes |
|
||||
| Edge | Yes |
|
||||
| Safari on iPhone or iPad | No |
|
||||
| Firefox | No |
|
||||
|
||||
Where the camera opens but the browser can't read barcodes, the screen says `Live reading isn't supported here — type the code instead.` Where the browser has no camera access at all, it says `This browser has no camera access — type the code instead.`
|
||||
|
||||
On an iPhone, type the code or use a USB scanner.
|
||||
|
||||
## The Android scanner
|
||||
|
||||
Inside the **ThreadCount** Android app, the phone's own scanner reads the code instead of the browser's detector. If the app can't load that scanner, it uses the browser detector instead.
|
||||
|
||||
When counting a shelf, scanning stays on until you press `Stop scanning`. The same code seen again within 0.9 seconds is taken as the same garment still in view, not a second one. `Beep and buzz on a scan` in `More › Settings` turns the sound and vibration on or off for that phone.
|
||||
|
||||
The ThreadCount Staff app has no scanner.
|
||||
|
||||
## Codes ThreadCount doesn't know
|
||||
|
||||
A code is known once it is bound to one size of one garment. What happens with an unknown code depends on the screen:
|
||||
|
||||
- **Counting a shelf:** `isn't a garment ThreadCount knows. Bind it to a size first`. A known code from another shelf names that shelf instead.
|
||||
- **Issuing:** `isn't a garment ThreadCount knows.` Nothing is added.
|
||||
- **Returns:** the code has to match something the person is holding.
|
||||
- **Search:** the code is put in the search box.
|
||||
- **`Scan to add`:** you can start a new product from the code, or attach it to a size you already have.
|
||||
|
||||
With `Settings › Data` product lookup turned on, `Scan to add` first asks a public barcode database for a product name. With it off, nothing leaves the server.
|
||||
|
||||
A code can be on one size only. Binding a code that is already on another garment is refused unless you choose to move it. See [Barcodes](/docs/stock/barcodes).
|
||||
|
||||
## Printing ThreadCount barcodes
|
||||
|
||||
For garments that arrived without a barcode, `Generate barcodes` on the garment's page under `Stock` gives each size without a code one of ThreadCount's own. These are EAN-13 codes starting `29`, a prefix set aside for use inside one business, with a real check digit. A size that already has a supplier's code keeps it.
|
||||
|
||||
`Print labels` prints an A4 sheet of 6 labels at a time, one per garment on hand, for each size that has a code. A 13-digit code with a valid check digit prints as EAN-13, and any other code prints as Code 128.
|
||||
|
||||
`Reprint a label` in the counter app prints 1 to 24 copies of one size's label. It only lists sizes with a barcode bound to them. It prints from a phone browser. Inside the Android app the button reads `Print it on the desktop`, because that app can't print.
|
||||
|
||||
> **Careful** A garment without a readable barcode drops out of every scanned count. Reprint worn labels before the next stocktake.
|
||||
@@ -0,0 +1,76 @@
|
||||
---
|
||||
title: The staff app
|
||||
section: apps
|
||||
order: 2
|
||||
summary: The app for people who wear the uniform. How a staff member gets a sign-in, what they see and can do, what managers get, and how access is removed.
|
||||
screen: /my
|
||||
role: Staff
|
||||
keywords: staff app, wearer, nurse, self-service, code, slip, activation, sign in, kit, request, waitlist, damage, kit check, manager, approve, ward round, remove access
|
||||
---
|
||||
|
||||
The staff app shows one staff member their own uniform record, and lets them ask the linen room for what they need. It is at `/my` in any browser. On Android it is also on Google Play as **ThreadCount Staff**, which opens the same screens. There is no iOS app.
|
||||
|
||||
A staff sign-in is not a coordinator account. It is attached to the person's entry on the staff register, and it cannot open `/app` or `/m`.
|
||||
|
||||
## Getting a sign-in
|
||||
|
||||
An Admin gives each person a one-time code from their staff record on the website:
|
||||
|
||||
1. **Open the person in `People`** and press `Generate a code` in the `Staff app` panel.
|
||||
2. **Print the slip or copy the code.** The code is 12 characters in three groups and is shown once only.
|
||||
3. **Give the slip to the person.** In the app they tap `I have a code` (or `First time? I have a code` on the sign-in screen).
|
||||
4. **They enter the code, an email address and a password** of at least 8 characters, and tick the terms box if it is shown.
|
||||
|
||||
The code works once. It expires 14 days after it was printed (`SLIP_DAYS` in `lib/compute.ts`), and the staff record says how many days it has left. `New code` replaces an unused code, and `Cancel the code` withdraws it. A person who already has a sign-in cannot be given a code until their access is removed.
|
||||
|
||||
The email address is theirs to choose and may be a personal one. Each staff sign-in needs its own email address.
|
||||
|
||||
A staff member who forgets their password cannot reset it by email. The linen room removes their access and gives them a new code.
|
||||
|
||||
| Record | Change | Undo |
|
||||
|---|---|---|
|
||||
| Staff record | A code and its print date are stored | `Cancel the code` |
|
||||
| Staff account | Created with the email and a hashed password; the code is spent | `Remove access` |
|
||||
|
||||
## What a staff member sees and can do
|
||||
|
||||
The bar at the bottom has `Home`, `Kit`, `Orders` and `Messages`.
|
||||
|
||||
- **Home** shows the request furthest along (with its collection code once it is ready), how many garments they hold, and shortcuts.
|
||||
- **Kit** lists what the linen room has recorded against them. `This isn't right` raises a query about the record.
|
||||
- **Request** asks for one or more garments with a reason. The request goes to the manager recorded on their staff record for approval.
|
||||
- **On the shelf** shows each size as `In stock`, `Low` or `None on shelf`, and says when it was last counted.
|
||||
- **Waitlist** is offered for a size with none on the shelf, showing their place before they join. Accepting a held garment sends it to their manager as a request.
|
||||
- **Report damage** can also request a replacement. The garment leaves their record only when handed in at the counter.
|
||||
- **Kit check** is open only while the linen room is running one, and Home prompts for it if they hold garments and haven't answered yet. They confirm how many of each they still have.
|
||||
- **Orders** lists their open and finished requests, each with a message thread to the linen room.
|
||||
- **Your sign-in** changes their password. A new password signs them out on every other phone or browser.
|
||||
|
||||
## What they never see
|
||||
|
||||
- prices, costs or any payment
|
||||
- stock numbers: the shelf is shown in words only
|
||||
- anyone else's record, unless that person reports to them as a manager
|
||||
|
||||
They cannot delete their own account; only the linen room can remove access.
|
||||
|
||||
## Manager functions
|
||||
|
||||
A staff member becomes a manager when someone on the register names them as their manager. See [Managers](/docs/people/managers). They get:
|
||||
|
||||
- **Approvals.** Home shows how many requests are waiting. They can approve or decline each line, with a reason when they decline.
|
||||
- **Approve by link.** The email about a new request links to `/my/approve`, which needs no sign-in. The link lasts 14 days and stops working once the request is decided or either person leaves the register.
|
||||
- **Ward.** Who on their team holds what, with each person's set count.
|
||||
- **Raise for your team.** A request typed for someone who reports to them. It goes to the manager's own manager for approval.
|
||||
|
||||
A person with `On the ward desk` ticked in the `Staff app` panel of their staff record also gets `Ward round`, where bags delivered to their ward are signed for. Whoever signs is named on the order. See [Delivery rounds](/docs/counter/delivery-rounds).
|
||||
|
||||
## Permissions and connection
|
||||
|
||||
ThreadCount Staff asks for internet access and nothing else: no camera, location, contacts, files, photos or microphone. It has no barcode scanner. It works online only. With no connection it shows `No connection.` and nothing is saved to send later.
|
||||
|
||||
## Having access removed
|
||||
|
||||
On the person's staff record, an Admin presses `Remove access` and confirms. The staff account is deleted and every session it had ends at once. Their register entry and issue history stay.
|
||||
|
||||
Deactivating the person on the register also stops their sign-in straight away, with the message `You're no longer on the register at this facility.` See [Deactivating and deleting](/docs/people/deactivating-and-deleting).
|
||||
Reference in New Issue
Block a user