# Exposing LiveKit status in site settings serializer

**URL:** https://meta.discourse.org/t/exposing-livekit-status-in-site-settings-serializer/411428
**Category:** Support
**Tags:** voice
**Created:** [1 september 2026 om 23:23 UTC](https://meta.discourse.org/t/exposing-livekit-status-in-site-settings-serializer/411428 "2026-09-01T23:23:01Z")
**Posts on this page:** 13
**Page:** 1

<div class="post-metadata">

### Author: ![nicolsdennis](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/nicolsdennis/32/545883_2.png) [@nicolsdennis](https://meta.discourse.org/u/nicolsdennis)
#### Post date: [1 september 2026 om 23:23 UTC](https://meta.discourse.org/t/exposing-livekit-status-in-site-settings-serializer/411428/1 "2026-09-01T23:23:01Z")

</div>

@Falco Is it possible to expose a public check in the site settings/serializer for whether LiveKit is configured, alongside voice\_enabled?

Today voice\_enabled is client-exposed, but there’s no public signal for whether a site can serve LiveKit. The only LiveKit-related site attribute, voice\_livekit\_per\_room\_available, is scoped to the room-form checkbox, so it returns false under the all\_rooms policy and can’t be used to answer “does this site do LiveKit at all”.

RoomSerializer#expected\_transport covers the per-room case nicely, but that requires fetching rooms first, and it comes back empty when voice\_public\_access is off, even on a site where LiveKit is fully configured.

Would something like this be acceptable? It’s derived from existing state, exposes no credentials or policy detail, and needs no new endpoint.

It would go in plugins/voice/plugin.rb, after the voice\_livekit\_per\_room\_available block and just before the Voice::DefaultRoomSeeder.ensure! line:

`# Public, credential-free signal that the site can serve LiveKit at all.`  
`add_to_serializer(:site, :voice_livekit_available) do`  
` Voice::Livekit.configured? && SiteSetting.voice_livekit_room_policy != "disabled"`  
`end`

---

<div class="post-metadata">

### Author: ![nicolsdennis](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/nicolsdennis/32/545883_2.png) [@nicolsdennis](https://meta.discourse.org/u/nicolsdennis)
#### Post date: [2 september 2026 om 08:49 UTC](https://meta.discourse.org/t/exposing-livekit-status-in-site-settings-serializer/411428/2 "2026-09-02T08:49:31Z")

</div>

voice\_enabled isn’t reachable from the JSON API at all: /site.json carries no site\_settings key. So the only public signal that voice is running on a site is the presence of voice\_assets\_path.

What I’m asking for is two public, credential-free booleans so a client can decide whether to surface voice before fetching any rooms. Both are derived from existing state and need no new endpoint, in plugins/voice/plugin.rb:

At line 141, above voice\_public\_access:

```ruby
#Public, credential-free signals for API clients that voice is enabled.

add_to_serializer(:site, :voice_available) { SiteSetting.voice_enabled }

```

At line 152, above voice\_livekit\_per\_room\_available:

```ruby
# Whether joins can use LiveKit at all. A bare yes/no: no URL, key or
# policy value. The per-room attribute below only gates the room form's
# SFU checkbox, and reads false under the all_rooms policy.

  add_to_serializer(:site, :voice_livekit_available) do

    Voice::Livekit.configured? && SiteSetting.voice_livekit_room_policy != "disabled"

  end

```

This exposes nothing new: expected\_transport is an ungated attribute on RoomSerializer (line 30, defined at 150) and rooms#index skips login (rooms\_controller.rb:18), so “livekit” / “mesh” is already anonymously readable per room. This just answers it without a room fetch that may come back empty.

---

<div class="post-metadata">

### Author: ![david](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/david/32/157490_2.png) [@david](https://meta.discourse.org/u/david)
#### Post date: [2 september 2026 om 08:54 UTC](https://meta.discourse.org/t/exposing-livekit-status-in-site-settings-serializer/411428/3 "2026-09-02T08:54:59Z")

</div>

Please don’t mention team members in-bulk like that (I edited the mentions out).

It may help if you describe what your end goal is for this extra information. It’s hard to answer a feature-request without any justification for what you’ll be using the information for.

---

<div class="post-metadata">

### Author: ![nicolsdennis](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/nicolsdennis/32/545883_2.png) [@nicolsdennis](https://meta.discourse.org/u/nicolsdennis)
#### Post date: [2 september 2026 om 09:58 UTC](https://meta.discourse.org/t/exposing-livekit-status-in-site-settings-serializer/411428/4 "2026-09-02T09:58:12Z")

</div>

Apologies I asked a question on an announcement and I was split to support, which left me unaware of who to speak to since this is a feature request than troubleshooting, after reviewing for past 5hrs I tagged the members from the core commit/merge of voice.

However to add some context. I have an application that acts as a multi-client for Discourse communities, each configured differently, so at boot it builds the navigation for whichever site the user is on. Chat appears if chat is enabled, and I’d like voice to appear if voice is enabled and actually joinable from the app.

The app joins over LiveKit and can’t do mesh, so on a mesh site I want to leave voice out of the navigation entirely rather than show rooms that will fail to connect and make it look like the app is broken.

So the flow is: read site info once at boot, decide whether voice belongs in the app for that site, then use `expected_transport` per room once the user opens it. The two booleans are just the first step, and without them I’m either showing a feature that can’t work or hiding one that can.

Alternatively I can place “Not Available on this Forum” in a global alert within the application regardless of being enabled but this seemed like the better approach so I’ve pinpointed the entry point and gave the code and comments.

---

<div class="post-metadata">

### Author: ![pmusaraj](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pmusaraj/32/119489_2.png) [@pmusaraj](https://meta.discourse.org/u/pmusaraj)
#### Post date: [2 september 2026 om 12:30 UTC](https://meta.discourse.org/t/exposing-livekit-status-in-site-settings-serializer/411428/5 "2026-09-02T12:30:06Z")

</div>

> [@nicolsdennis](#):
>
> The app joins over LiveKit and can’t do mesh, so on a mesh site I want to leave voice out of the navigation entirely rather than show rooms that will fail to connect and make it look like the app is broken.

Thanks for the explanation! The request makes sense.

The voice plugin is new and in an experimental state. It will likely go through changes in the next few weeks and months. Especially internal changes. We are open to exposing this information in some fashion, but can’t be sure yet what that form will be. It depends on how the LiveKit integration evolves.

---

<div class="post-metadata">

### Author: ![Falco](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/falco/32/179432_2.png) [@Falco](https://meta.discourse.org/u/Falco)
#### Post date: [2 september 2026 om 12:38 UTC](https://meta.discourse.org/t/exposing-livekit-status-in-site-settings-serializer/411428/6 "2026-09-02T12:38:24Z")

</div>

> [@nicolsdennis](#):
>
> after reviewing for past 5hrs I tagged the members from the core commit/merge of voice.

If you think 5h is too much to wait, you may be new to the concept of async comms in forums. Welcome!

> [@nicolsdennis](#):
>
> RoomSerializer#expected\_transport covers the per-room case nicely, but that requires fetching rooms first, and it comes back empty when voice\_public\_access is off, even on a site where LiveKit is fully configured.

I will investigate this and come up with something we can use.

---

<div class="post-metadata">

### Author: ![nicolsdennis](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/nicolsdennis/32/545883_2.png) [@nicolsdennis](https://meta.discourse.org/u/nicolsdennis)
#### Post date: [2 september 2026 om 12:59 UTC](https://meta.discourse.org/t/exposing-livekit-status-in-site-settings-serializer/411428/7 "2026-09-02T12:59:12Z")

</div>

> [@Falco](#):
>
> If you think 5h is too much to wait, you may be new to the concept of async comms in forums. Welcome!
> 
> nicolsdennis:

I think you misunderstood, I was up from 1am to 5am reviewing what was done and the merges that’s how i found the team members i originally tagged. Not that i’m waiting on a reply for 5hrs. The app already submitted for review and it’s utilizing the default system I already have.

> [@pmusaraj](#):
>
> The voice plugin is new and in an experimental state. It will likely go through changes in the next few weeks and months. Especially internal changes. We are open to exposing this information in some fashion, but can’t be sure yet what that form will be. It depends on how the LiveKit integration evolves.

That’s fine by me, take as much time as needed. I’ve done my testing over a period of 6 months, took some fine tuning for scaling.

---

<div class="post-metadata">

### Author: ![Falco](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/falco/32/179432_2.png) [@Falco](https://meta.discourse.org/u/Falco)
#### Post date: [3 september 2026 om 14:43 UTC](https://meta.discourse.org/t/exposing-livekit-status-in-site-settings-serializer/411428/8 "2026-09-03T14:43:14Z")

</div>

> [@nicolsdennis](#):
>
> RoomSerializer#expected\_transport covers the per-room case nicely, but that requires fetching rooms first

Actually you were right on the spot there. The official API is exactly doing a call to and parsing it like this

```bash
curl https://meta.discourse.org/voice/rooms.json -s | jq '.rooms[] | {name: .name, transport: .expected_transport}'

```

Which will give you the peer room transport.

> [@nicolsdennis](#):
>
> it comes back empty when voice\_public\_access is off

`voice_public_access` is not an existing setting. What are you talking about?

Of course, you want to use auth on the API call to rooms.json to be able to fetch rooms only the current user have access to.

---

<div class="post-metadata">

### Author: ![nicolsdennis](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/nicolsdennis/32/545883_2.png) [@nicolsdennis](https://meta.discourse.org/u/nicolsdennis)
#### Post date: [3 september 2026 om 15:05 UTC](https://meta.discourse.org/t/exposing-livekit-status-in-site-settings-serializer/411428/9 "2026-09-03T15:05:14Z")

</div>

I was looking at plugin.rb line 144, where it’s added to the site serializer, backed by Guardian#voice\_public\_access? in lib/voice/guardian\_extension.rb line 16. I read it as a setting when it isn’t one, so that’s my error.

And thanks for the rooms.json pointer, the authenticated call with expected\_transport is what I was missing.

All I’m after is whether the site can serve LiveKit at all, in the site payload. Can room transport can tell me that: available\_for? returns room.livekit\_enabled under per\_room (lib/voice/livekit.rb line 26), and expected\_transport returns the pin first (room\_serializer.rb line 150), including after a mesh fallback (rooms\_controller.rb line 169).

---

<div class="post-metadata">

### Author: ![nicolsdennis](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/nicolsdennis/32/545883_2.png) [@nicolsdennis](https://meta.discourse.org/u/nicolsdennis)
#### Post date: [3 september 2026 om 15:23 UTC](https://meta.discourse.org/t/exposing-livekit-status-in-site-settings-serializer/411428/10 "2026-09-03T15:23:42Z")

</div>

@Falco I’ll test further on my local instance.

A separate question Is voice\_allowed\_groups exposed to clients anywhere, and is expected\_transport the intended way to tell LiveKit from mesh per room in a list? I’d want to hide mesh rooms and show only LiveKit ones where available, I don’t see how to separate them.

---

<div class="post-metadata">

### Author: ![Falco](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/falco/32/179432_2.png) [@Falco](https://meta.discourse.org/u/Falco)
#### Post date: [3 september 2026 om 16:15 UTC](https://meta.discourse.org/t/exposing-livekit-status-in-site-settings-serializer/411428/11 "2026-09-03T16:15:39Z")

</div>

> [@nicolsdennis](#):
>
> A separate question Is voice\_allowed\_groups exposed to clients anywhere

No. Exposing that would be borderline information disclosure. Only the current user needs to know about his own permissions.

> [@nicolsdennis](#):
>
> is expected\_transport the intended way to tell LiveKit from mesh per room in a list?

Yes, 100%.

> [@nicolsdennis](#):
>
> I’d want to hide mesh rooms and show only LiveKit ones where available, I don’t see how to separate them.

Use `expected_transport`.

---

<div class="post-metadata">

### Author: ![nicolsdennis](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/nicolsdennis/32/545883_2.png) [@nicolsdennis](https://meta.discourse.org/u/nicolsdennis)
#### Post date: [3 september 2026 om 16:41 UTC](https://meta.discourse.org/t/exposing-livekit-status-in-site-settings-serializer/411428/12 "2026-09-03T16:41:23Z")

</div>

Okay, thanks much for the assitance.

---

<div class="post-metadata">

### Author: ![nicolsdennis](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/nicolsdennis/32/545883_2.png) [@nicolsdennis](https://meta.discourse.org/u/nicolsdennis)
#### Post date: [4 september 2026 om 13:25 UTC](https://meta.discourse.org/t/exposing-livekit-status-in-site-settings-serializer/411428/13 "2026-09-04T13:25:30Z")

</div>

> [@pmusaraj](#):
>
> It depends on how the LiveKit integration evolves.

> [@Falco](#):
>
> Yes, 100%.
> 
> nicolsdennis:

This is what I’ve done [A Social Mobile & Desktop Client for Communities (2) - #30 by nicolsdennis](https://meta.discourse.org/t/a-social-mobile-desktop-client-for-communities-2/408132/30)
