On the first room creation, when the authentication redirection takes
place, the iframe wasn't properly messaging the parent.
Fixed it. Send the room data in any of the two methods to acquire it.
Actually, the code when gathering data through the callback endpoint is
a bit dirty.
Improve UX by adding a delay before showing tooltips in the lateral menu.
Users often hover from bottom to top, causing tooltips to overlap other
options too quickly.
Use a totally different strategy, which hopefully works in prod env.
Actually broadcast channel cannot be shared between two different
browsing context, even on a same domain, an iFrame and a pop up
cannot communicate.
Moreover, in an iFrame session cookie are unavailable.
Rely on a newly created backend endpoint to pass room data.
Necessary in cross browser context situation, where we need to
pass data of a room newly created between two different windows.
This happens in Calendar integration.
Enhanced the FaceLandmarksProcessor to include
a new 'french' effect, allowing users to add
a beret image to detected faces. Updated the
EffectsConfiguration component to toggle this
effect and modified localization files to
reflect the change from 'mustache' to 'french'.
Added functionality to display mustache effects
on detected faces. Enhanced the EffectsConfiguration
component to toggle these effects and updated
localization files for this effects.
Added functionality to draw glasses on detected
faces by calculating eye positions and scaling
the glasses image accordingly. Initialized glasses
image in the constructor for improved visual
effects during face tracking.
Switch from insanely-fast-whisper to WhisperX for transcription services,
gaining word-level granularity not available with FlashAttention in previous
API. Whisper was packaged in FastAPI image with basic diarization and
speaker-segment association capabilities.
Implementation prioritized speed to market over testing. Future iterations
will enhance diarization quality and add proper test coverage. API consumers
should expect behavioral differences and new capabilities.
This change allows the marketing service timeout to be easily adjusted
via an environment variable, eliminating the need for a new software release.
Additionally, the update makes the code more explicit and easier to maintain.
Improves sendData reliability by preventing execution when the room
doesn’t exist.
This change addresses errors in staging and production where waiting
participants arrive before the room owner creates the room.
In remote environments, the LiveKit Python SDK doesn’t return a clean
Twirp error when the room is missing; instead of a proper "server unknown"
response, it raises a ContentTypeError, as if the LiveKit server weren’t
responding with a JSON payload, even though the code specifies otherwise.
While the issue cannot be reproduced locally,
this should help mitigate production errors.
Part of a broader effort to enhance data transmission reliability.
Importantly, a participant requesting entry to a room before the owner
arrives should not be considered an exception.
Invert operation sequence to first notify people in room before setting
participant in cache. Fixes infinite loop issue caused by 3s cache timeout
for waiting participants when requests take too long. Problem only occurred
when notifications were delayed, as faster notification delivery masked the
race condition.
Updated styling system to implement the official French font used across all
La Suite products. This enhances brand consistency and improves the visual
identity alignment with other government digital services.
Created modal that appears when users fail to share their entire screen. Also
added documentation helper that explains proper screen sharing setup steps for
different operating systems and browsers.
Related to 5b1a2b20de
There are no references to the `generate_document.html` template
in the codebase. The same goes for the `INVITATION_VALIDITY_DURATION` setting,
which arrived straigt from https://github.com/suitenumerique/docs
WeasyPrint is (I believe) not used in the project, so it is a ghost dependency.
Fixed two HIGH severity vulnerabilities in libxslt:
- CVE-2024-55549: Use-After-Free in libxslt (xsltGetInheritedNsList)
- CVE-2025-24855: Use-After-Free in libxslt numbers.c
The image was manually updated as no more recent unprivileged nginx-based
images were available. This addresses the security scan failures from Trivy.
Revamp README to be more engaging and informative.
Goal: Foster a true open-source spirit by making it easier for
contributors to engage, interact, and contribute.
Heavily inspired by PostHog's excellent README.
Upgraded libxml2 from version 2.12.7-r1 to 2.12.7-r2 to address
a HIGH severity NULL Pointer Dereference vulnerability. This security update
prevents potential application crashes that could be triggered through
malicious XML input.
Added intuitive make commands that help new developers quickly set up
frontend dependencies and launch the entire stack. This streamlines
onboarding by providing clear entry points for common development tasks
without requiring deep knowledge of the project structure.
Added configuration to docker-compose stack allowing users to run the
frontend in production mode. This simplifies the developer onboarding,
for those wanting to run the project locally.
Specified the expected platform in dockerize configuration to ensure
compatibility with Mac M2 architecture. This resolves build failures
experienced by developers using Apple Silicon, enabling seamless
development across different hardware.
Add a clear explanatory text about the project's opensource nature.
This provides better context for users while maintaining transparency
about the software license.
Created a proper terms of service page within the application to replace
external doc page redirects. Implemented based on Sophie's accessibility
requirements to improve user experience for all users regardless
of ability.
Created a proper accessibility page within the application to replace external
doc page redirects. Implemented based on Sophie's accessibility requirements
to improve user experience for all users regardless of ability.
Created a proper legal notice page within the application to replace
external doc page redirects. Implemented based on Sophie's
accessibility requirements to improve user experience for all users
regardless of ability.
Added a new style variant to the link primitive component that
visually highlights technical links specifically within legal notices.
This improves clarity and helps users distinguish different link types
in legal documentation.
Override LiveKit Docker image to include nip.io Certificate Authority for
development environment. Addresses issue where LiveKit webhook calls fail in
dev mode due to unknown CA. Custom image places certificate in appropriate
location since LiveKit chart lacks volume mounting options for CA certs or
webhook SSL disabling capabilities.
Discussed with @rouja.
Enable LiveKit webhook feature to notify backend when events occur in rooms.
Configure LiveKit to call our endpoint whenever events are triggered,
providing real-time updates on room activities. Refer to LiveKit
documentation or LiveKitWebhookEventType enum for complete list of available
events.
This commit is not functionnal, LiveKit fails verifying our backend's
certificate. It will be fixed in the upcoming commits.
Add new endpoint to access the event-handler matching service. Route is
protected by LiveKit authentication, handle at the service level.
Enables webhook event processing through standardized API.
Create new service that matches received events with their appropriate
handlers. Provides centralized system for event routing and processing
across the application.
If an event has no handler, it would be ignored.
Implement new lobby service method to clear all participant entries from cache.
Lays foundation for upcoming feature where participant permissions reset when
meetings end. Currently introduces only the cache clearing functionality;
event handling for meeting conclusion will be implemented in future commits
Fix regression caused by competing styling methods in Box component. Remove
duplicate position properties and standardize on simple div with css-in-js
approach to prevent style conflicts and unexpected layout behavior.
Implement text truncation for excessively long usernames in waiting
participant list items to prevent layout overflow and maintain consistent UI
appearance.
Remove group action buttons for accept/deny all participants as they were not
included in the designer's mockups. Functionality may be reintroduced in a
future iteration based on user feedback.
Not necessary for this v1
Add adaptive content to existing notification that displays quick approval
action for the first 10 seconds when new participants request entry. Makes
room access management more efficient without requiring admin to open the
participant panel.
This approach could be apply to the two first participants waiting.
Let's discuss it with the designer.
Add new usePrevious utility hook to track previous values in functional
components. Enables comparing current and previous prop/state values across
renders for improved state management.
Correct throttling configuration for request_entry endpoint from hours to
minutes. Previous setting of 150 requests per hour was insufficient as
participants query approximately once per second while in the lobby.
Replace current red with higher contrast variant when used as background with
white text to meet accessibility contrast requirements. Improves readability
for all users.
Update the menu rendering to an earlier breakpoint due to added admin controls
taking up more space. Temporary adjustment until a more comprehensive layout
enhancement is implemented.
Change the "more options" button layout to horizontal orientation following
patterns used in Jitsi and Whereby. Improves discoverability and makes the
button's purpose more apparent to users.
Update switch component following accessibility consultant recommendations:
make indicator outlined instead of filled when not selected and add checkmark
when selected. Changes align with DSFR guidelines to improve state visibility.
Add aria-hidden="true" attribute to the "site under construction" banner icon
to prevent it from being announced by screen readers. Improves accessibility
by avoiding unnecessary and potentially confusing vocalization
Change footer text from "Accessibility: audit in progress" to "Accessibility:
non-compliant" to accurately reflect current status until formal audit is
completed. Provides more transparent information about accessibility
compliance.
Adjust background color of emoji hover state to ensure minimum visual
contrast ratio as recommended by accessibility consultant.
Change ensures compliance with RGAA accessibility standards.
Add informational message suggesting authentication for users waiting in
lobby without being logged in. Highlight that logging in could grant
immediate access without admin approval when rooms have trusted
access level enabled.
Update admin panel interface to include the newly introduced trusted
user access level option alongside existing public and restricted settings.
Allows room administrators to select this intermediate permission level
through the frontend configuration panel.
Introduce new intermediate access level between public and restricted that
allows authenticated users to join rooms without admin approval. Not making
this the default level yet as current 12hr sessions would create painful
user experience for accessing rooms. Will reconsider default settings after
improving session management.
This access level definition may evolve to become stricter in the future,
potentially limiting access to authenticated users who share the same
organization as the room admin.
Replace excessive mocking with more realistic test scenarios to better
reflect actual code execution. Improves debuggability while maintaining
thorough test coverage.
Deactivate inherited user listing capability that allows authenticated users
to retrieve all application users in JSON format. This potentially unsecure
endpoint exposes user database to scraping and isn't currently used in the
application.
Implement security flag to disable access until properly refactored for
upcoming invitation feature. Will revisit and adapt endpoint behavior when
developing user invitation functionality.
Change entry text to interrogative form to make it sound more polite and
welcoming. Improves tone and friendliness of the user interface through
more considerate language.
Add comprehensive validation for metadata that can be input by users with
LiveKit access tokens. Handle all user-controlled metadata with extra care,
implementing strict checks to prevent injection attacks or other security
issues from malicious input.
Implement regex validation for HSL color format in notification metadata.
Ensures only properly formatted color values are accepted, preventing
potential injection or rendering issues from malformed color strings.
Strengthen decodeNotificationDataReceived function with additional validation
to properly handle malicious input. Ensures application security when
processing potentially dangerous notification data from untrusted sources.
Redis was made a required dependency for running project tests. Update CI
environment to include Redis instance as tests now depend on it for proper
execution. Affects all backend test suites.
This dependency was intorduced by the lobby service.
Implement interface allowing room creators to configure access settings,
with options to set rooms as either public or restricted. Provides users
with control over who can join their rooms.
Introduce new dedicated side panel for room administration, providing
centralized interface for admins to manage room settings and participants.
Content will be added in the upcoming commits.
Add special non-closing notifications for waiting participants that remain
visible until all have been reviewed. Implement complementary system alongside
existing toaster notifications.
Designed with accessibility in mind but would benefit from expert review.
Current UX provides good foundation with quick actions planned for v2.
Add raw loading spinner component from react-aria library to handle
loading states. Will refine styling and appearance after receiving design
review feedback.
Implement list showing waiting participants for admins already in the room.
Initial fetch on render, then stops polling if empty until LiveKit emits event
for new arrivals. Uses long polling with configurable timeouts to prevent UI
flicker. Focus on UX implementation with responsive layout issues remaining
for long participant names.
Update Join component to integrate with the newly introduced lobby system.
Current implementation has functional UX but UI elements and copywriting
still need refinement and will be polished in upcoming commits.
Implement lobby service using cache as LiveKit doesn't natively support
secure lobby functionality. Their teams recommended to create our own
system in our app's backend.
The lobby system is totally independant of the DRF session IDs,
making the request_entry endpoint authentication agnostic.
This decoupling prevents future DRF changes from breaking lobby functionality
and makes participant tracking more explicit.
Security audit is needed as current LiveKit tokens have excessive privileges
for unprivileged users. I'll offer more option ASAP for the admin to control
participant privileges.
Race condition handling also requires improvements, but should not be critical
at this point.
A great enhancement, would be to add a webhook, notifying the backend when the
room is closed, to reset cache.
This commit makes redis a prerequesite to run the suite of tests. The readme
and CI will be updated in dedicated commits.
Extract serialization logic for LiveKit server connection data to make it
reusable across endpoints. Function naming will be improved in future
refactoring when utility functions are moved to a proper service.
Replace unused is_public boolean field with access_level to allow for more
granular control. Initially maintains public/restricted functionality while
enabling future addition of "trusted" access level.
LiveKit uses aiohttp which relies on the ssl module under the hood.
Set certificate file using an env variable, similar to @rouja's fix
for the request module.
This tweak applies only in the dev environment.
Update CI environment to use the same Python version as our Docker image.
Issue surfaced when upgrading IPython to v9, which requires Python 11.
Ensures consistent runtime behavior between CI tests and production.
Add data attributes to important buttons in the frontend to enable tracking
through PostHog actions. Allows measurement of user interaction with key
features to inform future product decisions.
Add optional email collection step for anonymous users submitting survey
responses. Store email in new "unsafe_email" property on PostHog user
profile to enable follow-up troubleshooting while maintaining anonymity.
Addresses inability to contact users reporting issues without accounts.
Fix logout functionality that was failing in 2 out of 3 scenarios where
support and analytics sessions weren't properly closed. Prevents bugs and
behavioral issues when enabling feature flags or advanced PostHog features.
Increase message notification size to improve text readability when
notifications appear, enhancing user experience by making content more
visible at a glance.
Add link to technical notice for our videoconference product describing
network engineering details, required ports, and IP addresses that need to be
allowed in client systems. Helps users properly configure their environments.
Add validation for emoji received through notifications to ensure
participants cannot send forbidden emoji characters. Improves security
by filtering potentially problematic content before display.
Replace invalid session/end endpoint with correct logout endpoint in Keycloak
configuration. Fixes broken logout functionality that prevented developers
from properly signing out of the application during development.
Tilt live updates generate a new image for each change, ending up storing
a lot of images when you are really developing with Tilt.
I have not found a built-in way of cleaning old images from Tilt documentation,
I create a utility doing the dirty work.
The notifications namespace was being lazy-loaded when the first notification
appeared, causing a screen flicker during translation loading. Now preloading
the namespace during i18n initialization to ensure smooth rendering.
Implement a new reactions system allowing users
to send quick emoji responses during video calls.
This feature is present in most visio softwares.
Particulary this commit:
- Add ReactionsButton to control bar with emoji selection
- Support floating emoji animations
This feature is far from perfect. Still not working on Safari.
Also, we should display this warning when user share the current
opened window. Minor enhancement, I don't have time currently
to prioritize these enhancements.
Visual regression was introduced probably by a change on button style.
As this button is quite different than the usual one, remove its inheritance
from the primitive ones.
Users requested that their raised hands be lowered automatically if they become
the active speaker. This change ensures a more natural experience during
discussions, preventing user from forgetting to lower their hand while speaking.
It includes a consumer project which is simply a demo app. The sdk
project includes the first version of the SDK, with a light React
implementation. The first version lays down the foundations of
the iframe sdk framework. The npm package logic is also already
ready to be published.
The create room button is a dedicated route. There is also a bit of
logic implied in this commit, including the BroadcastChannel.
The router has been updated with a /sdk negation in order to avoid
including support and react query debug tool in the iframe.
When displayed in an iframe, not being logged-in causes a redirection
to the home page. Which is not what we want with the SDK integration.
We just want to stay on the same page.
Following user feedback about infinite loops risks, add warning overlay
when users attempt to share their entire screen. The warning explains
the risk and suggests sharing a specific tab instead, providing options
to stop sharing or dismiss the warning while respecting user preferences
for future sessions.
Added temporary root privileges to update OpenSSL libraries. Upgrades libssl3
and libcrypto3 to 3.3.3-r0 to fix HIGH severity vulnerability. Properly
switches back to nginx user after updates. Maintains unprivileged execution
while addressing security concern affecting RFC7250 Raw Public Keys
authentication.
Security: CVE-2024-12797
When loading notification settings from localStorage,
keep user preferences for existing notification types while adding
new notification types with default values.
If a notification type is removed, make sure to get rid of it.
My initial implementation wasn't future proof.
Introduce ToastDuration enum to replace magic numbers for notification
timeouts. Added semantic duration constants for different notification types
(alerts, messages, join/leave events). Improves maintainability and
consistency across toast implementations.
Users frequently miss chat messages due to discrete visual indicators.
Implemented toast notifications showing sender name and message preview to
improve visibility. Added message tracking and auto-dismiss when chat panel
opens.
Remove the warning in handleDataReceived function, it was triggered by
chat message events.
The participant's name in the query key prevented proper cache invalidation
when renamed. Since name changes don't affect query data, removed this
dependency.
On hover, based on participant's type (remove/local) offer an
appropriate action. Either applying effects on the local participant
video or muting the remote participant.
This is a huge enhancement in term of UX, nobody was finding these two
controls in the current menus, and though the features were not
implemented.
Inspired by GMeet. Make central actions available on a participant
tile when a user hover it.
This new interactive zone will be extended with more actions and
controls.
useSyncAfterDelay allows to enable loading indicators only if the
loading takes more than a specific time. It prevent blinking
effect when the loading time is nearly instant.
Some users have ad-blockers or privacy extensions that prevent the Crisp chat
widget script from loading properly. This was causing the support toggle to
still display in rooms, but clicking it had no effect since Crisp was blocked.
This ensures users don't see an inactive support button when their browser
is blocking Crisp functionality.
BackgroundBlurCustomProcessor is renamed to BackgroundCustomProcessor in
order to reflect the fact that is now handles virtual backgrounds too.
BackgroundBlurFactory is also renamed to BackgroundProcessorFactory.
The processor serialization handling has also been updated in order
to support various options, also if persisted in local storage.
This is a wrapper around track-processor-js virtual background
processor. This is needed in order to be used in a generic way
in our code between firefox processors.
I introduced a bug while moving the border radius css style to the
parent element of the video.
On safari, the video element wasn't rounded anymore.
Fix this! Please note our approach should be refactored, nit-picking,
but there are few pixels leaking from the black background on the
video corner.
Disable Picture-In-Picture option for browsers that support it,
to avoid having the option appearing on the video element.
It's not appropriate.
Actually, I am not sure we should disable remote playback ones,
feel free to challenge it.
On unsupported browser showing this option whitout offering the
blur effects to the user would be quite frustrating.
At the moment, safari user cannot blur their background.
Also, avoid offering the option on mobile which are really
cpu-constrained devices.
We need to have an agnostic component to apply effects on any video
track, enters EffectsConfiguration. It takes in input the video
track and outputs the processor applied. This is gonna be used in
order to use the same component on the pre join screen and the in
room customization side panel.
Prevents runtime error when Crisp chat hasn't initialized before component mount
Previously caused crash since we assumed $crisp global was always available.
- Always enable camera/mic by default (like Google Meet)
- Fix video state transitions and add visual feedback
- Simplify form using React Aria components
- Reduce shadow intensity for better visual balance
Each menu item is now a standalone component, improving:
- Code organization & reusability
- Maintainability by reducing OptionsMenuItems complexity
This breaks down large components.
Added an option allowing users to trigger the fullscreen mode while on desktop.
Heavily inspired by the PR #279 from @sylvinus.
Yet, this option allow user to enable/disable the fullscreen mode on the whole
ui, in the next iteration I'll add the same feature but for a given video track.
This is on purpose that the feature is available on desktop only.
The hook code has been partially written by Claude and inspired by @sylvinus
first suggestion.
When using nip.io for local development DNS mapping (which allows hostname-based
access to localhost), we need to explicitly allow these domains in Vite's server
configuration to prevent host security violations.
This check should be ignored when using https.
Implemented collapsible advanced options to maintain usability on narrow screens
following GMeet's UX pattern. Dialog and popover components were chosen
based on GMeet choices, though this introduces potential accessibility concerns
that should be addressed in future iterations.
Current implementation uses JS for breakpoint handling due to challenges with
Panda CSS's pure CSS approach. This workaround was necessary to resolve a
persistent issue where the popover remained open after window expansion beyond
750px, even after the lateral menu trigger was removed from view.
Technical debt note: Code needs refinement, particularly around breakpoint
management and component architecture. Prioritized shipping over perfection to
meet immediate responsive design needs.
We want this screen to have a better ux, the join button was invisible on
some small screen sizes, also we want to align the style of this screen with
the ui of the video conference previously made.
Inspired by GMeet. Actually, these menus are horrible to work with.
This is clearly some technical debt. I fixed the styles, but not the
code, we should refactor them to make easy to chose between two
variant, a light and a dark one.
Updates build configuration to support new major version.
This might introduce some breaking changes.
I've read their migration guide, everything seems okay.
Key prop was incorrectly passed down as a regular prop to ParticipantListItem
instead of being used at the array mapping level. Key is a special React prop
for list rendering and cannot be accessed as a component prop.
We cannot use track-processor-js for Firefox because it uses various
approaches not compatible with Firefox. Firefox cannot run inference
on GPU, so we must use CPU, we could also not use MediaStreamTrackProcessor nor
MediaStreamTrackGenerator. So I had to make a new implementation from
the ground up, using canvas filters and CPU inferences.
Improved script portability by switching to `/usr/bin/env bash`, ensuring
better support across environments where `bash` may not be the default shell.
Avoid disabling SSL verification in development environment,
simply mount in the right folder, an extra volume, that declares
the certificate authority necessary to validate nip.io domains.
Updated deployments metadata to include configurable annotations using
`.Values.xxx.dpAnnotations`. This change supports the new approach of
storing secrets in an external Vault, allowing annotations to be added in
staging/prod to trigger refreshes when external secrets change.
Will be configured accordingly in La Suite deploiement repository.
Refactored ClusterSecretStore and ExternalSecret deployment to support
VaultWarden custom fields beyond login/password, including multi-line
values via file input. Also made the secret template name configurable
for added flexibility.
ClusterSecretStore are supposed to be cluster-wide objects, it's useless
to precise any namespace.
Previous merge of helm chart refactoring was incomplete. Currently,
linting only occurs during chart publication rather than on each PR.
This temporary solution will be improved in a future update.
Existing make command wasn't working on Mac. Fixed it, plus
refactored it in a proper script, so we can share it among
projects, as for the build kind cluster one.
External secrets are created in a dedicated namespace, to avoid
duplicating them if we spawn several LaSuite applications on the
same local stack.
Fix the following issue :
```
The workflow is not valid. .github/workflows/release-helmchart.yml
(Line: 25, Col: 12): Job 'release' depends on unknown job
'helmfile-lint'.
```
Use the common create_cluster.sh in order to improve cooperation
between teams.
Also, mount extra volume, to avoid setting ssl_verify to false,
while using request module in Python.
We have a dedicated deployment repository, also containing
the Helm chart. To avoid duplicating and maintaining twice
a chart, we decided to publish our Helm chart.
At first we tried the official chart releaser action, however,
this ended in creating a new release on Github for each chart
update, which wasn't acceptable.
Offer a standalone dev environment or a dinum specific dev
environment with ProConnect authentication.
Needed to refactor the way secrets are managed in the project,
and also re-organize the Helm chart to make it totally standalone.
Particulary useful for external wanting to run the project.
Work done by @rouja.
Submitting new users to the marketing service is currently handled
during signup and is performed only once.
This is a pragmatic first implementation, yet imperfect.
In the future, this should be improved by delegating the call to a Celery
worker or an async task.
Introduced a MarketingService protocol for typed marketing operations,
allowing easy integration of alternative services.
Implemented a Brevo wrapper following the protocol to decouple
the codebase from the sdk. These implementations are simple and pragmatic.
Feel free to refactor them.
Found this solution googling on Stack Overflow.
Without a default ordering on a model, Django raises a warning, that
pagination may yield inconsistent results.
The new endpoint requires title and content, breaking
the original implementation. This hotfix ensures staging works
immediately while I plan an LLM-based solution
for title generation.
It led to an error, with two occurrences of the form's URL being
desynchronized. Fix this minor issue, and refactor the constant
in a constant file to be shared across the app.
Enabled recording feature in production. MinIO needs to trigger a webhook
when a new recording is saved. Secret will be updated in the upcoming commits.
Updated the webhook URL to the definitive version in docs.
Jacques also updated the webhook secret for authentication
against Impress API. Not tested locally.
We want to have a specific responsive menu on mobile browsers.
It also implied to refactor a bit the way the settings modals is opened
because it could be opened from this responsive menu, so in order to achive
that a specific context has been created in order to allow its opening
from any sub component of the control bar.
We want to be able to customize the variant which those toggle uses as
well as being able to trigger an event when the toggle is pressed. This
is going to be useful to close the responsive menu after each clic as
react-aria prevent click event propgation.
According to the documentation:
Dynacast dynamically pauses video layers that are
not being consumed by any subscribers, significantly
reducing publishing CPU and bandwidth usage.
Dynacast will be enabled if SVC codecs (VP9/AV1) are used.
Multi-codec simulcast requires dynacast
My goal is to reduce CPU and bandwidth usage for clients.
Dynacast is enabled both in OpenTalk and LiveKit demo app!
Adaptive stream is a key optimization in large room.
Enabled adaptive stream to automatically manage
the quality of subscribed video tracks, optimizing
for bandwidth and CPU usage.
When video elements are visible, it adjusts
the resolution based on the size of the largest visible
element. If no video elements are visible, it
temporarily pauses the track until they are visible again.
Additionally, introduced support for custom pixel density,
which defaults to `2` for high-density screens
(devicePixelRatio ≥ 3) or `1` for standard screens.
Setting it to `screen` allows the pixel density to match
the actual screen's devicePixelRatio, optimizing video
clarity on ultra-high-definition displays.
This ensures a balance between streaming quality
and resource consumption.
This might also significantly increase the bandwidth
consumed by people streaming on high definition screens.
It needs to be battle tested.
OpenTalk uses a adaptiveStream equals true, while LiveKit
demo app uses 'screen' value. I followed OpenTalk choice,
I was scared 'screen' value creates performance issues
for user with high resolution screen in poor network conditions.
As a mandatory codec in WebRTC specifications, VP8 serves as
the baseline for compatibility, making it the default choice
in LiveKit client configuration.
There is room for optimization.
Newer codecs like VP9 offer significant efficiency gains
compared to VP8, with a 23-33% improvement in compression
efficiency. This translates to better video quality at
the same bitrate or reduced bandwidth usage for the same quality.
VP9 is supported in Safari starting from version 15.0+,
and Firefox offers partial support. However, Firefox lacks
support for VP9's Scalable Video Coding (SVC).
With SVC, participants can send a single VP9 stream
with multiple spatial or temporal layers. This allows receivers
to dynamically adjust video quality by using lower layers when
resolution or bandwidth needs to be reduced, improving
adaptability in heterogeneous network conditions.
Simulcast, by contrast, sends multiple separate streams
at different resolutions. While widely supported in VP8 and VP9,
it consumes more bandwidth compared to SVC.
The configuration added here is based on the LiveKit demo app,
which defaults to VP9 when supported. OpenTalk’s configuration
also recommends VP9.
If a browser does not support VP9, LiveKit falls back to VP8 or
other codecs as needed. Notably, LiveKit disables VP9 encoding for
Firefox due to longstanding issues, but it can still decode VP9
streams and encode VP8 for outgoing streams. This ensures
compatibility with other participants, even in mixed environments
where some browsers use VP9 and others fallback to VP8.
In theory, participants do not all need to switch to a single codec,
as both LiveKit and browsers intelligently handle codec negotiation
on a per-participant basis. This dynamic adaptation ensures seamless
communication without manual intervention.
A similar challenge with codec compatibility was raised
in Jitsi two years ago, check issue #10657.
Before any release, this needs to be battle tested
with Firefox 115 browsers.
Introduced a global state to handle user preferences related to notifications.
The first use case is sound notifications, allowing users to disable them
based on feedback.
Additionally, the sound volume is now stored globally, making it easy to
configure in the future if needed. I've lowered the volume of
the notifications to make them more discreet.
Preferences are persisted in local storage, ensuring they are retained
between meetings.
Add STORAGE_KEYS object to centralize localStorage keys,
ensuring no key overlaps by maintaining a single source
of truth for key declarations across the app.
Might be premature, as only the notification store will be persisted.
Valtio allows state persistence in local storage, which is
necessary for the notification store. In this case, I'll need
to persist a `proxyMap`—a utility provided by Valtio to create
an observable map.
However, since `proxyMap` isn't natively serializable,
I'll need to implement two custom functions: one for serialization
and another for deserialization (revival).
Regarding the file structure, I've named the file `utils/valtio`,
but this can be discussed further. The purpose of this file is
to centralize common utility functions related to Valtio
for better organization and reuse.
I found the item names unclear, so I updated them for better clarity.
I also removed the unnecessary 'lowered' item and added
a TODO comment about handling the message received notification,
which is not yet implemented in the code.
Inspired by Robin's design, I've styled a React Aria
Switch component using our DSFR theme.
This is an initial draft and isn't yet pixel-perfect compared
to Robin's design. It also hasn't been integrated into
the form inputs yet.
Rely on Posthog for a first iteration on the feature flag feature.
This is a pragmatic choice, relying on an external dependency might
not suitable on the longer term, however, compare to the maturity
of our product, this is the best trade off.
Few frontend features rely on Posthog. Posthog is not activated in
dev environment. Offer a hook that encapsulates this logic, and
return a boolean flag.
Configure dev and staging environment to use our self-deployed
models (Whisper and LLM). Secrets need to be updated btw.
Because of outscale LB bug, which timeout after 60s, we need to
connect directly to the svc.
Feedback from one of our users.
I forgot animation can be disabled for accessibility purpose.
Fix it by bypassing the animation if reduce motion is activated.
Oopsie, mybad, I learnt something.
Declare Marianne font. Not sure of my configuration, lmk if
my configuration feel wrong @nvasse @manuhabitela.
It's a requirement in the public sector.
Based on Florian and Stéphanie feedbacks, add the 'Marianne' logo,
and a beta tag on our visio's logo.
I've slightly updated the header. Its responsive is broken in certain
situations.
While hot reloading the stack, I got an error, Crisp not being
defined at the time of the component rendering. Prevent such issue.
I am not 100% sure this commit is useful, WDYT?
Discussed IRL with Robin and Natan. Previous iteration wasn't
appropriated for a visioconference tool.
Try a trade off between nice colors and DSFR. We will probably
continue to iterate on these.
Got an unexpected error while instantiating the openai client
since I installed sentry deps. I've upgraded openai version
without digging much, and it worked again.
Draft a piece of code to try the feature in staging. I'll consolidate this
implementation ASAP, as soon we have a first implementation functional.
What's missing?
- when owners are multiple
- retry when the backend cannot reach the summary service
- factorize the key oneliner, duplicated from the egress service
- optimize SQL query
- unit tests
Share the same project as the microservice one. Will see in the future
if we need a separate sentry account for the backend. Good enough
at this project stage.
This is written in a rush, boostrap the real logic with celery
worker to process meeting recording.
Lack of unit tests is critical, I am not proud of a it. I am
totally in a hurry for the demo. Not sure we will actually keep
this microservice.
Update values for dev and staging environment to enable
recording-related endpoints. A new secret need to be created.
Production values will be added in an upcoming commit.
This commit solves few issues:
- sharing the relevant certificates with minio so when triggering the webhook
notification, the minio pod can verify our backend domain certificates.
- making sure everything spawn in the right namespace (LiveKit and the Egress)
without relying on a dirty fix in the make start-tilt.
all these fixes were made by @rouja, I don't fully understand them yet.
He simplified the stack, removing two Kind nodes to make it lightweight.
thx @rouja.
Quick fix, not optimal. Removed a useless breaking point IMO.
I won't spend too much time on the Header component, I'll
introduce new features needing a heavy layout update.
Needed a trade off between xs and sm breaking points.
Introduce xsm, I am not very satisfied with this naming.
We might refactor xs in xss. Not urgent.
Refactored the feedback alert button into a more discreet and polished banner.
The banner provides additional context about Visio being under construction.
Also updated the link to the feedback form.
Previously, language detection was failing to read browser settings correctly.
Added explicit detection order to ensure localStorage preferences are checked
before falling back to browser language.
I've created a beta form, allowing interested visitors to
register to be a beta user.
This form is yet created with Grist, could be enhance. I'll
investigate using PostHog.
Avoided installing a dependency for such small piece of code.
I've implemented a naive component, which allow users explore
the slide presenting key feature of our app.
User experience should be ok. However, I might need to optimize
image format and loading strategy. First 'raw' iteration, gonna
optimize it in the future.
I found original to hide text decoration on hover. It felt wrong
to me, I proposed a new animation. Please feel free to rework it
or enhance it in the future.
Created a component for an intro slider to showcase app features.
Each slide will include a minimal illustration and concise descriptions.
Work In Progress, Slide logic will be added in upcomming commits.
Oooopsie while merging chat, I forgot to test horizontal scrolling.
It ended up creating a scroll issue. Fixed!
This fix might create a new issue for mobile users, I'll refactor
their layout ASAP.
Streamline user joining a room by pre-fillig name field from
their ProConnect data. Reduces friction and typos in the join flow.
This feature will be mostly used by new users. Recurrent users have
their previous choices persisted in local storage.
Request the necessary scopes from ProConnect service.
Update configurations in every environments.
Note: ask given_name and usual_name scopes to get users' info.
(these scopes should be granted by default by ProConnect when
requesting a client id client secret)
Inspired by @sampaccoud's eee2003 commit on impress, adapt the code to be more
Pythonic. Add basic test coverage for user name synchronization on login. User
name fields now update automatically at each login when new data is available.
Note: current logic doesn't handle the case where a user with existing names
logs in with missing first/last names - should we clear the names then?
Removing a field that was present in the initial form is not a valid update
operation.
Following @sampaccoud's work on impress, add new fields to handle
user names in our application.
@sampaccoud preferred having a full and short names instead of
a basic first and last ones, to follow common good practices, and
avoid having frontend formating names (from my understanding).
Please see commit eee20033 on Impress.
DINUM users face connection issues in bandwidth-constrained environments.
They cannot reach their room, the peer connection timeouts while negotiating
TURN/TLS handshake (from our current understanding).
I am not sure this issue is linked to those parameters, at least try something.
I've protected this endpoint with a feature flag, and an authentication
class, as it will be exposed on the public internet.
I've tried to keep the viewset logic as minimal as possible, I've
to ship smth and will continue iterating on this piece of code.
At some point, abstracting webhook endpoint and authentication class
might be beneficial for the project. YAGNI as of today.
A recording is savable only if it's active or stopped. In other
status (error, already saved, etc.) it won't be possible. I might
iterate on this piece of code. Let's ship it.
When a new file is uploaded to a Minio Bucket, a webhook can be
configured to notify third parties about the event. Basically,
it's a POST call with a payload providing informations on the
event that just happened.
When a recording worker will stop, it will upload its data to a Minio
bucket, which will trigger the webhook.
Try to introduce the minimalest code to parse these events, discard
them whener it's relevant, and extract the recording ID, thus we
know which recording was successfully saved to the Minio bucket.
In the longer runner, it will trigger a callback.
Addressed a `DeprecationWarning` in `RecordingFactory` related to the
`_after_postgeneration` method, which will stop saving the instance after
postgeneration hooks in the next major release. To resolve this,
`skip_postgeneration_save=True` was added to `RecordingFactory.Meta` to
avoid extraneous save calls. Alternatively, if instance saving is needed,
the save call can be moved to postgeneration hooks or by overriding
`after_postgeneration`.
Avoided unnecessary manipulation of the room name to prevent issues when
starting an egress worker. Previously, hyphens were stripped from the room
name, likely inherited from the legacy setup with Jitsi in Magnify, though
the purpose of this change is unclear and might be an undesired legacy
feature.
To ensure accurate room matching during egress worker requests, this update
removes any manipulation of the room name. This approach minimizes the risk
of errors when initiating recordings and maintains the integrity of the
original room name throughout the process.
The LiveKit egress worker interactions are proxied through the backend for
security reasons. Allowing clients to directly use tokens with sufficient
grants to start recordings could lead to misuse, enabling users to spam the
egress worker API and potentially initiate a DDOS attack on the egress
service. To prevent this, only users with room-specific privileges can
initiate recordings.
We make sure only one recording at the time can be made on a room.
The requested recording mode is stored so it can be referenced later when
the recording is saved, triggering a callback action as needed.
A feature flag was also introduced for this capability; while this is a simple
approach, a more robust system for managing feature flags could be valuable
long-term. For now, KISS (Keep It Simple, Stupid) applies.
The viewset endpoints were designed to be as straightforward as possible—
let me know if anything can be improved.
Introducing a new worker service architecture. Sorry for the long commit.
This design adheres to several key principles, primarily the Single
Responsibility Principle. Dependency Injection and composition are
prioritized over inheritance, enhancing modularity and maintainability.
Interactions between the backend and external workers are encapsulated in
classes implementing a common `WorkerService` interface. I chose Protocol
over an abstract class for agility, aligning closely with static typing
without requiring inheritance. Each `WorkerService` implementation can
independently manage recordings according to its specific requirements.
This flexibility ensures that adding a new worker service, such as for
LiveKit, can be done without any change to existing components.
Configuration management is centralized in a single `WorkerServiceConfig`
class, which loads and provides all settings for different worker
implementations, keeping configurations organized and extensible. The worker
service class itself handles accessing relevant configurations as needed,
simplifying the configuration process.
A basic dictionary in Django settings acts as a factory, responsible for
instantiating the correct worker service based on the client's request mode.
This approach aligns with Django development conventions, emphasizing
simplicity. While a full factory class with a builder pattern could provide
future flexibility, YAGNI (You Aren't Gonna Need It) suggests deferring
such complexity until it’s necessary.
At the core of this design is the worker mediator, which decouples worker
service implementations from the Django ORM and manages database state
according to worker state. The mediator is purposefully limited in
responsibility, handling only what’s essential. It doesn’t instantiate
worker services directly; instead, services are injected via composition,
allowing the mediator to manage any object conforming to the `WorkerService`
interface. This setup preserves flexibility and maintains a clear
separation of responsibilities. The factory create worker services,
the mediator runs it.
(sorry for this long commit)
Write the proper ORM code to sanitize the rows in db and avoid
existing users lose access to our app.
Existing duplicate user accounts are merged, and resource accesses
are transferred.
Add test cases for email-based user matching fallback logic:
- String comparison edge cases
- Multiple users with matching email addresses
- Invalid email format handling
Fix will follow in subsequent commit.
When OIDC providers return random values in the "sub" field instead of stable
identifiers, implement email-based user matching as fallback.
Note: Current implementation needs improvement. Tests forthcoming.
Original: @sampaccoud (ff7914f) on Impress
Handle case where user is inactive.
Previously this edge case would cause unexpected behavior.
Related to previous commit that added the test coverage.
Remove redundant wrapper method that duplicates SUB validation logic.
Already validated in parent class, following the pattern established by
@sampaccoud in People and Impress modules.
Handle case where sub value is an empty string instead of None.
Previously this edge case would cause unexpected behavior.
Related to previous commit that added the test coverage.
Add failing test for corner case when sub value is an empty string.
This edge case was discovered by @sampaccoud and was previously untested.
Fix will follow in subsequent commit.
Add missing hint to guide user entering their name while
joining a room.
I introduced this bug while merging @manuhabitela works on
the newly prejoin screen.
Manage Recording in the Django Admin. As of today, I have not enforced
a strict policy to avoid edit on recording rows or even creating new
data point directly from the admin. Will do in the future.
Implements routes to manage recordings within rooms, following the patterns
established in Impress. The viewset exposes targeted endpoints rather than
full CRUD operations, with recordings being created (soon) through
room-specific routes (e.g. room/123/start-recording).
The implementation draws from @sampaccoud's initial work and advices.
Review focus areas:
- Permission implementation choices
- Serializer design and structure
Credit: Initial work by @sampaccoud
The Recording model is introduced to track recording lifecycle within rooms,
while maintaining strict separation of access controls between rooms and
recordings.
Recordings follow the BaseAccess pattern (similar to Documents in Impress),
providing independent access control from room permissions. This ensures that
joining a room doesn't automatically grant access to previous recordings,
allowing for more flexible permission management.
The implementation was driven by TDD, particularly for the get_abilities
function, resulting in reduced nesting levels and improved readability.
The Recording model is deliberately kept minimal to serve as a foundation for
upcoming AI features while maintaining flexibility for future extensions.
I have avoided LiveKit-specific terminology for better abstraction.
Note: Room access control remains unchanged in this commit, pending future
refactor to use BaseAccess pattern (discussed IRL with @sampaccoud).
Renames a Django setting in the Resource base class to use resource-agnostic
terminology. While rooms are currently the only resource type, keeping base
class naming generic improves clarity.
Previously, the Docker Compose filename was hardcoded in _config.sh when used
through utility scripts. In recent commits, I've renamed the filename without
updating this configuration.
Oopsie, running make commands was fine, but running bin scripts
requiring compose failed.
Python module models.py raises too-many-ancestors warning, but linter
still pass, code is rated 10/10.
Inspired from @sampaccoud's commit #eee20032 on impress.
The version is now automatically guessed by Docker Compose. This
commit will fix the warning raised about the uselessness of this
setting.
from @sampaccoud
Egress is already deployed in staging. But, while
working locally on feature relying on Egress, it's not
suitable to test your development or iterate.
Especially I'll need to test the connection between the Egress
and the minio bucket in my next PR.
We faced quite a few issue while starting the whole stack.
Egress didn't want to start. Its connection with the livekit server
while the egress participant was joining the room was not successful.
The Turn part of the livekit server helm chart was activated. We needed
to update few values to in the helm configuration to enabled this turn.
Updated CoreDNS to expose Egress pod. Egress tries connecting to MinIO at
127.0.0.1, where no instance exists. Using minio.127.0.0.1.nip.io resolves
to 127.0.0.1, causing Egress to connect to itself for uploads. The CoreDNS
rewrite directs this to the Ingress IP, correctly routing to MinIO.
Inspired by Impress and @sampaccoud's work.
We use Indie Hoster’s Kubernetes objects in staging and production.
In the "dev" environment, we install the `bitnami/minio` chart to mimic
Indie Hoster’s MinIO setup.
To access the MinIO admin interface in dev, use port forwarding;
the interface runs on port 9001.
LiveKit Helm chart doesn't support namespace parameterization
like MinIO templates. Egress and server deploy to default namespace,
but frontend and backend need all components in the same namespace.
Workaround: force kubectl context to 'meet' before starting Tilt.
Future improvement needed in chart.
Issue #105 have been opened in livekit-helm repo.
Encapsulate all interactions with the layout store concerning the
side panel into a hook. This hook exposes a clear interface.
Each variable has a single responsability, with a clear naming.
Rename useWidget interaction to useSidePanel. Remove LiveKit-specific naming
as we no longer use LiveKit elements in the layout context. This change
improves clarity and reflects the current functionality of the hook.
Properly integrate chat into the sidepanel to improve UX and avoid disruptions.
Implement initial styling based on Google Meet's design, with plans for future
enhancements. Some details remain to be refined, such as preserving newline
characters in the message formatter.
This substantial commit refactors and cleans up a significant legacy component.
Chat notifications will be addressed in a separate PR.
Note: While this is a large commit, it represents a major improvement in user
experience (in my opinion).
Implement smooth animations and DOM persistence for sidepanel.
Side panel state should be kept alive, to match initial LiveKit team
intent.
Temporarily, remove chat component. Chat functionality will be absent
until next commits. It will be reintegrated in the side panel.
When a participant leaves a videoconference, remove all notifications they
authored. It's generally unnecessary to keep notifications about actions from
users who are no longer present, with few exceptions.
As we currently support only two notification types (Joined and Raised Hand),
it's appropriate to close all of them when the author leaves the room.
Changes introduced by LiveKit which deprecated some chat's options.
As we duplicated their code, let's just removed them.
They are not useful, and not in use anywhere.
Introduce a draft chat input component inspired by Google Meet design.
This component is not yet in use and requires further enhancements.
To be improved:
- Avoid sizing in pixels
- Replace hardcoded colors with theme variables
This lays the groundwork for a more interactive chat experience in the future.
Allow more flexibility in side panel behavior. Some panels, such as the chat,
require specific scrolling functionality:
- Header and footer should remain fixed
- Only chat messages should be scrollable
This change enables customization of scroll behavior for different panel types,
improving component reusability.
In object-oriented terms, the previous implementation violated the Liskov
Substitution Principle. Props between these two components (Button and Link)
were not substitutable.
This led to TypeScript errors and increased overall complexity without
significant DX gains. To address this, the LinkButton has been extracted
into a dedicated component.
Fix following warning messages :
- You have not set a value for the SECURE_HSTS_SECONDS setting.
- Your SECURE_SSL_REDIRECT setting is not set to True.
I am not a huge fan of changing the component's behavior based on
a if, but that the only way I found to have something quickly.
Actually, the push to talk feature will always only applies to the
microphone. No other devices will be concerned.
Reuse the active speaker indicator to quickly bootstrap the feature.
Some details should be improved in terms of UI. The UX is quite
decent.
Needed to support push to talk using the spacebar.
Introduce a utility hook. Will be called by the mic toggle
in the upcoming commits.
Inspired by Jitsi code.
React Query refetches stale data on window focus, which triggers
silent login attempts for logged-out users.
If user data becomes stale (after 1 hour), silent login redirects
the user to the auth domain, potentially disconnecting them during calls.
To prevent this, user data is now considered non-stale
during active sessions.
If the user logs in via another tab, a manual page
reload will be required to refresh their session.
Based on feedback from @rouja, I've updated the Helm configuration for PostHog
to use separate ingress resources for each service. Although the documentation
suggests sharing the same ingress, the services have different externalName
values, which conflicts with the use of a vhost in the ingress annotations.
This change ensures proper service redirection by aligning each service with
its own ingress.
Declare the expected support and analytics env variables
expected by the frontend for each environment. To avoid consuming
too much credits from our PostHog free tier plan.
Query API to get the App's configs.
Replacement for env variables, thus with a single image,
we can dynamically update frontend's behavior.
Code inspired by Marsha. Not sure having a single component
returning null is a good idea, to be discussed.
Inspired by Joanie.
In Frontend context, env variables are only available at build time,
not runtime. This is one of the easiest way to pass frontend dynamic
configurations while running.
This commit only exposes the view already existing.
Implement a chat feature that allows users to communicate directly with an
engineer for assistance with issues. We use Crisp for consistency, as it’s
already utilized in all other LaSuite products. Additionally, we need to
configure an environment variable in the frontend for better flexibility.
This is the initial implementation, and session handling will be refined
in future updates.
Decouple the code from the PostHog dependency by wrapping it in a custom hook
and several utility functions. This enhances code maintainability and separation
of concerns.
Fixed an issue where a setting cloned from Joanie was missing
in the Django configuration. Although its value was provided, it was
not applied due to the missing reference in the settings file.
We should use participant attributes, rather than metadata, to store hand
status (raised/lowered). However, the useParticipantInfo hook is currently
not suited for this, as it does not refresh when attributes change.
Be transparent with users: this version lacks quality and is currently
limited to Chrome, which may lead to frustration.
In addition to providing information, we should implement a method to
collect user feedback and reactions.
Simplified the logic to avoid redundancy. Removed unnecessary duplication of
eventGroups, as it's already exported from the core. My bad for the initial
complication — code is now cleaner.
Implemented using MediaPipe, which is not supported on Firefox due to
limitations outlined in issue #38 of the track-processors-js repo.
We decided to release this first version exclusively for Chrome to quickly
offer a solution to users. Future iterations will address broader compatibility.
An informational message will be added to notify users that the feature is
experimental. For now, a text label will be used in place of an icon.
Refactor side panel into a reusable component to display any interactive
content like menus, messages, participant lists, or effects. Establish it
as a core feature of the videoconference tool.
Improve extensibility and better share responsibilities. The next step is to
refactor the chat to render inside the side panel.
Increased all icons size, as they looked a bit small on screen.
Introduce a new component separator, to organize menu items
in section.
Work in progress, added the 'effects' item, which triggers no
action yet.
Recommended dependency to process video tracks, to add a virtual
background, or a blurring effect. Created and maintained by the
core LiveKit's team.
Please note, few issues are known. track-processors-js relies on
MediaPipe (by Google), which is not supported on Firefox …
Quick-win to ship a first draft.
When new secret is added to backend secret, it's not sync at the
beginning of argocd synchronisation and jobs are blocked. Theses new
annotations fix this issue.
Upgraded to livekit/components-react v2.5.4, fixing a bug in v2.5.3 that
caused repeated nesting of persistent user choices, exhausting the quota.
Thanks to Lukas for the quick fix.
PostHog's autocapture is useful, but explicit tracking ensures cleaner, more
focused data. This initial pass targets high-impact actions; we'll iterate as
needed.
Initialize Posthog script with our project's keys.
This key is public, it's not a secret.
Our data is hosted in Europe, followed Tchap integration,
which was reviewed by the ANSI.
Enhanced the share screen button by adding a tooltip and improving contrast for
better accessibility. Created a temporary icon by combining two from Remix, but
it’s bulky and will need refactoring soon.
Improved handling of the disconnect call by properly managing the returned
promise. Simplified the approach by skipping the useDisconnectButton hook.
Updated the button to display only an icon for a cleaner interface.
Ensure notification toasts are cleared when a participant disconnects,
preventing stale notifications from showing if the user quickly rejoins.
This resolves issues with duplicate or outdated notifications appearing.
Previously, I prevented clients from fetching new tokens when data is stale.
It seems totally wrong. Enabling data refresh addresses potential issues
with random user disconnections.
Please note the data refresh when stale was only disabled for people
who created the room.
While in focus, left tiles should be large enough to render
long name and still have a big enough size to get who is in the
tile. Temporary, but functional.
Due to responsiveness issues and awkward display on mobile screens.
Note: Chrome inspector's responsive mode inaccurately triggers mobile
behavior. It uses a temporary function imported from LiveKit.
Toast-related components are reusable. They follow React Aria recommendations.
The UI is heavily inspired by GMeet, we should iterate on it.
Why toast? It gives additional information and quick actions when an event
occurs in the room.
The ToastRegion design should be improved to be more extensible, to move away
from poor practices with conditional rendering.
Added initial toast display when users join, with room for further improvement.
Please read the fixme items.
Inspired by the props disableSpeakingIndicator, used the same
logic for all metadata displayed on hover on a participant's tile.
Why? I'll need to render the joining participant tile without any
metadata, so the participant see who is joining the room.
Absolutely needed some toasts to handle in app notifications,
or feedbacks. React Aria is working on it, and has released a
first beta. No component is available, only hooks.
Added user feedback for actions with explicit text indicating
URL will be copied to clipboard. Modeled after Jitsi's button
behavior for clarity and consistency in user experience.
Based on User's feedback.
Having the dialog position visually in the participant tile is
confusing for the user.
Position the dialog to be explicitly outside of a participant
tile container.
Users' feedbacks. Design is inspired from Whereby, a webinars
product. I am not a huge fan of having the indicator on the
left of the participant's name. It causes a shift of the name
when the participant unmute herself.
This should be discussed with the UX designer.
Users's feedbacks. Raised hands in participants' tiles were not
highlighted enough.
It was discussed adding a colorful border around the participant's
tile (idea inspired by Jitsi). Nonetheless, it conflicts with the
current blue border, indicating when a participant is speaking.
Until this blue border is present, it's not a great idea having a
second border indicating a new level of informations.
@sampacoud requested a yellow-ish/colorful indicator of when a
participant raised her hand, inspired by Jitsi. However, I think
yellow color should be reserved for warning or dangerous action.
I chose to use a white background around the participant's name,
to reinforce the visual indication a participant has her hand
raised, while still being discreet. It's inspired by Gmeet.
The Gmeet-inspired indicator was misleading for users,
at least those not used to GSuite products.
They didn't understand how to mute a participant.
Plus, having the button disabled for the local participant,
was creating confusion. To simplify the UX, have all
the buttons enabled is simpler to understand.
Empirical observations with a few number of users, should be
enhance and challenge in the long run.
'hash' built-in function is randomly seed by Python process.
In staging or production, our backend runs over 3 pods, thus 3
Python processes. For a given identity, it was not prompting
the same hash across all pods.
Why 'hash' is randomly seed? For security reasons, there was
a vulnerability disclosure exploiting key collision. Since Python 3.2,
'hash' is by default randomly seed.
Fixed it! Thx @jonathanperret for your help.
Height was varying when muting/unmuting the mic, so I added a minimum height to
avoid layout shift.
Proof of concept for the future UX: a raised hand would be placed on
the left side of the participant's name.
Having the mic indicator and raised hand side by side is temporary and totally
undesired (it feels super weird). I'll refactor the whole UX of the participant
tile in a dedicated PR.
Encapsulate code responsible for toggling hand,
and determining the hand state based on participant metadata.
This gonna be reused across the codebase.
Inspired from Gmeet. Add a button to lower all hands at once.
It should be quite useful for room moderator/admin.
The UX might feel strange, having this action button at the top of
the list, but I could not figure out a better layout. In terms of
UX I feel this is the best we can provide. However, the UI should
definitely be improved.
Show the raised hand waiting list, allow any participant to
lower other participants' hands.
Inspired from Gmeet. I found it quite clear to have a dedicated
waiting list for raised hands.
Will need it for lower hand action.
Actually, this piece of code should be enhanced. It'll act
as a corner stone of all actions dispatched in the interface.
I'll continue refactoring it later on.
Why? This layout is extensible. This menu will have two sections,
to separate in-room participants from the waiting room ones.
It's copied from Gmeet User Experience.
In-room participants will be divided in sub-lists based on their
states (ex: hand raised, …). This User Experience is extensible
if in the future with support subroom in a room or whatever.
Inspired by Magnify. Rely on participant metadata to determine,
if the local user has raised its hand.
There is a todo item in LiveKit code, useLocalParticipant is not
subscribed to metadata updates events.
The contrast of the toggled button in legacy Style is poor,
it needs to be urgently improved. User can barely distinguish if
their hands are raised.
These changes should be discussed. Needed for the audio selects,
that render super long text values.
By default, centered texts are sometime hard to read.
Removed annoying overlay that blocked the user. (feedback from @spaccoud)
Previous design required one click too many. As this dialog doesn't need
an overlay, I couldn't use the default primitive.
It's a hacky but functional, creating technical debt here.
Closer to the Gmeet design. Added a warning about permissions
since the rooms are public in beta.
Apologies @manuhabitela, this may impact accessibility for users unfamiliar
with the copy icon. Let's conduct user testing.
Messy code file organization, but functions are okay. Functional, but not
well-designed and likely hard to maintain. Shipping it, creating technical
debt here. Will be reused for interactions with LiveKit server API.
Participants need to be room admin to interact with LiveKit server
api. Until we offer private room, with moderation, all participants
will be considered as room admin.
note: room admin doesn't offer permission to record a room. please,
refer to LiveKit documentation to learn more.
This commit focuses on the UX more than the code quality. In facts,
we should design a centralized component/alert service, that we
can trigger anywhere in the codebase, when a user is prompted for
confirmation.
The alert modal with cancel/submit buttons and a description is generic.
Creating technical debt here.
Rapidly, a 'more option' button should be added to the row. Thus,
participants will have access to few more actions (ex: remove from
the room, pin camera, etc…).
This flex layout should be definitive, except the code which is dirty,
but not creating much technical debt here.
First raw iteration.
Tried replicating Gmeet UX and layout. However, in their ux, even if
action button are disabled, some tooltips explain to the user why they
cannot perform the action. With the default Trigger, it's not easily
feasible. As soon as the button is disabled, there is no way to trigger
the tooltip in an uncontrolled manner.
In upcoming commits I'll arrange layout, and call the remote LiveKit
ServerApi, to perform the mute action.
Main update: create a component, which has the responsability of
rendering a Participant in the list. I tried gettig closer to a
cleaner codebase, with small and well-scoped components. WIP.
Formatting participants before rendering the list was way to over
complicated, iterating twice on the list was kinda useless. Fixed!
Few updates:
- Removed capitalizing Participant's name to be consistent with the
avatar. This choices mimics GMeet UX.
- Duplicated isLocal utils function from LiveKit, which is not
exported by their package.
Avatar font size was way too small in the participant list context.
I tried improve it. Few font sizing are visually uncomfortable in
the participant list.
oupsy, heavily copied from Gmeet.
Thx Nathan Vasse for his css animation skills, he crushed it.
This component will be core in the app, and reused in many places.
It was necessary for the participants list.
Upgrading Django to 5.1 created a severe issue.
Migrate and create-superuser jobs were failing.
The issue originated from the third party easy_thumbnail.
Please refer to the issue #641 on their repo.
This is the suggested workaround by @Miketsukami.
It explains why participant initials doesn't update when a participant
changes its name.
Similar issue as the one faced while developing on the participant list.
It needs to be fixed at the root, in the LiveKit repo.
Duplicated source from LiveKit internal hooks (not ideal, but necessary)
to ensure the inner content of the participant placeholder consistently
fits its parent container. Unfortunately, I couldn't find
a simpler solution.
This might lead to some performances issues, as for each tile, some js
would be computing avatar's size, which is much more costly than pure
css…
Note: Gmeet achieves this by generating a temporary placeholder image
with a colored background and initials, allowing for a perfectly round,
responsive avatar without relying on JavaScript.
Default 'transparent' value avoid showing the avatar when
participant's info are not yet available. Might be a bad design
if we follow the single responsability pattern. Please feel free
to refactor it.
Color is stored in participant's metadata.
Using a hash of some participant's info allow to persist the color
for logged-in participant without storing the color in db.
Please feel free to tune the saturation and lightness range.
Code is inspired by a tutorial found online.
Inspired by Gmeet animation (mine is far from perfect).
Some details should be improved, especially to have a smooth
animation stop when the user stops speaking.
Duplicated LiveKit sources to customize the participant tile. It’s needed
to enhance the design and color of the participant placeholder.
More in the next commits.
Inspired by the Google Meet user experience.
A simple UX for scheduling meetings was requested by some users.
This is a quick and basic poc to validate the UX in a production
environment. If it gains traction, it will be refined and consolidated.
Inspired by GMeet user experience. Offer a sound tester button
to our users while configuring their audio output.
uprise.mp3 has a free license. We should credit them in our legal
terms asap.
First draft, it lacks important features, as a visual indicator when
the mic is active, and a trigger to test the audio output.
I made some heuristics (e.g. default output/input, etc..) to ship a
first version of this setting tabs that should work good enough to
create value for our current users.
Please refer to the inline comments.
Introduced a General settings tab, currently allowing language configuration.
Although this commit introduces some duplication, the default settings dialog
will be refactored in future updates.
The General tab is designed to accommodate additional features over time.
User can now update their name in a dedicated Account tab,
inspired by Jitsi design. Removed the username dialog.
Account-related updates will be operated through the advanced
settings dialog, in this dedicated tab.
Inspired by other videoconferencing tools' designs.
Sizes are mixing pixels and rem, it should be harmonized.
Will be used by the advanced settings panels.
Refactored it in a proper component. Initially planned to
use it in the Account Tab, but I changed my mind.
This refactoring is an enhancement, the Avatar props are better
encapsulated.
This component should be the definitive layout for settings.
Why extended? I kept the original one, which is still in-use in the
homepage, and considered this settings dialos as an extended version,
or advanced one.
I hope in a close future, we merge these two dialogs to avoid
maintaining too much code. Not the top prio.
Relevant TabPanel components will be introduced in the upcomming commits.
Even if the list is empty, previous assertion was returning true.
Fixed it, mybad, noob error.
In fact, the participants list should never be empty, as you are
in the meeting to access it.
The 'Box' component has a type 'dialog' which limits the Dialog size.
The default size is insufficient for larger dialogs like
the advanced settings.
To address this temporarily, I'm allowing the wrapper component to set the
Dialog size directly. This isn't ideal, but will enable better flexibility
until we finalize the user experience and dialog requirements.
I am not sure of the new props' naming introduced.
Added a new variant for Tabs and TabList components
to support borderless styles.
By default, both Tabs and TabList include borders.
Using React context, TabList’s children will automatically
inherit a borderless style if specified via props.
However, you can still explicitly apply borders
to individual children, even if the parent
TabList is set to be borderless.
Style react aria components and exposed them.
Tabs are needed for the advanced settings component.
Both orientations, horizontal and vertical, are supported.
Introduce an option to render or omit the title in the Dialog component.
This is necessary for the advanced settings Dialog, which displays its
title in the Tab menu.
This could affect existing component API created by @manuhabitela.
The component will become less opinionated, offering more flexibility
in its usage (I am not 100% convinced it's actually a great idea).
Quick fix! Let's enhance it
Text.tsx export not only a component, but also few types.
This triggers an eslint warning. I don't want refactoring it
without discussing it with @manuhabitela. Silence it.
@manuhabitela introduced Menu and MenuTrigger components. Refactor the
options menu to benefits from his components.
Few details are not perfect yet. wip
it seems panda-css didn't like my way of sharing css code. When sharing
bare objects matching panda-css interface, panda-css didn't understand
those were styles and didn't parse them. Now using actual recipes via
the `cva` helper, panda understands correctly those styles need to be
updated on change.
ps: cleaned a few panda imports that didn't use our "@" alias
this will be used for toggled on/off mic and camera buttons. We want
toggled-on buttons that don't look pressed as it looks a bit weird
(we'll change icons on pressed/unpressed state). And we want red buttons
for when the buttons are not pressed, so adding the "danger" variant
too.
the whole colorpalette stuff needs a bit of work to be clean but it'll
do for now
Refactor the existing Button component to extract a new ToggleButton
component that wraps react aria ToggleButton. This will
be used to toggle cam/mic on/off, or any other controls in the control
bar.
ditch the "PopoverList" component that was basically a poor Menu. Now
dropdown buttons can be made with react aria Menu+MenuItems components
via the Menu+MenuList components.
The difference now is dropdown menus behave better with keyboard (they
use up/down arrows instead of tabs), like selects.
Popovers are there if we need to show any content in a big tooltip, not
for actionable list items.
The current design is inefficient, using two separate approaches to manage
the app state and determine which widget is open. This inconsistency affects
the user experience and overall design quality.
Soon, only one container will be open/close, and its content will be toggle,
using an extensible system.
As a quick fix, I’ve added basic logic to ensure that opening one widget
automatically closes any other open widgets, such as the chat or participants
widget. This is a temporary measure to fix state management until a
more robust solution can be implemented.
This commit refactor the default chat toggle to enhance few details:
- styling (e.g. button's size, icon's style, etc)
- accessibility (e.g. tooltip, aria label, keyboard controls)
- notifications (enhanced contrast on the red dot, feedback from Arnaud)
I faced few challenge while using LiveKit hook, please refer to my commits.
I'll work on a PR on their repo to get it fixed. Duplicating their sources
add overhead.
This commit introduce the most minimal participants list possible. More
controls or information will be added in the upcomming commits.
Responsiveness and accessibility should be functional.
Soon, any right side panel will share the same container to avoid visual
glichts.
Introduced a button to manage the visibility of the participants list.
Encountered refresh issues with the room context where the participant count
in the room metadata does not update in real-time, causing discrepancies
between the actual number of participants and the displayed count. To address
this, I utilized the participants hook, which updates more frequently and
ensures consistency.
Encountered issues extending the current button due to the complexity of the
Button and Link props construction. I’ll need to redesign the component to
enhance its extensibility.
The legacy style adheres to the previous interface but suffers from poor
color contrast. Hex codes were used to match the selected toggle color,
resulting in a difficult color system to maintain. This approach needs refactoring
for better color handling. Legacy styles will soon disappear.
Efforts were made to minimize code for handling the toggle functionality.
Future work should focus on refactoring the button to align with the field
approach for improved developer experience and props validation.
In LiveKit, opening the chat causes the entire page layout, including
participant tiles and controls, to shift left. This disrupts the user
experience, as the chat toggle button moves, requiring users to reposition
their cursor to close the chat.
This behavior also prevents effective organization of the control bar,
especially when trying to maintain a centered section for main controls and
a fixed section for quick-access buttons on the left or right bottom corners.
This fix temporarily locks the controls and participant list in place when
the chat is toggled. The styles will be refactored during the upcoming
redesign.
Updated Django's ALLOWED_HOSTS setting from '*' to the specific host of the
server. Setting ALLOWED_HOSTS to '*' is a security risk as it allows any host
to access the application, potentially exposing it to malicious attacks.
Restricting ALLOWED_HOSTS to the server's host ensures only legitimate
requests are processed.
In a Kubernetes environment, we also needed to whitelist the pod's IP address
to allow health checks to pass. This ensures that Kubernetes liveness and
readiness probes can access the application to verify its health.
Few scripts were duplicated between the scripts and the bin folders.
Reorganize the scripts in a common folder, and align filenames to
follow the same rule.
Updated the liveness and readiness probes interval from every 10 seconds to
every 30 seconds. This change reduces the load on the server by decreasing
the frequency of health checks.
Given the current stability of the application, a 30-second interval is
sufficient to ensure that the application remains responsive and healthy.
Silenced certain Django security warnings because the application is served
behind a reverse proxy. These warnings are not applicable in our deployment
context, where the reverse proxy handles these security concerns.
This change ensures relevant security measures are appropriately managed
while avoiding unnecessary warnings. Any question? asked @rouja.
/!\ actually, this commit is not working, and should be fixed.
Some outdated references to Terraform and OpenStack were missed during
the project quickstart. These are legacy elements inherited from OpenFun.
This commit cleans up the codebase.
LiveKit access tokens are valid for 6 hours after generation. Without a
`staleTime` set, room data becomes stale immediately (0 milliseconds),
causing unnecessary refetches, particularly when users switch focus back
to the call window.
This issue led to an excessive number of "get room" events, as observed
in the analytics. For example, during a meeting, if a user switches tabs
and then returns, the room data would be refetched despite the access
token still being valid.
By adding a `staleTime` aligned with the token's validity, we avoid
unnecessary network requests.
(aligned with Google Meet or Jitsi ux)
This ensures participants join a room with a fresh access token.
Some participants information might be altered after the access token
was generated (e.g. their name).
I wanted the initial data to be passed only once, when you navigate
to the room from the create button, but if you reload the page, then
a new access token will be fetched, and the pre-join screen displayed.
Utilized local storage to persist the updated name. After careful
consideration, persisting all user choices in the backend was deemed overly
complex and unnecessary for the value it would provide.
Opted for a single responsibility approach by leveraging local storage to manage
user choices, aligning with LiveKit's default implementation.
Switched to using query parameters instead of GET requests, enabling the
inclusion of additional parameters when calling the create endpoint via POST.
Simplified the access token generation process by removing redundant calls to
`with_identity` and consolidating token generation steps. This streamlines the
method flow by preparing all necessary data before generating the access token.
The user name is initially set by the backend when generating the LiveKit access
token. By default, if the frontend has not provided a username, the backend uses
the user's email address. This approach isn't ideal, as some users prefer using
their first name.
This update allows local participant to change their username in real-time
during a session. However, these changes are not yet persisted for
future meetings. This persistence feature will be added in upcoming commits.
Reintroduced user information in the settings dialog. This change allows
users to see the account they are logged into, which is important for
account management. An additional feature to update usernames will be
added soon. Apologies to @manuhabitela for the oversight.
Removed the header when inside a room to maximize space for the camera
gallery. Settings are now accessible via the options menu.
It aligns the design with common video conference tools as meet,
or jitsi. @manuhabitela was aligned with this change.
I am not hundred percent sure it respects @manuhabitela's guidelines,
but for the options menu, I would need to trigger a dialog in a controlled way.
I tried to have the minimal impact on the existing settings dialog.
Replaced the existing settings button with a new `OptionsButton` component.
This new component integrates a menu for more actions, providing an
extensible and accessible interface.
Refactoring will follow to enhance code maintainability.
A legacy style was introduced to keep visual coherence with the other controls
from the controls bar. It's temporary, until we redesign the whole bar.
It doesn't match pixel-perfect the legacy styles.
A new public Tchap chan was created. All users, and not only beta users,
can now join it using the link in the menu, and reach us.
Localized video conference controls to match the selected language.
Previously, controls were always in English, causing confusion for French users.
A full refactor of the controls is planned soon.
Same approach as the previous commit. Few elements were not exposed
by the LiveKit package, and I had to duplicate them. Let's see if
we can asap get rid off all this complexity.
Basically, duplicate LiveKit code to start iterating on their
components, not sure wether it's the optimal strategy, but at least
we will be more agile, shipping small features which are lacking.
Added CI job to run linting and formatting checks in the frontend
codebase. Please note, we should cache frontend dependencies,
to avoid re-installing them. Future improvement!
Ran Prettier on the entire codebase to fix formatting issues. My IDE was
previously misconfigured, causing most of these errors. The IDE configuration
has been corrected.
Following @manuhabitela's recommendation, we've decided to switch
from Yarn to npm for managing our Node.js dependencies. This update
aligns all remaining parts of the codebase that were still using
Yarn to now utilize npm.
I added an example in the documentation to ensure we remember to upgrade the
frontend image during the release process. This will help prevent any issues
related to outdated images when deploying new versions.
(I did this mistake while releasing)
Enhanced the error screen to support customizable titles and descriptions.
Allows for more detailed and informative error messages for users.
By default, the error screen displays a standard heading. You can
now pass custom title and body content to provide additional context
and clarity.
Attempt to create a room using a mutation if the fetch query fails.
If the mutation succeeds, update the fetch query data to ensure
it is up-to-date.
I tried to reproduce kind of a ‘get or create’ mechanism.
Due to the removal of the 'onError' prop in React Query, it is recommended
to use useEffect for handling such event propagation.
Regarding status handling, the fetch status takes priority over the mutation.
The mutation should only be called if the fetch has failed.
I'll need this key to sync data when the mutation responds successfully.
This is a preliminary refactoring; the mutation will be added
in upcoming commits.
Enabling logs by default in clients during production feels insecure.
Therefore, I have silenced all LiveKit logs.
This might pose a challenge if we need to debug a user in the future,
but currently, we don’t require these logs.
Additionally, my utils file and function work as intended,
though there is room for improvement.
With unregistered rooms being now forbidden, we need to call create a room
in our Django db to get an access token.
Clicking on the 'Create room' will create a new entry using a Post request.
The output serialized already contains an access token to the LiveKit server,
thus we won't need to run the useQuery hook when navigating to the room.
/!\ this modification now prevent authenticated users to create rooms
by simply navigating to it. It'll be fixed in the upcoming commits.
Require users to create a room in the database
before requesting a LiveKit token.
If user request an access token for a room that doesn't
exist in our db, its request would end in a 404 error.
Ensure that rooms must be registered by a user before they can be accessed.
By default, all created rooms remain public, allowing anonymous users to join
any room created by a logged-in user.
However, anonymous users cannot create rooms themselves.
I have set up distinct namespaces for each environment. You can now push
events to the development namespace without affecting production data.
Please note that these keys are not 'secret'. They will also be configured
in the browser SDK, which is inherently insecure. The documentation does not
specify a secure storage method for these keys.
In this commit, we'll integrate a third-party service to track user events.
We start by using the `identify` method to track sign-ins and sign-ups.
Additionally, we use the `track` method to monitor custom events such as room
creation, access token generation, and logouts. This will provide us with
valuable data on current usage patterns.
The analytics library operates by opening a queue in a separate thread for
posting events, ensuring it remains non-blocking for the API. Let's test
this in a real-world scenario.
Add a new property 'email_anonymized' to the User model,
to allow tracking a user's email without any personal data.
In fact, we're dealing with professional data, thus it shouldn't
be subject to the GDPR, however I prefer taking extra care
when working with potentially first and last names.
I've chosen June, a closed project, for our product analysis. Please note that
this is temporary until we find our product-market fit and achieve
significant traction.
I selected June for several reasons, particularly their focus on pre-product-
market fit (PMF) analysis, which is crucial for us. Their approach will help us
track user engagement and identify the most important features.
Remember, the purpose of this data is not to provide definitive answers about
our product, but to prompt us to ask the right questions and engage with users
to find the answers.
Close issue #91. Each <li> element in a list should have a unique key
to avoid React warnings.
Added unique keys to 'popover' items. Although the 'lang' keys are generated
by i18n dependencies and are expected to be unique, this implementation
ensures keys are unique and not based on indexes.
Removing the __init__.py makes it impossible for Pylint to get the sources
to lint from the root folder. We manually set all the paths pylint will lint.
That's not a big deal, as we'll remove Pylint any soon to rely only on ruff.
I took inspiration from marsha or magnify project.
I removed the now useless bash script to run Pylint command. It saves us
wrapper! Plus, having a lint command running with different option locally
and in the CI was quite a pain.
Locally linter was running on diff files; Fixed! CI and make command has now
the same behavior.
Recent updates in dependencies broke the tests.
I am in a rush, I found a stack overflow discussion mentionning we should
NOT consider the root folder of a Django project as a Python package.
My issue was:
Model class app.core.models.User doesn't declare an explicit app_label
and isn't in an application in INSTALLED_APPS.
Removing the __ini__.py file at the root folder fixed the regression.
Recent updates of dev/ruff and dev/pylint dependencies led
to new linting warnings.
Pylint 3.2.0 introduced a new check `possibly-used-before-assignment`,
which ensures variables are defined regardless of conditional statements.
Some if/else branches were missing defaults. These have been fixed.
Previously each route rendered its whole layout from a to z.
Now each route updates a single common wrapper when the layout changes
between pages.
Also the Loading, Error, UserFetched, QueryAware code is more explicit
and understandable.
This introduces valtio as dependency, allowing us to deal with global
state easily in a svelte/vue way (reactive mutable state). This limits
the boilerplaty-ness of immutable state lib approaches, while keeping
rendering optimization better than homemade react contexts.
we query user at load and keep info for a while, way less than user
session anyway. will need to check if we could get de-sync (like loading
the frontend with backend user session ending in 30 minutes while we
don't check user state until an hour)
2024-07-30 01:37:20 +02:00
549 changed files with 72811 additions and 7742 deletions
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at visio@numerique.gouv.fr. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [PostHog Code of Conduct](https://github.com/PostHog/posthog/blob/master/CODE_OF_CONDUCT.md), inspired from Contributor Covenant version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see
Thank you for taking the time to contribute! Please follow these guidelines to ensure a smooth and productive workflow. 🚀🚀🚀
To get started with the project, please refer to the [README.md](https://github.com/suitenumerique/meet/blob/main/README.md) for detailed instructions.
Please also check out our [dev handbook](https://suitenumerique.gitbook.io/handbook) to learn our best practices.
## Creating an Issue
When creating an issue, please provide the following details:
1.**Title**: A concise and descriptive title for the issue.
2.**Description**: A detailed explanation of the issue, including relevant context or screenshots if applicable.
3.**Steps to Reproduce**: If the issue is a bug, include the steps needed to reproduce the problem.
4.**Expected vs. Actual Behavior**: Describe what you expected to happen and what actually happened.
5.**Labels**: Add appropriate labels to categorize the issue (e.g., bug, feature request, documentation).
## Commit Message Format
All commit messages must adhere to the following format:
`<gitmoji>(type) title description`
* <**gitmoji**>: Use a gitmoji to represent the purpose of the commit. For example, ✨ for adding a new feature or 🔥 for removing something, see the list here: <https://gitmoji.dev/>.
***(type)**: Describe the type of change. Common types include `backend`, `frontend`, `CI`, `docker` etc...
***title**: A short, descriptive title for the change, starting with a lowercase character.
***description**: Include additional details about what was changed and why.
### Example Commit Message
```
✨(frontend) add user authentication logic
Implemented login and signup features, and integrated OAuth2 for social login.
```
## Changelog Update
Please add a line to the changelog describing your development. The changelog entry should include a brief summary of the changes, this helps in tracking changes effectively and keeping everyone informed. We usually include the title of the pull request, followed by the pull request ID to finish the log entry. The changelog line should be less than 80 characters in total.
### Example Changelog Message
```
## [Unreleased]
## Added
- ✨(frontend) add AI to the project #321
```
## Pull Requests
It is nice to add information about the purpose of the pull request to help reviewers understand the context and intent of the changes. If you can, add some pictures or a small video to show the changes.
### Don't forget to:
- check your commits
- check the linting: `make lint && make frontend-lint`
- check the tests: `make test`
- add a changelog entry
Once all the required tests have passed, you can request a review from the project maintainers.
## Code Style
Please maintain consistency in code style. Run any linting tools available to make sure the code is clean and follows the project's conventions.
## Tests
Make sure that all new features or fixes have corresponding tests. Run the test suite before pushing your changes to ensure that nothing is broken.
## Asking for Help
If you need any help while contributing, feel free to open a discussion or ask for guidance in the issue tracker. We are more than happy to assist!
## Réutilisation de l’« Information » sous cette licence
Le « Concédant » concède au « Réutilisateur » un droit non exclusif et gratuit de libre « Réutilisation » de l’« Information » objet de la présente licence, à des fins commerciales ou non, dans le monde entier et pour une durée illimitée, dans les conditions exprimées ci-dessous.
**Le « Réutilisateur » est libre de réutiliser l’« Information » :**
- de la communiquer, la reproduire, la copier ;
- de l’adapter, la modifier, l’extraire et la transformer, notamment pour créer des « Informations dérivées » ;
- de la diffuser, la redistribuer, la publier et la transmettre, de l’exploiter à titre commercial, par exemple en la combinant avec d’autres informations, ou en l’incluant dans votre propre produit ou application.
**Sous réserve de :**
- mentionner la paternité de l’«Information» : sa source (a minima le nom du « Concédant ») et la date de la dernière mise à jour de l’« Information » réutilisée.
Le « Réutilisateur » peut notamment s’ acquitter de cette condition en indiquant l’adresse (URL) renvoyant vers « l’Information » et assurant une mention effective de sa paternité.
**Par exemple :**
Dans le cas d’une réutilisation de la base SIRENE de l’INSEE, mentionner l’URL du « Concédant » : www.insee.fr + la date de dernière mise à jour de l’Information réutilisée.
Cette mention de paternité ne doit ni conférer un caractère officiel à la « Réutilisation » de l’« Information », ni suggérer une quelconque reconnaissance ou caution par le « Concédant », ou par toute autre entité publique, du « Réutilisateur » ou de sa « Réutilisation ».
## Données à caractère personnel
L’« Information » mise à disposition peut contenir des « Données à caractère personnel » pouvant faire l’objet d’une « Réutilisation ». Alors, le « Concédant » informe le « Réutilisateur » (par tous moyens) de leur présence, l’ « Information » peut être librement réutilisée, sans faire obstacle aux libertés accordées par la présente licence, à condition de respecter le cadre légal relatif à la protection des données à caractère personnel.
## Droits de propriété intellectuelle
Il est garanti au « Réutilisateur » que l’ « Information » ne contient pas de « Droits de propriété intellectuelle » appartenant à des tiers qui pourraient faire obstacle aux libertés qui lui sont accordées par la présente licence.
Les éventuels « Droits de propriété intellectuelle » détenus par le « Concédant » sur l’ « Information » ne font pas obstacle aux libertés qui sont accordées par la présente licence. Lorsque le « Concédant » détient des « Droits de propriété intellectuelle » » sur l’ « Information », il les cède au « Réutilisateur » de façon non exclusive, à titre gracieux, pour le monde entier, pour toute la durée des « Droits de propriété intellectuelle », et le « Réutilisateur » peut en faire tout usage conformément aux libertés et aux conditions définies par la présente licence.
## Responsabilité
L’ «Information» est mise à disposition telle que produite ou reçue, sans autre garantie expresse ou tacite qui n’est pas prévue par la présente licence. L’absence de défauts ou d’erreurs éventuellement contenues dans l’ «Information», comme la fourniture continue de l’ « Information » n’est pas garantie par le «Concédant». Il ne peut être tenu pour responsable de toute perte, préjudice ou dommage de quelque sorte causé à des tiers du fait de la « Réutilisation ».
Le « Réutilisateur » est seul responsable de la « Réutilisation » de l’« Information ».
La « Réutilisation » ne doit pas induire en erreur des tiers quant au contenu de l’« Information », sa source et sa date de mise à jour.
## Droit applicable
La présente licence est régie par le droit français.
### Compatibilité de la présente licence
Elle a été conçue pour être compatible avec toute licence libre qui exige _a minima_ la mention de paternité. Elle est notamment compatible avec la version antérieure de la présente licence ainsi qu’avec les licences « Open Government Licence » (OGL) du Royaume-Uni, « Creative Commons Attribution » (CC-BY) de Creative Commons et « Open Data Commons Attribution » (ODC-BY) de l’Open Knowledge Foundation.
## Définitions
Sont considérés, au sens de la présente licence comme :
- Le « **Concédant** » : toute personne concédant un droit de « Réutilisation » sur l’« Information » dans les libertés et les conditions prévues par la présente licence.
- L’« **Information** » :
- toute information publique figurant dans des documents communiqués ou publiés par une administration mentionnée au premier alinéa de l’article L.300-2 du CRPA ;
- toute information mise à disposition par toute personne selon les termes et conditions de la présente licence.
- La « **Réutilisation** » : l’utilisation de l’« Information » à d’autres fins que celles pour lesquelles elle a été produite ou reçue.
- Le « **Réutilisateur** » : toute personne qui réutilise les « Informations » conformément aux conditions de la présente licence.
- Des « **Données à caractère personnel** » : toute information se rapportant à une personne physique identifiée ou identifiable, pouvant être identifiée directement ou indirectement. Leur « Réutilisation » est subordonnée au respect du cadre juridique en vigueur.
- Une « **Information dérivée** » : toute nouvelle donnée ou information créées directement à partir de l’« Information » ou à partir d’une combinaison de l’ « Information » et d’autres données ou informations non soumises à cette licence.
- Les « **Droits de propriété intellectuelle** » : tous droits identifiés comme tels par le Code de la propriété intellectuelle (droit d’auteur, droits voisins au droit d’auteur, droit sui generis des producteurs de bases de données).
## À propos de cette licence
La présente licence a vocation à être utilisée par les administrations pour la réutilisation de leurs informations publiques. Elle peut également être utilisée par toute personne souhaitant mettre à disposition de l’« Information » dans les conditions définies par la présente licence
La France est dotée d’un cadre juridique global visant à une diffusion spontanée par les administrations de leurs informations publiques afin d’en permettre la plus large réutilisation.
Le droit de la « Réutilisation » de l’« Information » des administrations est régi par le code des relations entre le public et l’administration (CRPA) et, le cas échéant, le code du patrimoine (livre II relatif aux archives).
Cette licence facilite la réutilisation libre et gratuite des informations publiques et figure parmi les licences qui peuvent être utilisées par l’administration en vertu du décret pris en application de l’article L.323-2 du CRPA.
Etalab est la mission chargée, sous l’autorité du Premier ministre, d’ouvrir le plus grand nombre de données publiques des administrations de l’État et de ses établissements publics. Elle a réalisé la Licence Ouverte pour faciliter la réutilisation libre et gratuite de ces informations publiques, telles que définies par l’article L321-1 du CRPA.
Cette licence est une version 2.0 de la Licence Ouverte.
Etalab se réserve la faculté de proposer de nouvelles versions de la Licence Ouverte. Cependant, les « Réutilisateurs » pourront continuer à réutiliser les informations disponibles sous cette licence s’ils le souhaitent.
Meet is a simple video and phone conferencing tool, powered by [LiveKit](https://livekit.io/).
Meet is built on top of [Django Rest
Framework](https://www.django-rest-framework.org/) and [Vite.js](https://vitejs.dev/).
## Getting started
### Prerequisite
#### Docker
Make sure you have a recent version of Docker and [Docker
Compose](https://docs.docker.com/compose/install) installed on your laptop:
```bash
$ docker -v
Docker version 20.10.2, build 2291f61
$ docker compose -v
docker compose version 1.27.4, build 40524192
```
> ⚠️ You may need to run the following commands with `sudo` but this can be
> avoided by assigning your user to the `docker` group.
#### LiveKit CLI
Install LiveKit CLI, which provides utilities for interacting with the LiveKit ecosystem (including the server, egress, and more), please follow the instructions available in the [official repository](https://github.com/livekit/livekit-cli).
### Project bootstrap
The easiest way to start working on the project is to use GNU Make:
```bash
$ make bootstrap FLUSH_ARGS='--no-input'
```
Then you can access to the project in development mode by going to http://localhost:3000.
You will be prompted to log in, the default credentials are:
```bash
username: meet
password: meet
```
---
This command builds the `app` container, installs dependencies, performs
database migrations and compile translations. It's a good idea to use this
command each time you are pulling code from the project repository to avoid
dependency-related or migration-related issues.
Your Docker services should now be up and running 🎉
[FIXME] Explain how to run the frontend project.
### Configure LiveKit CLI
For the optimal DX, create a default project named `meet` to use with `livekit-cli` commands:
```bash
$ livekit-cli project add
URL: http://localhost:7880
API Key: devkey
API Secret: secret
Give it a name for later reference: meet
? Make this project default?? [y/N] y
```
Thus, you won't need to pass the project API Key and API Secret for each command.
The application is deployed across staging, preprod, and production environments using Kubernetes (K8s).
Reproducing environment conditions locally is crucial for developing new features or debugging issues.
This is facilitated by [Tilt](https://tilt.dev/) ("Kubernetes for Prod, Tilt for Dev"). Tilt enables smart rebuilds and live updates for services running locally in Kubernetes. We defined our services in a Tiltfile located at `bin/Tiltfile`.
Powered by [LiveKit](https://livekit.io/), La Suite Meet offers Zoom-level performance with high-quality video and audio. No installation required—simply join calls directly from your browser. Check out LiveKit's impressive optimizations in their [blog post](https://blog.livekit.io/livekit-one-dot-zero/).
### Features
- Optimized for stability in large meetings (+100 p.)
- Support for multiple screen sharing streams
- Non-persistent, secure chat
- End-to-end encryption (coming soon)
- Meeting recording (coming soon)
- Meeting transcription (currently in beta)
- Telephony integration (in development)
- Secure participation with robust authentication and access control
- LiveKit Advances features including :
- speaker detection
- simulcast
- end-to-end optimizations
- selective subscription
- SVC codecs (VP9, AV1)
#### Getting Started
La Suite Meet is fully self-hostable and released under the MIT License, ensuring complete control and flexibility. It's simple to [get started](https://visio.numerique.gouv.fr/) or [request a demo](mailto:visio@numerique.gouv.fr).
Make sure you have installed:
- kubectl
- helm
- helmfile
- tilt
We’re continuously adding new features to enhance your experience, with the latest updates coming soon!
To build and start the Kubernetes cluster using Kind:
```shell
$ make build-k8s-cluster
```
Once the Kubernetes cluster is ready, start the application stack locally:
```shell
$ make start-tilt
```
These commands set up and run your application environment using Tilt for local Kubernetes development.
## Table of Contents
You can monitor Tilt's at `http://localhost:10350/`. After Tilt actions finish, you can access the app at `https://meet.127.0.0.1.nip.io/`.
- [Get started](#get-started)
- [Docs](#docs)
- [Contributing](#contributing)
- [Philosophy](#philosophy)
- [Open source](#open-source)
#### Debugging frontend
Tilt deploys the `meet-dev` for the frontend by default, to benefit from Vite.js hot reloading while developing.
To troubleshoot production issues, please modify the Tiltfile, switch frontend's target to `frontend-production`:
## Get started
```yaml
...
### La Suite Meet Cloud (Recommended)
Sign up for La Suite Meet Cloud, designed for french public servants. Hosted on SecNumCloud-compliant providers and accessible via government SSO, [ProConnect](https://www.proconnect.gouv.fr/). The easiest way to try our product. Reach out if your entity isn't connected yet to our sso.
target='frontend-production', # Update this line when needed
live_update=[
sync('../src/frontend', '/home/frontend'),
]
)
...
```
### Open-source deployment (Advanced)
Deploy La Suite Meet on your own infrastructure using [our self-hosting guide](https://github.com/suitenumerique/meet/blob/main/docs/installation.md). Our open-source deployment is optimized for Kubernetes, and we're working on supporting additional deployment options. Keycloak integration and any SSO are supported. We offer customer support for open-source setups—just reach out for assistance.
## Docs
We're currently working on both technical and user documentation for La Suite Meet. In the meantime, many of the essential aspects are already well covered by the [LiveKit documentation](https://docs.livekit.io/home/) and their [self-hosting guide](https://docs.livekit.io/home/self-hosting/deployment/). Stay tuned for more updates!
## Contributing
This project is intended to be community-driven, so please, do not hesitate to
get in touch if you have any question related to our implementation or design
decisions.
We <3 contributions of any kind, big and small:
- Vote on features or get early access to beta functionality in our [roadmap](https://github.com/orgs/suitenumerique/projects/3/views/2)
- Open a PR (see our instructions on [developing La Suite Meet locally](https://github.com/suitenumerique/meet/blob/main/docs/developping_locally.md))
- Submit a [feature request](https://github.com/suitenumerique/meet/issues/new?assignees=&labels=enhancement&template=Feature_request.md) or [bug report](https://github.com/suitenumerique/meet/issues/new?assignees=&labels=bug&template=Bug_report.md)
## Philosophy
We’re relentlessly focused on building the best open-source video conferencing product—La Suite Meet. Growth comes from creating something people truly need, not just from chasing metrics.
Our users come first. We’re committed to making La Suite Meet as accessible and easy to use as proprietary solutions, ensuring it meets the highest standards.
Most of the heavy engineering is handled by the incredible LiveKit team, allowing us to focus on delivering a top-tier product. We follow extreme programming practices, favoring pair programming and quick, iterative releases. Challenge our tech and architecture—simplicity is always our top priority.
## Open-source
Gov 🇫🇷 supports open source! This project is available under [MIT license](https://github.com/suitenumerique/meet/blob/0cc2a7b7b4f4821e2c4d9d790efa739622bb6601/LICENSE).
All features we develop will always remain open-source, and we are committed to contributing back to the LiveKit community whenever feasible.
To learn more, don't hesitate to [reach out](mailto:visio@numerique.gouv.fr).
### Help us!
Come help us make La Suite Meet even better. We're growing fast and [would love some help](mailto:visio@numerique.gouv.fr).
We're using the awesome [LiveKit](https://livekit.io/) implementation. We're also thankful to the teams behind [Django Rest Framework](https://www.django-rest-framework.org/), [Vite.js](https://vite.dev/), and [React Aria](https://github.com/adobe/react-spectrum) — Thanks for your amazing work!
## License
This work is released under the MIT License (see [LICENSE](./LICENSE)).
Code in this repository is published under the MIT license by DINUM (Direction interministériel du numérique).
Documentation (in the docs/) directory is released under the [Etalab-2.0 license](https://spdx.org/licenses/etalab-2.0.html).
If you have any issue regarding security, please disclose the information responsibly submiting [this form](https://vdp.numerique.gouv.fr/p/Send-a-report?lang=en) and not by creating an issue on the repository. You can also email us at visio@numerique.gouv.fr
We appreciate your effort to make Visio more secure.
## Vulnerability disclosure policy
Working with security issues in an open source project can be challenging, as we are required to disclose potential problems that could be exploited by attackers. With this in mind, our security fix policy is as follows:
1. The Maintainers team will handle the fix as usual (Pull Request,
release).
2. In the release notes, we will include the identification numbers from the
GitHub Advisory Database (GHSA) and, if applicable, the Common Vulnerabilities
and Exposures (CVE) identifier for the vulnerability.
3. Once this grace period has passed, we will publish the vulnerability.
By adhering to this security policy, we aim to address security concerns
effectively and responsibly in our open source software project.
Before setting up, let's review Visio's architecture.
Visio consists of four main components that run simultaneously:
- React frontend, built with Vite.js
- Django server
- LiveKit server
- FastAPI server (optional, required for AI beta features)
These components rely on a few key services:
- PostgreSQL for storing data (users, rooms, recordings)
- Redis for caching and inter-service communication
- MinIO for storing files (room recordings)
- Celery workers for meeting transcript (optional, required for AI beta features)
We provide two stack options for getting Visio up and running for development:
- Docker Compose stack (recommended for most users)
- Kubernetes stack powered by Tilt (Advanced)
We recommend starting with the **Docker Compose** option for simplicity. However, if you're comfortable with running Kubernetes locally, the advanced option mirrors the production environment and provides most of the tools required for development (e.g., hot reloading).
These instructions are for macOS or Ubuntu. For other distros, adjust as needed.
If any steps are outdated, please let us know!
---
We also provide **GNU make utilities**. To view all available Make rules, run:
```shellscript
$ make help
```
---
## Need Help?
If you need any assistance or have questions while getting started, feel free to reach out to @lebaudantoine anytime! Antoine is available to help you onboard and guide you through the process. Chat with him @antoine.lebaud:matrix.org, or from the [support hotline](https://go.crisp.chat/chat/embed/?website_id=58ea6697-8eba-4492-bc59-ad6562585041).
---
## Option 1: Developing with Docker
### Prerequisites
1. Ensure you have a recent version of **Docker** and **Docker Compose** installed:
```shellscript
$ docker -v
Docker version 20.10.2, build 2291f61
$ docker compose version
Docker Compose version v2.32.4
```
2. Install **LiveKit CLI** by following the instructions available in the [official repository](https://github.com/livekit/livekit-cli). After installation, verify that it's working:
```shellscript
$ lk --version
lk version 2.3.1
```
---
### Project Bootstrap
1. Bootstrap the project using the **Make** command. This will build the `app` container, install dependencies, run database migrations, and compile translations:
```shellscript
$ make bootstrap FLUSH_ARGS='--no-input'
```
2. Access the project:
- The frontend is available at [http://localhost:3000](http://localhost:3000) with the default credentials:
- username: meet
- password: meet
- The Django backend is available at [http://localhost:8071](http://localhost:8071)
---
## Developing
- To **stop** the application:
```shellscript
$ make stop
```
- To **restart** the application:
```shellscript
$ make run
```
- For **frontend development**, start all backend services without the frontend container:
```shellscript
$ make run-backend
```
Then:
```shellscript
$ make frontend-development-install
$ make run-frontend-development
```
Which is equivalent to these direct npm commands:
```shellscript
$ cd src/frontend
$ npm i
$ npm run dev
```
---
## Adding Content
You can bootstrap demo data with a single command:
```shellscript
$ make demo
```
---
## Option 2: Developing with Kubernetes
Visio is deployed across staging, preprod, and production environments using **Kubernetes (K8s)**. Reproducing the environment locally is crucial for developing new features or debugging.
This is facilitated by [Tilt](https://tilt.dev/), which provides Kubernetes-like development for local environments, enabling smart rebuilds and live updates.
### Getting Started
Make sure you have the following installed:
- kubectl
- helm
- helmfile
- tilt
To build and start the Kubernetes cluster using **Kind**:
```shellscript
$ make build-k8s-cluster
```
Once the Kubernetes cluster is ready, start the application stack locally:
```shellscript
$ make start-tilt-keycloak
```
Monitor Tilt’s progress at [http://localhost:10350/](http://localhost:10350/). After Tilt actions finish, you can access the app at [https://visio.127.0.0.1.nip.io/](https://visio.127.0.0.1.nip.io/).
This document is a step-by-step guide that describes how to install Visio on a k8s cluster without AI features.
## Prerequisites
- k8s cluster with an nginx-ingress controller
- an OIDC provider (if you don't have one, we will provide an example)
- a LiveKit server (if you don't have one, we will provide an example)
- a PostgreSQL server (if you don't have one, we will provide an example)
- a Memcached server (if you don't have one, we will provide an example)
### Test cluster
If you do not have a test cluster, you can install everything on a local kind cluster. In this case, the simplest way is to use our script **bin/start-kind.sh**.
To be able to use the script, you will need to install:
The local CA is already installed in the system trust store! 👍
The local CA is already installed in the Firefox and/or Chrome/Chromium trust store! 👍
Created a new certificate valid for the following names 📜
- "127.0.0.1.nip.io"
- "*.127.0.0.1.nip.io"
Reminder: X.509 wildcards only go one level deep, so this won't match a.b.127.0.0.1.nip.io ℹ️
The certificate is at "./127.0.0.1.nip.io+1.pem" and the key at "./127.0.0.1.nip.io+1-key.pem" ✅
It will expire on 23 March 2027 🗓
1. Create registry container unless it already exists
2. Create kind cluster with containerd registry config dir enabled
Creating cluster "visio" ...
✓ Ensuring node image (kindest/node:v1.27.3) 🖼
✓ Preparing nodes 📦
✓ Writing configuration 📜
✓ Starting control-plane 🕹️
✓ Installing CNI 🔌
✓ Installing StorageClass 💾
Set kubectl context to "kind-visio"
You can now use your cluster with:
kubectl cluster-info --context kind-visio
Thanks for using kind! 😊
3. Add the registry config to the nodes
4. Connect the registry to the cluster network if not already connected
5. Document the local registry
configmap/local-registry-hosting created
Warning: resource configmaps/coredns is missing the kubectl.kubernetes.io/last-applied-configuration annotation which is required by kubectl apply. kubectl apply should only be used on resources created declaratively by either kubectl create --save-config or kubectl apply. The missing annotation will be patched automatically.
configmap/coredns configured
deployment.apps/coredns restarted
6. Install ingress-nginx
namespace/ingress-nginx created
serviceaccount/ingress-nginx created
serviceaccount/ingress-nginx-admission created
role.rbac.authorization.k8s.io/ingress-nginx created
role.rbac.authorization.k8s.io/ingress-nginx-admission created
clusterrole.rbac.authorization.k8s.io/ingress-nginx created
clusterrole.rbac.authorization.k8s.io/ingress-nginx-admission created
rolebinding.rbac.authorization.k8s.io/ingress-nginx created
rolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx created
clusterrolebinding.rbac.authorization.k8s.io/ingress-nginx-admission created
configmap/ingress-nginx-controller created
service/ingress-nginx-controller created
service/ingress-nginx-controller-admission created
deployment.apps/ingress-nginx-controller created
job.batch/ingress-nginx-admission-create created
job.batch/ingress-nginx-admission-patch created
ingressclass.networking.k8s.io/nginx created
validatingwebhookconfiguration.admissionregistration.k8s.io/ingress-nginx-admission created
When your k8s cluster is ready, you can start the deployment. This cluster is special because it uses the \*.127.0.0.1.nip.io domain and mkcert certificates to have full HTTPS support and easy domain name management.
Please remember that \*.127.0.0.1.nip.io will always resolve to 127.0.0.1, except in the k8s cluster where we configure CoreDNS to answer with the ingress-nginx service IP.
## Preparation
### What will you use to authenticate your users ?
Visio uses OIDC, so if you already have an OIDC provider, obtain the necessary information to use it. In the next step, we will see how to configure Django (and thus Visio) to use it. If you do not have a provider, we will show you how to deploy a local Keycloak instance (this is not a production deployment, just a demo).
If you haven't run the script **bin/start-kind.sh**, you'll need to manually create the namespace by running the following command:
```
$ kubectl create namespace meet
```
If you have already run the script, you can skip this step and proceed to the next instruction.
You can find these values in **examples/keycloak.values.yaml**
### Find livekit server connexion values
Visio use livekit for streaming part so if you have a livekit provider, obtain the necessary information to use it. If you do not have a provider, you can install a livekit testing environment as follows:
Livekit need a redis (and meet too) so we will start by deploying a redis :
Visio uses a postgresql db as backend so if you have a provider, obtain the necessary information to use it. If you do not have, you can install a postgresql testing environment as follows:
From here important information you will need are :
```
DB_HOST: postgres-postgresql
DB_NAME: meet
DB_USER: dinum
DB_PASSWORD: pass
DB_PORT: 5432
POSTGRES_DB: meet
POSTGRES_USER: dinum
POSTGRES_PASSWORD: pass
```
## Deployment
Now you are ready to deploy Visio without AI. AI required more dependencies (Openai-compliant API, LiveKit Egress, Cold storage and a docs deployment to push resumes). To deploy meet you need to provide all previous information to the helm chart.
Whenever we are cooking a new release (e.g. `4.18.1`) we should follow a standard procedure described below:
1. Create a new branch named: `release/4.18.1`.
2. Bump the release number for backend project, frontend projects, and Helm files:
2. Bump the release number for backend project, frontend projects, and Helm files:
- for backend, update the version number by hand in `pyproject.toml`,
- for each frontend projects (`src/frontend`, `src/mail`), run `npm version 4.18.1` in their directory. This will update both their `package.json` and `package-lock.json` for you,
- for Helm, update Docker image tag in files located at `src/helm/env.d` for both `preprod` and `production` environments:
- for backend, update the version number by hand in `pyproject.toml`,
- for each frontend projects (`src/frontend`, `src/mail`), run `npm version 4.18.1` in their directory. This will update both their `package.json` and `package-lock.json` for you,
- for Helm, update Docker image tag in files located at `src/helm/env.d` for both `preprod` and `production` environments:
```yaml
image:
repository: lasuite/meet-backend
pullPolicy: Always
tag: "v4.18.1" # Replace with your new version number, without forgetting the "v" prefix
```
```yaml
image:
repository: lasuite/meet-backend
pullPolicy: Always
tag: "v4.18.1" # Replace with your new version number, without forgetting the "v" prefix
...
frontend:
image:
repository: lasuite/meet-frontend
pullPolicy: Always
tag: "v4.18.1" # Replace with your new version number, without forgetting the "v" prefix
```
The new images don't exist _yet_: they will be created automatically later in the process.
The new images don't exist _yet_: they will be created automatically later in the process.
3. ~~Update the project's `Changelog` following the [keepachangelog](https://keepachangelog.com/en/0.3.0/) recommendations~~ _we don't keep a changelog yet for now as the project is still in its infancy. Soon™!_
4. Commit your changes with the following format: the 🔖 release emoji, the type of release (patch/minor/patch) and the release version:
field=models.JSONField(blank=True,default=dict,help_text='Values for Visio parameters to configure the room.',verbose_name='Visio room configuration'),
field=models.CharField(choices="(('en-us', 'English'), ('fr-fr', 'French'))",default='en-us',help_text='The language in which the user wants to see the interface.',max_length=10,verbose_name='language'),
('id',models.UUIDField(default=uuid.uuid4,editable=False,help_text='primary key for the record as UUID',primary_key=True,serialize=False,verbose_name='id')),
('created_at',models.DateTimeField(auto_now_add=True,help_text='date and time at which a record was created',verbose_name='created on')),
('updated_at',models.DateTimeField(auto_now=True,help_text='date and time at which a record was last updated',verbose_name='updated on')),
('status',models.CharField(choices=[('initiated','Initiated'),('active','Active'),('stopped','Stopped'),('saved','Saved'),('aborted','Aborted'),('failed_to_start','Failed to Start'),('failed_to_stop','Failed to Stop')],default='initiated',max_length=20)),
('worker_id',models.CharField(blank=True,help_text='Enter an identifier for the worker recording.This ID is retained even when the worker stops, allowing for easy tracking.',max_length=255,null=True,verbose_name='Worker ID')),
('id',models.UUIDField(default=uuid.uuid4,editable=False,help_text='primary key for the record as UUID',primary_key=True,serialize=False,verbose_name='id')),
('created_at',models.DateTimeField(auto_now_add=True,help_text='date and time at which a record was created',verbose_name='created on')),
('updated_at',models.DateTimeField(auto_now=True,help_text='date and time at which a record was last updated',verbose_name='updated on')),
constraint=models.UniqueConstraint(condition=models.Q(('user__isnull',False)),fields=('user','recording'),name='unique_recording_user',violation_error_message='This user is already in this recording.'),
),
migrations.AddConstraint(
model_name='recordingaccess',
constraint=models.UniqueConstraint(condition=models.Q(('team__gt','')),fields=('team','recording'),name='unique_recording_team',violation_error_message='This team is already in this recording.'),
),
migrations.AddConstraint(
model_name='recordingaccess',
constraint=models.CheckConstraint(condition=models.Q(models.Q(('team',''),('user__isnull',False)),models.Q(('team__gt',''),('user__isnull',True)),_connector='OR'),name='check_recording_access_either_user_or_team',violation_error_message='Either user or team must be set, not both.'),
field=models.CharField(choices=[('screen_recording','SCREEN_RECORDING'),('transcript','TRANSCRIPT')],default='screen_recording',help_text='Defines the mode of recording being called.',max_length=20,verbose_name='Recording mode'),
field=models.CharField(choices=[('initiated','Initiated'),('active','Active'),('stopped','Stopped'),('saved','Saved'),('aborted','Aborted'),('failed_to_start','Failed to Start'),('failed_to_stop','Failed to Stop'),('notification_succeeded','Notification succeeded')],default='initiated',max_length=50),
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.