LITHOS / getting started / private groups

Private groups

A small-group discussion, an interview in the foyer, a quick huddle after the service. Anyone with a phone starts a group, shows the code, and the people around them join. Nobody at the sound desk has to do anything — and the group disappears when they're done.

The idea

What a private group is

The classes you set up on the operator page are listed: every phone sees "Sunday School" in its group picker and taps in. A private group is the opposite. It never appears in any list. It exists only for the people who have its 6-digit code (or scanned its QR), it has a language menu of its own, and every phone in it can speak — it is a round-table, not a lecture.

  • Made by an attendee, from the ordinary listener page. No PIN, no operator, no laptop.
  • Encrypted. Creating or joining one moves the phone to the https address, so its audio, captions and code travel encrypted — unlike the main service, which is plain http on purpose so the congregation never sees a certificate warning.
  • Temporary. It ends when the creator taps End group, when nobody has been in it for a few minutes, or at a lifetime limit you set. Nothing is saved.
  • Bounded. You decide how many groups can exist at once and how many billed language streams they may share. See caps.

Private groups are a feature of the same server your congregation already uses. Everything below applies to the desktop app and the always-on server alike unless it says otherwise.

Once, by the operator

Turn it on

It is off out of the box, because on means anyone on your WiFi can open a billed translation stream. Two ways to switch it on:

  1. On the operator page. Open Service settings at the bottom, tick Attendee groups, and press Save settings. The four numbers beside it are the caps — the defaults are sensible; they are explained below.
  2. Or with an environment variable, if you run the server yourself: LT_ATTENDEE_GROUPS=1 alongside your keys and operator PIN. This turns it on and ticks the box for you.
Attendee groups enabled with caps of 3 groups, 8 languages, 5 idle minutes and 120 lifetime minutes.
Service settings → Attendee groups. Checkbox, then the four caps.

Two things need to be true before a phone can actually create a group:

  • At least one language is turned on in the service. The private group's menu is the service's language menu — a group cannot offer a language you have not enabled. If none are on, the phone is told "No languages are available to translate."
  • A provider key is set (OpenAI or Gemini), because a private group is real translation and it is billed like any other.

The main service does not have to be running. A private group brings up its own translation, and only for the languages people in it actually pick.

From any phone

