Files
Infosec/Presentation system/v1.3
2026-09-13 20:09:20 +01:00
..
2026-09-13 20:09:20 +01:00
2026-09-13 20:09:20 +01:00
2026-09-13 20:09:20 +01:00

MPS — Martinhal Presentation System

A self-hosted app that turns any presentation into a link and a QR code. Upload a video, PowerPoint, Word doc, Excel sheet, PDF, or image; the app converts it to a browser-friendly format and generates a QR code. Anyone who scans it watches along on their own phone — live and in sync with the presenter, or browsing at their own pace.

Everything runs in a single Docker container. No cloud, no third-party services except the mail account you choose to connect for email sharing.

Version 1.3 · © 2026 Martinhal IT — Joao Vaz


What's new in 1.3

  • First-run setup. The very first time you open the app it asks you to create the administrator account — no default password to remember or change.
  • Rebranded as MPS — Martinhal Presentation System, with the MPS logo across the app.
  • QR Code button on every ready presentation opens the code on its own page in large format — ideal for putting on a projector. It has copy-link, fullscreen and print actions.
  • Bigger presentation cards on the host dashboard (twice as wide, 50% taller) so the QR preview and controls are easier to use.

From 1.2

Login page and user accounts, admin-only user management, mail settings and activity logs, email sharing, PurelyMail SMTP+IMAP with a copy saved to Sent, and First/Last slide controls.


Quick start (Docker Compose)

# Point QR codes at an address phones can actually reach (LAN IP or public URL).
export PUBLIC_BASE_URL=http://192.168.1.50:3000

docker compose up --build -d

Open http://<host>:3000. On first launch you'll be asked to create the admin account. After that, sign in, upload a file, and hit Present. Show the QR code (Share / QR, or the QR Code button for a full-screen page) and the room scans to join.

Unattended installs: if you'd rather not use the setup screen, set ADMIN_USERNAME and ADMIN_PASSWORD before the first start and an admin will be pre-created from those values instead. They're ignored once an account exists.

Plain Docker

docker build -t mps .
docker run -d --name mps \
  -p 3000:3000 \
  -e PUBLIC_BASE_URL=http://192.168.1.50:3000 \
  -v qr_data:/data \
  mps

Without Docker (Node 18+)

Requires libreoffice, ffmpeg, and fonts on the host.

npm install
npm run fetch-vendor   # vendors PDF.js for offline use
npm start

Updating (no data loss)

All state — user accounts, mail settings, logs, uploaded decks — lives under the /data volume, never inside the app code. To update:

  1. Unzip the new version over your existing project folder (code files are replaced; your data/ and the Docker qr_data volume are left untouched).

  2. Rebuild and restart:

    docker compose up --build -d
    

Your admin account, users, presentations, and mail configuration carry straight over, and the first-run setup screen does not reappear.


Users & roles

Role Can do
admin Everything: manage users, configure mail, view logs, see and manage all presentations.
user Sign in, upload and present their own decks, share them (link, QR, email).

The first admin is created during setup. Manage further accounts at /users (admins only). The app prevents removing or demoting the last remaining admin, and you can't delete your own account.


Sharing a presentation

Each ready presentation offers several ways to get people in:

  • QR Code — opens a dedicated full-screen page with a large, scannable code (plus copy-link, fullscreen, and print). Great for a projector or printed handout.
  • Share / QR (in the presenter view) — a quick pop-over with the code and link.
  • Copy link — the plain audience URL.
  • Email — sends the link and QR straight to recipients (requires mail set up).

Email sharing (PurelyMail)

  1. Sign in as an admin → Manage users → Mail.

  2. Tick Enable email sending, enter the PurelyMail account email and password. Servers are prefilled and match PurelyMail's settings:

    Host Port Security
    SMTP (send) smtp.purelymail.com 465 SSL/TLS
    IMAP (Sent copy) imap.purelymail.com 993 SSL/TLS
  3. Save, then Send test to confirm it works.

Every message is delivered over SMTP and a copy is appended to the Sent folder over IMAP, so it appears in your normal mail client. The stored mail password lives only in /data/config.json on your server and is never sent back to the browser.


Presenting

  • Slides: « First · Prev · Next · Last », or the keys Home End.
  • Synced ↔ Free browse: in Synced mode the audience follows you; in Free browse they move on their own. Audience members who wander off get a one-tap "Rejoin presenter".
  • Video: play / pause / seek are broadcast to everyone. Viewers tap once to allow sound (browsers block autoplay audio until then).

Supported formats

Input Handled as Tool
.pdf paged deck served directly
.pptx .ppt .odp .pps .ppsx paged deck LibreOffice → PDF
.docx .doc .odt .rtf .txt .md paged deck LibreOffice → PDF
.xlsx .xls .ods .csv .tsv paged deck LibreOffice → PDF
.mp4 .webm .ogg synced video served directly
.mov .avi .mkv .wmv .flv .3gp .mpeg .ts synced video ffmpeg → MP4
.png .jpg .jpeg .gif .webp .svg .bmp .avif image served directly

Configuration

Variable Default Purpose
PUBLIC_BASE_URL derived from request Absolute URL encoded in QR codes / links. Set this.
ADMIN_USERNAME admin Only for unattended pre-seed (see Quick start).
ADMIN_PASSWORD (unset) If set on first run, pre-creates an admin instead of showing setup.
ADMIN_EMAIL (empty) Email for a pre-seeded admin.
MAX_UPLOAD_MB 500 Maximum upload size.
PORT 3000 Listen port.
DATA_DIR /data (Docker) Where all state is stored. Mount as a volume.
CONVERT_TIMEOUT_MS 240000 Per-file conversion timeout.

Security notes

  • Put a reverse proxy with HTTPS in front for anything beyond a trusted LAN, and set PUBLIC_BASE_URL to the https address.
  • Passwords are stored as salted scrypt hashes. Login sessions are HttpOnly cookies.
  • The container runs as a non-root user; all state stays on the mounted volume.

License

MIT.