Anonymous Q&A rooms for lectures and live sessions
Ghost Room is a web application for university lectures, seminars, and live events that lets students ask questions anonymously while giving lecturers a structured way to manage them.
- Production: https://ghostroom.fi
- Repository: https://github.com/KristopherZlo/live-chat-vamk (source code is publicly visible, but the license is not open-source)
OPEN BETA
Latest automated capture: docs/screenshots/latest
Light Theme
Dark Theme
- Host (lecturer) creates a room and shares a public link or QR code.
- Participants (students) join the room and post chat messages or mark messages as questions.
- Questions appear in a private queue visible only to the host.
- The host reviews questions, changes their status, and responds when appropriate.
- Private question queue with statuses:
new,answered,ignored,later - Sound notification on new questions
- Picture-in-Picture question queue
- Moderation tools (remove questions, ban participants)
- Anonymous participation (chat + questions)
- Reactions and threaded replies
- Personal "My Questions" panel
- Delete own questions and rate answers
- Live updates via WebSockets (polling fallback if unavailable)
- Optimistic UI updates for smooth interaction
- Designed for academic audiences (~150–250 participants); messages/questions are loaded in chunks
- Browser-only usage (no mobile apps required)
- Open registration with email verification
- CSRF / XSRF protection
- Throttling for registration, login, and messaging
- Host-only private moderation / question queue channel
- Ban lockout enforced across room read and write endpoints using participant session, IP, and fingerprint
- Strict permission checks for all moderation actions
- Production CSP without runtime CDN dependencies on the room page
- Laravel 12
- Blade templates
- REST APIs + Events
- Laravel Echo (WebSockets)
- Vite
- Tailwind CSS
- Vanilla JavaScript + TypeScript
- PostCSS
- MySQL / MariaDB
- Redis (optional)
- Queue workers
- Cookies and sessions
- PHP 8.2+ with extensions:
pdo_mysql/pdo_pgsqlmbstringopenssljsonctypefileinfo
- Composer 2.x
- Node.js 18+ and npm
- MariaDB / MySQL 10.5+ (or compatible)
- Redis (optional — DB is used by default for cache, sessions, and queues)
git clone https://github.com/KristopherZlo/live-chat-vamk.git
cd live-chat-vamk
cp .env.example .env
composer install
npm install
php artisan key:generate
# create database and set DB_* variables in .env
php artisan migrate
php artisan serve # http://localhost:8000
npm run dev # assets + HMRIf using queues (QUEUE_CONNECTION=database), run a worker in another terminal:
php artisan queue:workgit clone https://github.com/KristopherZlo/live-chat-vamk.git
cd live-chat-vamk
cp .env.example .env
# set APP_ENV=production
# set APP_DEBUG=false
# set APP_URL=https://your-domain
# configure database credentials
composer install --no-dev --optimize-autoloader
php artisan key:generate
php artisan migrate --force
npm install
npm run buildDeployment notes:
- Ensure
storage/andbootstrap/cache/are writable by the web server. - Point the web server document root to
public/. - Keep the Reverb server running for live updates.
- Add a cron entry for
* * * * * php artisan schedule:run. - Queue workers are optional for the current beta release; add
php artisan queue:workonly if you move mail or other background jobs to a queue.
Minimum production services:
- PHP app
- MySQL / MariaDB
- Reverb
- mail delivery
- cron for
php artisan schedule:run
Required production env:
APP_ENV=productionAPP_DEBUG=falseAPP_URL=https://your-domainBROADCAST_CONNECTION=reverb- valid
REVERB_APP_ID,REVERB_APP_KEY,REVERB_APP_SECRET,REVERB_HOST,REVERB_PORT,REVERB_SCHEME - valid
MAIL_*settings SESSION_SECURE_COOKIE=truewhen serving over HTTPS
Preflight before a public rollout:
composer install --no-dev --optimize-autoloadernpm install && npm run buildphp artisan migrate --forcephp artisan config:cachephp artisan route:cachevendor/bin/phpstan analyse --no-progresscomposer auditnpm audit --omit=dev- green CI for
php artisan test
Rollback basics:
- redeploy the previous release
- restore the previous
public/buildassets - run
php artisan config:clearandphp artisan route:clear - verify
/up, a public room page, Reverb connectivity, and email delivery
- Run tests:
php artisan test - Clear config cache:
php artisan config:clear - Rebuild frontend assets:
npm run build
Use Playwright to capture all static GET pages from php artisan route:list --json in both light and dark themes.
- Install browser binaries once:
npm run ui:screenshots:install - Start the app locally (for example in another terminal):
php artisan serve --host=127.0.0.1 --port=8000 - Optional for authenticated pages:
set
SCREENSHOT_AUTH_EMAILandSCREENSHOT_AUTH_PASSWORD - Run capture:
npm run ui:screenshots
Useful env vars:
SCREENSHOT_BASE_URL(defaulthttp://127.0.0.1:8000)SCREENSHOT_OUTPUT_DIR(defaultinterface-screenshots-auto)SCREENSHOT_VIEWPORT(default1920x1080)SCREENSHOT_WAIT_MS(default450)SCREENSHOT_TIMEOUT_MS(default30000)SCREENSHOT_NAV_RETRIES(default3, retries navigation on5xxresponses)SCREENSHOT_INCLUDE_TEST_ROUTES=1(include__test/*routes)SCREENSHOT_DISABLE_ONBOARDING_MODALS=0(by default welcome/what's-new/tutorial modals are suppressed)SCREENSHOT_PRELOAD_LAST_VISITED_ROOMS=0(by default preloads 9 demo "Last visited" rooms for join page screenshots)SCREENSHOT_SEED_ROOM_DEMO=0(by default runschat:seed-demobefore capture)SCREENSHOT_SEED_ROOM_SLUG(defaultneo-zion-briefing)SCREENSHOT_SEED_DEMO_COUNT(default90)SCREENSHOT_EXTRA_GUEST_ROUTES(comma-separated, e.g./r/custom-room)SCREENSHOT_EXTRA_AUTH_ROUTES(comma-separated, e.g./dashboard,/profile)SCREENSHOT_USE_HMR=1(by default the script temporarily disablespublic/hotso screenshots use built assets)
By default, routes containing presentation, plus /admin, /broadcasting/auth, /legal/privacy, and /verify-email, are skipped.
The seeded public room route (/r/<slug>) is captured in both guest and auth modes.
Each run writes screenshots into a timestamped folder and a manifest.json with captured/skipped/failed pages.
- Seed a room with demo chat data (messages, replies, questions, reactions):
php artisan chat:seed-demo <room-id-or-slug> [--count=200] [--delay=0]php artisan chat:seed-questions <room-id-or-slug> [--count=50]php artisan chat:seed-messages <room-id-or-slug> [--count=200]php artisan chat:seed-poll <room-id-or-slug> [--options=] [--votes=] [--replies=] [--reactions=] [--participants=] - Stream continuous demo activity (messages, replies, questions, reactions, poll votes):
php artisan chat:stream-demo <room-id-or-slug> [--delay=1-3] [--participants=8] - Simulate a live question stream (with a delay between questions):
php artisan chat:seed-questions <room-id-or-slug> [--count=50] [--delay=1]
- Polls and live voting
- Further loading and performance optimizations
- Interactive onboarding tutorial for hosts and students
- Email verification
The source code is publicly available for review and learning purposes. The project is not open-source, and reuse or redistribution is restricted.
Created and maintained by KristopherZlo. Originally developed for university use.






