Create one from a phone

  1. Open the usual listener page (scan the room's Join QR, or type the address). Once attendee groups are on, two small links appear under the group buttons: ➕ Create a group and 🔑 Join with a code.
  2. Tap Create a group. The phone hops to the secure (https) address. The first time a phone does this it meets the one-time certificate notice — tap through it, and that phone is done with it for about a year. (Details, and how to make it disappear entirely, in the certificate guide.)
  3. Give it a name — "Relief Society", "Interview", anything up to 40 characters.
  4. That's it. The phone now shows a QR code, a 6-digit code, a live count of how many people are in, and an End group button. Hold it up, or read the code out.
The listener room picker includes Create a group and Join with a code.
1 · The two links appear once the feature is on.
The creator’s Relief Society group page with its demo join QR, code, listener count and End group button.
4 · The creator's phone: QR, code, headcount, End group.

The creator is also a member: the language buttons and the speak controls sit under the code, exactly as for anyone who joins. You can lock the phone or switch apps and come back; the group waits two minutes for its owner before it decides you have left.

Anyone can start a group, but not endlessly: one device may create five groups per ten minutes.

Everyone else

Join with the code

  • Scan the QR with the phone camera. It opens the secure address with the code already filled in and lands straight in the group.
  • Or type it: open the listener page, tap 🔑 Join with a code, enter the six digits.
A listener inside a private group with language, audio, text size and speak controls.
Inside the group: pick a language, tap to hear it, and speak when you want to.

Inside, it works like any class: pick a language to read captions, tap the audio line to hear it (earbuds, please), and speak with the green button — or tick Hands-free so the group takes turns by voice. The language you chose on the first screen is pre-selected if the group offers it.

A wrong code is just a wrong code — but a phone that gets it wrong ten times in ten minutes is locked out of guessing for the rest of that window. With a million possible codes, that ends brute-forcing.

Ending it

The creator taps End group; everyone in it is told the group has ended and returns to the first screen. Without that tap, the group still ends on its own — when the owner has been gone two minutes, when it has been empty for the idle minutes, or when it reaches its lifetime limit. Whichever comes first, its translation streams close with it.

A fair question

How private is it?

Two different questions hide in that one.

Who can get in

  • A private group is never advertised — not in the picker on other phones, not in the server's public group list. The only way in is the code or the QR.
  • The code is six digits and rate-limited (ten tries per ten minutes per device), so nobody guesses their way in.
  • So a stranger on the WiFi cannot casually wander into the group. Anyone you show the code to can join, and can pass it on — treat it like a room number, not a password.

Who can listen on the wire

  • Private groups ride https. Their audio, captions, code and owner token are encrypted between each phone and your server. A packet sniffer on the same WiFi sees that a connection exists, and nothing inside it.
  • The main service is different: it is plain http on the LAN by design, so the whole congregation joins without a warning. On a password-protected WiFi the radio link is already encrypted against outsiders; a device already on the network could still read the main service unless your router isolates clients. If that matters to you, the certificate guide covers putting the main service behind https as well.

Recommendations, in order of effort: keep the WiFi password private; turn on client (AP) isolation on the router; put the translation box on its own SSID or VLAN rather than the guest network.

Keeping the bill bounded

Caps & what it costs

A private group costs the same per minute as any other group: one provider stream per language that somebody is actually listening to. Nobody listening in Portuguese, no Portuguese stream. When the last Portuguese listener leaves, that stream closes fifteen seconds later — long enough to survive a language switch or a WiFi blip without re-opening a billed session.

Because anyone on the WiFi can start one, four caps sit next to the checkbox. They are all per server, not per group:

  • max (default 3) — how many private groups may exist at once. The fourth person to try sees "Too many groups already — try again later."
  • langs (default 8) — the total number of live language streams all private groups may share. This is the one that bounds the bill: with eight streams, the worst case is eight billed minutes for every minute of wall-clock time, however many groups are open. When the budget is used up, a newly requested language in a group simply waits for one to free up; languages people are already hearing keep priority.
  • idle (default 5 minutes) — a group with nobody in it for this long is ended.
  • ttl (default 120 minutes) — the longest any private group may live, from the moment it was created, whoever is still in it. A group that outlives a meeting is the classic way to pay for an empty room; set this to the length of your longest small-group meeting and no more.
The listener page reports Too many groups already when another private group would exceed the cap.
The max cap, from the phone's side.

A back-of-envelope: at roughly $0.035 a minute per stream, the default caps cost at most about $17 an hour if every one of the eight streams is busy — and in practice a couple of small groups in two languages each is a dollar or two for the hour. Private groups show up in the operator page's cost meter like everything else, so you can see what a Sunday actually used.

The service-wide idle auto-stop (in Service settings) is for the main engine; the idle and ttl caps above are the equivalents for private groups.

Fixes

When something's wrong

I don't see "Create a group" on my phone
The feature is off, or the page is stale. Tick Attendee groups in Service settings and save, then reload the phone page. If you started the server with LT_ATTENDEE_GROUPS=1, check the startup line — it prints attendee groups: on.
"No languages are available to translate"
The service's language list is empty, so a group would have nothing to offer. Turn on at least one language on the operator page. The main service does not need to be started — only the languages need to be on.
"Too many groups already — try again later"
The max cap is reached. Someone's group will end on its own at the idle or lifetime limit; or raise the cap in Service settings; or ask whoever finished to tap End group.
The phone stops at a "connection is not private" page
That is the one-time certificate notice on the secure address. On Android or a desktop browser, tap Advanced → Proceed. On an iPhone tap Show details → visit this website. It happens once per phone, and once more if the server's LAN address changes. To remove it altogether, see the certificate guide.
The page loads but nothing connects after the notice
Reload once. Browsers show the warning for the page but not for the live connection behind it; after you accept, a reload lets the connection through. If it still fails and you gave the server a real domain name, the missing piece is naming that host (LT_PUBLIC_HOST) — see the certificate guide.
It says "waiting for this group to begin" after I pick a language
Either the stream is still starting (a few seconds), or the langs budget is used up across all private groups. The language starts as soon as another one closes. Raise the cap if this is routine — and remember it raises the ceiling on the bill by the same amount.
Someone can't speak in the group
Speaking needs the microphone, which browsers only allow on a secure address — which the group already is. Check the phone gave the browser microphone permission (Settings → browser → Microphone), and that they are using earbuds or headphones, or their own phone's speaker will feed the translation back into the group.
My group vanished while we were still talking
Most likely the creator's phone dropped off for more than two minutes (locked and lost WiFi, wandered out of range), or the group hit its ttl. The creator's phone reconnecting within the two minutes keeps the group; beyond that, start a new one — it takes ten seconds. If the lifetime keeps biting, raise ttl.

Something not covered here? Write to support@lithos.community with what the phone said and what the operator page said, and we'll sort it out.