Multi-Frontend Architecture
Channel Abstraction
The MessageChannel abstraction in src/channels.py provides a unified interface for sending messages regardless of which frontend a participant is using.
Implementations
TelegramChannel-- wraps python-telegram-bot's messaging APIWebSocketChannel-- sends JSON messages over WebSocket connections
Abstract Types
| Type | Description |
|---|---|
Button | Represents a button with label, callback_data, url, and web_app_url fields |
Keyboard | Contains rows of Button objects for inline keyboard layouts |
SentMessage | Wraps channel-specific message IDs as a string for uniform handling |
Shared Survey Logic
Pure survey logic lives in src/survey_logic.py with no Telegram dependency. This module is shared by both frontends:
src/handlers/survey.py-- Telegram survey handlersrc/api_webapp.py-- WebSocket survey handler
Both call the same functions for question rendering, response validation, session progression, and branching logic.
PWA Frontend
The PWA lives in the pwa/ directory and is built with:
- React + TypeScript for the UI
- Tailwind CSS 4 for styling
- Vite as the build tool
It connects to the backend via WebSocket through src/api_webapp.py. The production build output (pwa/dist/) is served as static files by the FastAPI server.
Adding a New Frontend
To add a new frontend (e.g., a native mobile app, a different messaging platform):
- Implement the
MessageChannelinterface insrc/channels.py - Wire up message handling for your transport (HTTP, WebSocket, SDK, etc.)
- Reuse the functions in
src/survey_logic.pyfor survey delivery and response handling
No changes to the core survey engine or database layer should be necessary.