Frontend webowy
repartee zawiera wbudowany frontend webowy, który działa obok interfejsu terminalowego. Uzyskaj dostęp do sesji IRC z dowolnej przeglądarki -- na komputerze lub urządzeniu mobilnym -- z dwukierunkową synchronizacją w czasie rzeczywistym.

TUI (po lewej) | Mobilny web (na środku) | Desktopowy web (po prawej) -- pełna synchronizacja stanu 1:1.
Włączanie
Frontend webowy jest domyślnie wyłączony. Aby go włączyć, ustaw hasło w ~/.repartee/.env i włącz go w config.toml:
1. Ustaw hasło logowania:
echo 'WEB_PASSWORD=your-secret-password' >> ~/.repartee/.env
2. Włącz w konfiguracji:
[web]
enabled = true
port = 8443
repartee automatycznie generuje samopodpisany certyfikat TLS przy pierwszym uruchomieniu. Otwórz https://localhost:8443 w przeglądarce i zaakceptuj ostrzeżenie o certyfikacie.
Konfiguracja
Wszystkie ustawienia webowe znajdują się w sekcji [web] w config.toml i mogą być zmieniane w czasie działania za pomocą /set:
| Ustawienie | Domyślna | Opis |
|---|---|---|
web.enabled | false | Włącz serwer webowy |
web.bind_address | 127.0.0.1 | Adres nasłuchiwania (użyj 0.0.0.0 dla dostępu z sieci lokalnej) |
web.port | 8443 | Port HTTPS |
web.tls_cert | (auto) | Ścieżka do certyfikatu TLS (PEM). Pusty = samopodpisany |
web.tls_key | (auto) | Ścieżka do klucza prywatnego TLS (PEM). Pusty = samopodpisany |
web.password | (z .env) | Hasło logowania (ustawiane przez WEB_PASSWORD w .env) |
web.session_days | 90 | Czas życia ciasteczka w dniach; sesje są zapisywane na dysku i przeżywają restart przeglądarki |
web.username | repartee | Nazwa użytkownika podpowiadana w formularzu logowania (dekoracyjna — weryfikowane jest tylko hasło) |
web.image_previews | false | Opcjonalne podglądy obrazków pod wiadomościami czatu |
web.image_previews_max_per_msg | 4 | Maksymalna liczba miniatur podglądu renderowanych na wiadomość |
web.thumbnail_cache_mb | 200 | Maksymalny rozmiar ~/.repartee/web_thumbnails/ (LRU po mtime) |
web.theme | nightfall | Domyślny motyw (nightfall, catppuccin-mocha, tokyo-storm, gruvbox-light, catppuccin-latte) |
web.timestamp_format | %H:%M | Format znacznika czasu (składnia chrono strftime) |
web.line_height | 1.35 | Wysokość linii CSS dla wiadomości czatu |
web.nick_column_width | 12 | Szerokość kolumny nicka w znakach |
web.nick_max_length | 9 | Maksymalna wyświetlana długość nicka przed obcięciem |
Ustawienia kolorowania nicków znajdują się w sekcji [display], ale są również synchronizowane z klientami webowymi:
| Ustawienie | Domyślna | Opis |
|---|---|---|
display.nick_colors | true | Włącz deterministyczne kolorowanie per nick |
display.nick_colors_in_nicklist | true | Koloruj również nicki na liście nicków na pasku bocznym |
display.nick_color_saturation | 0.65 | Nasycenie HSL (0.0-1.0) |
display.nick_color_lightness | 0.65 | Jasność HSL (0.0-1.0), niższa dla jasnych motywów |
Ustawienia zmienione za pomocą /set web.* lub /set display.nick_color* są natychmiast stosowane do wszystkich podłączonych klientów webowych.
Funkcje
Frontend webowy zapewnia pełną zgodność 1:1 z interfejsem terminalowym:
- Wszystkie typy buforów -- serwer, kanał, query, czat DCC
- Synchronizacja w czasie rzeczywistym -- wiadomości, zmiany nicków, joiny, party, quity, zmiany topiku, zmiany trybów
- Dwukierunkowe przełączanie buforów -- przełącz bufor w przeglądarce, a TUI podąża za nim i odwrotnie
- Wykonywanie poleceń -- uruchamiaj dowolne
/poleceniez pola wprowadzania w przeglądarce (wynik widoczny w przeglądarce) - Uzupełnianie Tab -- nicki,
/poleceniai ścieżki ustawień/set - Popup uzupełniania -- wpisanie
@nick,/cmdlub:emoteotwiera przyjazną dotykowi listę podpowiedzi (emote pokazują animowane miniatury). Strzałki przesuwają zaznaczenie, Tab akceptuje, Escape zamyka; Enter akceptuje tylko wtedy, gdy wiersz jest zaznaczony, więc w przeciwnym razie nadal wysyła wiadomość. Dotknięcie wiersza zatwierdza wybór już namousedown, więc przyjęcie podpowiedzi nie chowa klawiatury na urządzeniu mobilnym - Dotknij nicka, aby o nim wspomnieć -- dotknięcie nicka w logu czatu wstawia go do composera (
nick:na początku linii,nickw środku linii); podwójne kliknięcie nadal zaznacza tekst do skopiowania. Dotknięcie nicka na liście nicków otwiera query, tak jak dotychczas @nickprzepisywany przy wysyłce -- linia zaczynająca się od@nickjest wysyłana w tradycyjnej ircowej formie adresowanianick:, z kanoniczną wielkością liter z listy nicków. Jeśli nazwa nie pasuje do nikogo w buforze, linia jest wysyłana bez zmian, a@nickw środku linii nigdy nie jest przepisywany- Historia wpisywania -- naciśnij ↑/↓, aby przywołać to, co wysłałeś, tak jak w TUI (ostatnie 100 wpisów; niewysłany szkic jest odkładany i przywracany). ↑ cofa się w historii tylko wtedy, gdy karetka jest w pierwszej linii szkicu, więc w szkicu wieloliniowym nadal porusza się normalnie
- Wskaźniki pisania -- zobacz, kto komponuje wiadomość w bieżącym buforze, zgodnie z paskiem statusu TUI (
alice and bob are typing…). Twoje własne pisanie jest zgłaszane w trakcie komponowania, zgodnie z przełącznikami wysyłania[typing] - Kolorowanie nicków -- deterministyczne kolory per nick synchronizowane z ustawień serwera, ten sam algorytm HSL co TUI
- Lista nicków -- grupowana według trybu (opy, voice, zwykli), status away, kolorowanie per nick (osobno przełączalne)
- Wskaźniki aktywności -- kolorowe poziomy aktywności oraz plakietka nieprzeczytanych na każdym buforze (ograniczona do
99+, ukryta dla aktywnego bufora). Bufory z rozłączonej sieci są przygaszone - Regulowany rozmiar tekstu i odstęp między liniami -- menu Aa (dolny pasek na komputerze, wysuwany panel na urządzeniach mobilnych) ustawia rozmiar czcionki (10–24 px) i odstęp między liniami (1.00–2.20), wraz z przywróceniem wartości domyślnych. Oba ustawienia są zapisywane w
localStorage, więc przeżywają przeładowanie strony - Wzmianki -- śledzenie podświetleń z plakietką licznika wzmianek
- Wybór motywu -- zmiana motywu na żywo (5 wbudowanych motywów)
- Wieloliniowe wprowadzanie -- komponuj z podziałami wierszy lub wklej blok tekstu; wysyłane jako jedna wiadomość
draft/multiline, gdy serwer ją obsługuje, w przeciwnym razie linia po linii - Trwałe sesje -- domyślnie 90-dniowe ciasteczko, magazyn tokenów na dysku; restart przeglądarki, instalacja PWA i przejście z WiFi na sieć komórkową nie wylogowują użytkownika
- Formularz logowania z polem użytkownika -- prawidłowy
<form>z oddzielnymi polami username + password, dzięki czemu 1Password, iCloud Keychain i Bitwarden rozpoznają formularz - Klikalne linki -- URL-e w wiadomościach renderowane są jako odnośniki otwierające się w nowej karcie, z natywnym menu kontekstowym przeglądarki ("Otwórz w nowym oknie", "Kopiuj adres linku")
- Podglądy obrazków -- opcjonalne (
web.image_previews = true); pobieranie po stronie serwera z zabezpieczeniem SSRF i generowaniem miniatury (400x300 JPEG, cache lokalny), zarezerwowana ramka układu chroni przed przeładowywaniem czatu, dyskretne odrzucanie podglądu per wiadomość zapisywane w localStorage - Automatyczny reconnect -- WebSocket automatycznie łączy ponownie z wykładniczym opóźnieniem (2s-30s) po utracie połączenia
- Odporne pierwsze połączenie -- chwilowy problem sieciowy przy ładowaniu strony powtarza próby z wykładniczym opóźnieniem do pięciu razy, zanim spadnie do formularza logowania
- Separatory dat -- wizualne separatory między wiadomościami z różnych dni dla łatwiejszego czytania historii
- Wbudowana powłoka -- pełny terminal w przeglądarce przez renderer beamterm 1.0 WebGL2. Otwiera się w karcie przeglądarki inicjującej polecenie, z oddzielnym PTY na sesję webową (bez konfliktu zmiany rozmiaru z TUI). Czcionka FiraCode Nerd Font, poprawne renderowanie szerokich glifów 2-kolumnowych, zaznaczanie myszą ze schowkiem, zmiana rozmiaru czcionki Ctrl+/-, Ctrl+C (SIGINT), wklejanie ze schowka w trybie bracketed paste
- Inline emotes -- 183 wbudowane emote GG7
:name:renderowane jako inline animowane GIF-y serwowane prosto z binarki; wpisz:smile:(lub polskie:usmiech:) i pojawia się w miejscu - Emote & emoji pickers -- GG emote picker (animowane miniatury + filtr na żywo) oraz Unicode emoji picker (zakładki kategorii + wyszukiwanie) otwierane z przycisków paska narzędzi, polecenia
/emojilub skrótem Ctrl+G;:name:uzupełnia się również przez tab-complete w composerze. Oba wstawiają w miejscu caret, na komputerze i urządzeniach mobilnych - Formatowane topiki -- pasek topiku renderuje kolory mIRC/irssi, pogrubienie, kursywę, podkreślenie i klikalne URL-e (pełna 99-kolorowa paleta), zgodnie z parserem czatu
- Backlog scroll-back i synchronizacja read-marker -- przewiń kanał/query w stronę góry, aby stronicować starsze wiadomości prosto z logu SQLite (oraz z historii serwera, gdy bouncer obsługuje
draft/chathistory); pozycja przewijania jest zakotwiczona, a znaczniki przeczytania (MARKREAD) są synchronizowane między TUI, webem i innymi klientami bouncera - Wspólny panel ustawień (
/wizard) -- kliknij ikonę koła zębatego w lewym górnym rogu (lub wpisz/wizard), aby otworzyć pełny 10-sekcyjny panel ustawień współdzielony z TUI (Networks & Connections, Appearance, Messages, Notifications, History & Privacy, Keyboard, Extensions, E2E Encryption, Translation oraz Advanced), z wyszukiwarkąCtrl+F, edytorami list oraz kreatorami kanałów per sieć dla szyfrowania E2E i tłumaczeń; hasła i klucze trafiają do.env, nigdy doconfig.toml - Własne skróty klawiszowe (
/bind) -- skróty klawiszowe i sekwencje wieloklawiszowe skonfigurowane przez/bindlub sekcję[keyboard](w tym skok do aktywnościAlt+A,Alt+1–9/0,Alt+Lewo/Prawooraz nawigacja po highlightach) działają w interfejsie webowym i aktualizują się na żywo - Powiadomienia WebPush -- powiadomienia push w przeglądarce dzięki obsłudze
draft/webpush/soju.im/webpushna bouncerze - Ikony sieci -- wyświetla ikony sieci rozgłaszane przez IRCv3 ISUPPORT
draft/ICONna pasku bocznym i liście serwerów - Auto-revealing scrollbars -- cienkie, dopasowane do motywu scrollbary, które pojawiają się przy najechaniu/przewijaniu i poza tym pozostają niewidoczne, w Chrome, Firefox i Safari
Układ desktopowy
Układ desktopowy odzwierciedla interfejs terminalowy:
┌─────────────────────────────────────────────────────┐
│ Topic bar │
├──────────┬─────────────────────────────┬────────────┤
│ Buffers │ Chat area │ Nick list │
│ │ 14:23 @ferris❯ Hello! │ @ferris │
│ (status) │ 14:24 alice❯ Hey there │ alice │
│ 1.#rust │ │ bob │
│ 2.#help │ │ │
├──────────┴─────────────────────────────┴────────────┤
│ [kofany(+i)] [#rust(+nt)] [Lag: 42ms] [Act: 3,4] │
│ ❯ [Message input... ] [➤] │
│ [● ● ● ● ●] theme picker │
└─────────────────────────────────────────────────────┘
Układ mobilny
Na ekranach węższych niż 768px układ przełącza się na widok zoptymalizowany dla urządzeń mobilnych:
┌──────────────────────────┐
│ ☰ #rust (+nt) — Welc… 👥│ top bar
├──────────────────────────┤
│ 14:23 @ferris❯ Has any… │ inline nicks
│ 14:24 alice❯ Yeah, it's… │
├──────────────────────────┤
│ [kofany|Act: 3,4,7] │ compact status
│ [Message... ] ➤ │ input
└──────────────────────────┘
Funkcje mobilne:
- Czat inline -- nicki pojawiają się w linii z wiadomością (bez wyrównanej w prawo kolumny), aby zmaksymalizować przestrzeń poziomą
- Wysuwana lista buforów -- dotknij menu hamburger lub przesuń palcem w prawo z dowolnego miejsca, aby otworzyć listę kanałów/buforów
- Wysuwana lista nicków -- dotknij przycisku listy nicków lub przesuń palcem w lewo z dowolnego miejsca, aby otworzyć listę nicków
- Automatyczne zamykanie paneli -- dotknięcie bufora na wysuwanej liście przełącza na niego i automatycznie zamyka panel
- Przyjazny dotykowi -- duże cele dotykowe, gesty przesuwania, brak przypadkowego przewijania poziomego
- Dopasowanie do widoku -- używa
100dvhdo prawidłowego wypełnienia ekranu w iOS Safari i Android Chrome (uwzględnia chrome przeglądarki) - Bez automatycznego powiększania -- skupienie na polu wprowadzania nie wywołuje automatycznego powiększenia w iOS Safari
- Bezpieczny obszar wycięcia -- respektuje
safe-area-inset-bottomna iPhone'ach ze wskaźnikami home - Stabilne pinowanie do dołu -- wzorzec "pin to bottom" znany z The Lounge: dopóki najnowsza wiadomość jest widoczna, nowe wiadomości pozostają przyklejone do dołu; przewiń w górę o dowolny kawałek i widok zostaje zaparkowany, a historia spokojnie spływa pod spodem. Wcześniej widoczny "skok w górę i z powrotem" został wyeliminowany.
- Bez skoków, gdy treść się doładuje -- czat jest przypinany ponownie za każdym razem, gdy zmienia się jego ramka, a nie tylko przy zmianie rozmiaru okna, więc rosnący composer nie zasłania już ostatniej linii podczas pisania. Podglądy obrazków rezerwują swoją ramkę od pierwszego renderu i jedynie płynnie się pojawiają, więc obrazek kończący ładowanie w trakcie przewijania nie przebuduje widoku.
- Gęstsze panele -- ciaśniejsze odstępy i większe cele dotykowe na mobilnym pasku górnym oraz w wysuwanych panelach, a Escape zamyka otwarte okno modalne lub panel.
Własny TLS
Do użytku produkcyjnego (lub aby uniknąć ostrzeżeń o certyfikacie w przeglądarce) podaj własny certyfikat TLS:
[web]
tls_cert = "/path/to/fullchain.pem"
tls_key = "/path/to/privkey.pem"
Certyfikaty Let's Encrypt działają od razu.
Zdalny dostęp
Aby uzyskać dostęp do frontendu webowego z innych urządzeń w sieci:
[web]
bind_address = "0.0.0.0" # listen on all interfaces
port = 8443
Następnie otwórz https://adres-ip-twojego-komputera:8443 ze swojego telefonu lub innego komputera.
Bezpieczeństwo
- Tylko HTTPS -- cały ruch jest szyfrowany przez TLS
- Uwierzytelnianie hasłem -- logowanie weryfikowane HMAC-SHA256
- Ograniczanie prób -- ochrona przed atakami brute-force z progresywną blokadą
- Tokeny sesji -- 32-bajtowe losowe tokeny przekazywane jako ciasteczko
HttpOnly; Secure; SameSite=Strict; zapisywane w~/.repartee/web_sessions.bin(uprawnienia 0600) wyłącznie jakoHMAC-SHA256(token, WEB_SESSION_SECRET), więc surowy token nigdy nie trafia na dysk.WEB_SESSION_SECRETjest generowany do.envprzy pierwszym uruchomieniu; jego rotacja unieważnia wszystkie istniejące sesje. - Brak powiązania z IP/User-Agent -- ciasteczko jest granicą bezpieczeństwa, więc telefon przechodzący między WiFi a siecią komórkową nie wylogowuje się
- Ochrona SSRF dla podglądów --
/api/previewserwuje wyłącznie URL-e wcześniej wyłuskane przez sam serwer, wyszukiwane po hashu HMAC; cele prywatne, loopback, link-local i metadane chmury są blokowane na poziomie bezpośrednich URL-i, przekierowań i podążania zaog:image - Brak zewnętrznych zależności -- interfejs webowy jest skompilowany do WASM i osadzony w binarce; brak żądań do CDN, brak zewnętrznych skryptów