Skip to content

chandra-gummaluru/beamer-plus

Repository files navigation

Beamer+

Beamer+ is a local, browser-based presentation tool for interactive lectures. It renders PDF slide decks (e.g. LaTeX Beamer output) and layers live features on top: pen and shape annotations, embedded video / audio / 3D models, interactive widgets (calculators, plotters, Python REPLs, maps, …), and real-time audience surveys with AI-powered response summarization.

Everything runs from a single Flask server — on your machine for solo use, or hosted by your university for multiple concurrent lectures. Each presenter creates a session and works at /s/{code}/; audience survey QR codes point to URLs under that same session prefix.

Quick start

Requires Python 3.10+.

pip install -r requirements.txt
python launch.py            # production launcher: HTTPS with a self-signed cert

Open the https://... URL the launcher prints, then Start a new session on the welcome screen (or go directly to /s/{code}/ if you already have a code). Browsers warn about the self-signed certificate — click Advanced → Proceed. HTTPS is needed so camera/microphone widgets work on LAN addresses.

For development there is a lighter entry point:

python app.py               # ad-hoc HTTPS cert (needs `cryptography`)
python app.py --http        # plain HTTP (camera widget disabled on LAN)

To try the built-in demo presentation, click the tour button in the bottom-left corner of the app.

Loading a presentation

Use the upload button (top-right) to load either:

  • A plain PDF — every page becomes a slide.
  • A presentation ZIP — a PDF plus saved configuration, media, widgets and AI models (see below). The in-app editor can add media/widgets to slides and save the result back out as a ZIP.

Presentation ZIP format

presentation.zip
├── slides.pdf                  # required — the slide deck
├── config/
│   ├── slide-order.json        # slide sequence: pdf pages, blank slides, split views, hidden flags
│   ├── s<N>.json               # per-slide config: embedded videos/audio/models/widgets + layout
│   ├── annotations.json        # saved pen strokes per slide
│   └── widget-states.json      # widget state snapshots so widgets resume where they left off
├── assets/ video/ models/ …    # media referenced by the configs
└── ai/
    └── <model>.py              # optional survey-summarization models (see below)

Surveys

Survey widgets generate a QR code that audience members scan to answer from their phones (open text, word cloud, or multiple choice). Responses stream back live over Socket.IO. Open-text responses can be clustered into thematic summaries by an AI model.

Two models ship built in:

  • claude — uses the Anthropic API (ANTHROPIC_API_KEY env var, or paste a key in the widget settings; requires pip install anthropic)
  • gpt4o — uses the OpenAI API (OPENAI_API_KEY; requires pip install openai)

Custom models

Drop a Python file in ai/ (server-wide) or inside a presentation ZIP under ai/. It must expose:

def summarize(responses: list[str], n: int, api_key: str | None = None):
    """Return a list of exactly n (summary_text, num_respondents) tuples."""

Widgets

Widgets are standalone HTML files in widgets/, rendered in iframes on slides. Built-ins include a browser, calculator, camera, circuit sandbox, function plotter, Jupyter-notebook runner, map, MCQ/survey/word-cloud panels, PDF textbook viewer, Python REPL, shell, timer, and YouTube player.

To add your own, drop an .html file in widgets/. A <script id="widget-schema" type="application/json"> block in the file describes the editable fields the editor shows for it, and widgets can sync state across instances by emitting widget_state over Socket.IO.

Security model

Beamer+ assumes a cooperative local network (a lecture hall, not the open internet):

  • Loading a presentation ZIP executes any ai/*.py inside it — only open ZIPs you trust.
  • Socket.IO accepts connections from any origin so widget iframes and audience devices can connect.
  • The TLS certificate is self-signed (cert.pem / key.pem, regenerated by launch.py; delete them to force regeneration).

Do not expose the server to the public internet.

Project layout

beamer-plus/
├── app.py                  # dev entry point (`python app.py`)
├── launch.py               # production launcher: HTTPS cert + startup info
├── server/                 # backend (Flask) — one module per concern
│   ├── core.py             #   Flask app + Socket.IO instances
│   ├── paths.py            #   BASE_PATH and derived folders
│   ├── state.py            #   in-memory shared state (surveys, presentation)
│   ├── ai_models.py        #   survey-summarization model loading
│   ├── pages.py            #   HTML pages + PWA files
│   ├── presentation.py     #   upload, ZIP assets, demo packaging
│   ├── widgets.py          #   widget serving, embeddability probe
│   ├── surveys.py          #   survey REST API
│   └── sockets.py          #   Socket.IO handlers
├── ai/                     # built-in survey-summarization models (plugin dir)
├── templates/              # audience-facing pages + presenter shell
├── static/
│   ├── css/                # tokens → base → components/ → features/
│   ├── js/
│   │   ├── main.js         #   orchestrator: state, navigation, rendering
│   │   ├── core/           #   event bus, canvas, modal, widget iframes
│   │   ├── slides/         #   navigator, thumbnails, structure, media, spotlight
│   │   ├── annotations/    #   toolbar, pen slots, shape tools
│   │   ├── app/            #   settings, help, tour, uploader
│   │   └── editor/         #   edit mode (overlays, properties, picker, save)
│   └── vendor/             # vendored third-party libraries (no CDN)
├── widgets/                # built-in widget HTML files (one file per widget)
├── demo/                   # bundled demo presentation (used by the tour)
├── tests/                  # pytest suite for the Flask API
├── manifest.json           # PWA manifest (served from /manifest.json)
└── service-worker.js       # PWA service worker (served from /)

Development

pip install -r requirements-dev.txt
pytest

Third-party frontend libraries are vendored in static/vendor/ so the app has no CDN dependency and works offline (some widgets still pull large optional libraries, e.g. Pyodide, from CDNs). The app is an installable PWA; bump the cache version in service-worker.js when changing static assets.

License

MIT — see LICENSE.

About

Resources

License

Stars

2 stars

Watchers

1 watching

Forks

Packages

 
 
 

Contributors