# Project export: Chalkboard

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: OpenAI Build Week
- Tagline: Chalkboard is an open-source collaborative whiteboard that lets teams and students draw, brainstorm, and collaborate in real time, making online learning and teamwork more interactive.
- Devpost: https://devpost.com/software/chalkboard-2xkdgs
- GitHub: https://github.com/Emmanuelmelvin/chalkboard
- Video: https://www.youtube.com/embed/D72u1GSgpJQ?enablejsapi=1&hl=en_US&rel=0&start=&version=3&wmode=transparent
- Team: 1 GitHub contributor(s) — Emmanuelmelvin (116 commits)

## Devpost submission (written by the team)

### Inspiration

I was inspired by how ineffective many online classes and virtual meetings can be. They often feel boring and lack the natural interaction of a physical classroom or meeting room. I wanted to bring back the simplicity and familiarity of a traditional chalkboard in a digital, collaborative environment. How I Built It I built Chalkboard as a real-time collaborative whiteboard where multiple users can draw, write, and brainstorm together. The goal was to recreate the experience of using a physical board while making it accessible from anywhere. Challenges One of the biggest challenges was ensuring a smooth real-time collaboration experience while keeping the interface simple and intuitive for users. What I Learned Building Chalkboard taught me more about real-time communication, collaborative applications, and designing an experience that feels natural for both education and teamwork.

## README (from the GitHub repository)

# Chalkboard

Chalkboard is a real-time collaborative canvas for shared thinking. It gives a team, classroom, workshop, or study group one room where people can draw, explain ideas, add context, and see one another’s work as it happens.

The product deliberately combines the feel of a physical classroom blackboard with the capabilities of a modern collaborative application: authenticated rooms, live cursors, synchronized strokes, room permissions, saved links, reactions, presence, and an extensible plugin platform.

![Chalkboard demo](demo-video/chalkboard-demo.gif)

A beta release of Chalkboard is live at [chalkboard.click](https://chalkboard.click).

## What problem does it solve?

Ideas are often developed across disconnected tools: a video call for conversation, a whiteboard for diagrams, a document for notes, and chat for links. That makes it difficult to keep the discussion, visual thinking, and next steps together.

Chalkboard solves this by providing a shared, persistent room where participants can:

- Draw and annotate the same canvas at the same time.
- Explain ideas with freehand chalk, shapes, links, notes, and built-in thinking tools.
- See who is present and where each person is working.
- Control access with open rooms, approval-based rooms, or password-protected rooms.
- Assign room roles so owners, instructors, and viewers have appropriate capabilities.
- Extend the board with trusted built-in plugins or reviewed community plugins.

## Main features

### Collaborative canvas

- Freehand chalk strokes with color, size, intensity, and chalk-dust styling.
- Eraser, selection, pan, and zoom tools.
- Shapes including lines, arrows, circles, rectangles, polygons, stars, hearts, crosses, and diamonds.
- Select, move, resize, rotate, duplicate, group, ungroup, trim, cut, copy, paste, and delete board content.
- Undo, redo, and clear-board actions synchronized to the room.
- Saved links that connect a label or reference to a location on the canvas.

### Live rooms

- Multiple users can join the same room and see updates in real time.
- Live cursors, display names, colors, presence counts, reactions, and raised hands.
- Room history is loaded when a participant joins or reconnects.
- Reconnection handling includes a short presence grace period to prevent flicker.
- Room owners can update member roles, remove members, and close rooms.
- Rooms can be open, approval-required, or password-protected.
- Rooms have themes such as classroom, workshop, brainstorm, meeting, planning, and studio.

- Users can submit bug reports, feature requests, and general feedback from the in-app widget, which is powered by [UserJot](https://userjot.com) and shows the roadmap and changelog the moment the project is configured. Product feedback is triaged in the UserJot dashboard.
- End-of-session room ratings (1–5 stars) are collected after a participant leaves a room and are shown to the room's owners and instructors in a Room experience panel on the dashboard. These stay in Chalkboard's own database; UserJot covers product feedback, not per-room session ratings.

### Authentication and access control

- Sign-in uses Google Identity Services.
- The backend verifies the Google credential and creates an HTTP-only session cookie.
- Room roles are `owner`, `instructor`, and `viewer`.
- Platform roles are `user`, `admin`, and `super_admin`.
- The admin console is protected by a separate TOTP-based two-factor session.

### Built-in and external plugins

The frontend includes a plugin runtime and bundled tools for notes, tags, statistics, and mathematical sets. The mathematical-set tools can insert items such as Venn diagrams, number lines, coordinate grids, and set symbols as normal Chalkboard strokes.

The Developer workspace also supports external plugin packages. A plugin can declare its identity, version, permissions, commands, tools, selection tools, and JavaScript entry bundle. Plugin releases move through a draft, review, approval, and publication lifecycle.

Example packages are available in [`plugin-artifacts/`](plugin-artifacts/), including [`Focus Dot`](plugin-artifacts/focus-dot/README.md) and [`Inscribed Circles`](plugin-artifacts/inscribed-circles/README.md).

## How the application works

```mermaid
flowchart LR
    Browser["React + TypeScript browser"]
    Vite["Vite dev server\n5173"]
    Backend["Node.js backend\nHono + Socket.IO\n3001"]
    Postgres[("PostgreSQL\nusers, rooms, plugins")]
    Redis[("Redis\ncanvas and live room state")]
    LiveKit["LiveKit\nvoice token service"]
    Storage["Local storage or\nCloudflare R2\nplugin assets"]

    Browser --> Vite
    Vite -->|"/api proxy"| Backend
    Vite -->|"/socket.io WebSocket proxy"| Backend
    Backend --> Postgres
    Backend --> Redis
    Backend --> LiveKit
    Backend --> Storage
```

The frontend talks to the backend through same-origin `/api` and `/socket.io` paths. In development, Vite proxies those paths to `http://localhost:3001`. In a production build, the backend can serve the compiled frontend from `frontend/dist` alongside the API and Socket.IO server.

The data responsibilities are intentionally split:

- PostgreSQL stores users, room metadata, room members, join requests, bans, plugin metadata, plugin versions, reviews, installations, and admin 2FA records.
- Redis stores the active room canvas strokes, saved links, Socket.IO adapter data, presence-related room state, raised hands, and BullMQ job data.
- LiveKit is used by the backend to mint scoped voice tokens for voice-enabled rooms.
- Plugin files are stored locally during development by default. Cloudflare R2 is supported for shared or production asset storage.

Because open-room canvas state is held in Redis rather than PostgreSQL, production Redis must be operated with an appropriate persistence and backup strategy.

## Repository structure

```text
chalkboard/
├── backend/                    # Hono API, Socket.IO server, workers, database access
│   ├── src/controllers/        # HTTP request parsing and response shaping
│   ├── src/db/                 # Drizzle schema and PostgreSQL client
│   ├── src/middlewares/        # Authentication, logging, rate limiting, errors
│   ├── src/realtime/           # Socket.IO room and collaboration events
│   ├── src/services/           # Room, auth, plugin, storage, and business logic
│   ├── src/validators/         # Zod request and socket payload validation
│   ├── src/workers/            # BullMQ background worker
│   ├── drizzle/                # Checked-in PostgreSQL migrations
│   ├── .env.example            # Backend environment template
│   └── package.json
├── frontend/                  # React/Vite application
│   ├── src/components/         # Canvas tools, UI controls, and shared components
│   ├── src/pages/              # Home, login, dashboard, lobby, board, and docs pages
│   ├── src/plugins/             # Plugin types, registry, bridge, and built-ins
│   ├── src/stores/              # Zustand application and board state
│   ├── src/hooks/               # Canvas interaction, rendering, sockets, shortcuts
│   └── package.json
├── plugin-artifacts/           # Example uploadable plugin ZIPs and source packages
├── demo-video/                 # Demo GIF, source frames, and demo generation script
├── plugin_implementation.md    # Detailed plugin design and implementation notes
├── LICENSE                     # Business Source License 1.1 for the core codebase
├── package.json                # Root TypeScript development dependency
└── README.md
```

## Technology stack

| Area | Technologies | Responsibility |
| --- | --- | --- |
| Frontend | React, TypeScript, Vite | Application UI and development/build tooling |
| Canvas | HTML5 Canvas, custom TypeScript renderers | Strokes, shapes, selection, transformations, and chalk effects |
| Frontend state | Zustand | Board, authentication, links, and logger state |
| Browser routing | Wouter | Home, login, dashboard, lobby, room, and

[README truncated for size]

## Detected evidence (automated analysis)

Indexed codebase: 274 recognized source files, 2093 KB.
- CSS (language) — detected in the code
- HTML (language) — detected in the code
- JavaScript (language) — detected in the code
- React (technology) — detected in the code
- Redis (technology) — detected in the code
- SQL (language) — detected in the code
- TypeScript (language) — detected in the code
- Node.js (technology) — claimed on Devpost, not found in the code
- PostgreSQL (technology) — claimed on Devpost, not found in the code

## Codebase structure (from repository index)

### Files (120 of 318)

```
.gitignore
.vscode/tasks.json
backend/.dockerignore
backend/.env.example
backend/Dockerfile
backend/drizzle.config.ts
backend/drizzle/0000_sleepy_vindicator.sql
backend/drizzle/0001_classroom_backend.sql
backend/drizzle/0001_room_lifecycle.sql
backend/drizzle/0002_purple_ultimatum.sql
backend/drizzle/0003_friendly_sleepwalker.sql
backend/drizzle/0004_room_password_ciphertext.sql
backend/drizzle/0005_complex_stingray.sql
backend/drizzle/0006_wild_tyrannus.sql
backend/drizzle/0007_plugin_platform.sql
backend/drizzle/0008_plugin_logo.sql
backend/drizzle/0009_plugin_bundle_code.sql
backend/drizzle/0010_plugin_bundle_archive.sql
backend/drizzle/0011_plugin_storage.sql
backend/drizzle/0012_billing.sql
backend/drizzle/0013_admin_billing_and_developer_pool.sql
backend/drizzle/0014_workspaces.sql
backend/drizzle/0015_flaky_darwin.sql
backend/drizzle/0016_bumpy_eddie_brock.sql
backend/drizzle/0017_tired_quentin_quire.sql
backend/drizzle/meta/_journal.json
backend/drizzle/meta/0000_snapshot.json
backend/drizzle/meta/0001_snapshot.json
backend/drizzle/meta/0002_snapshot.json
backend/drizzle/meta/0003_snapshot.json
backend/drizzle/meta/0004_snapshot.json
backend/drizzle/meta/0005_snapshot.json
backend/drizzle/meta/0006_snapshot.json
backend/drizzle/meta/0011_snapshot.json
backend/drizzle/meta/0012_snapshot.json
backend/drizzle/meta/0013_snapshot.json
backend/drizzle/meta/0014_workspaces_snapshot.json
backend/drizzle/meta/0015_snapshot.json
backend/drizzle/meta/0016_snapshot.json
backend/drizzle/meta/0017_snapshot.json
backend/package.json
backend/README.md
backend/src/config/env.ts
backend/src/controllers/admin.controller.ts
backend/src/controllers/auth.controller.ts
backend/src/controllers/billing.controller.ts
backend/src/controllers/community.controller.ts
backend/src/controllers/feedback.controller.ts
backend/src/controllers/metrics.controller.ts
backend/src/controllers/plugin.controller.ts
backend/src/controllers/room.controller.ts
backend/src/controllers/support.controller.ts
backend/src/controllers/workspace.controller.ts
backend/src/db/client.ts
backend/src/db/schema.ts
backend/src/index.ts
backend/src/middlewares/auth.middleware.ts
backend/src/middlewares/errorHandler.middleware.ts
backend/src/middlewares/rateLimit.middleware.ts
backend/src/middlewares/requestLogger.middleware.ts
backend/src/realtime/socket.ts
backend/src/routers/admin.route.ts
backend/src/routers/api.ts
backend/src/routers/auth.route.ts
backend/src/routers/billing.route.ts
backend/src/routers/feedback.route.ts
backend/src/routers/plugin.route.ts
backend/src/routers/room.route.ts
backend/src/routers/support.route.ts
backend/src/routers/workspace.route.ts
backend/src/scripts/bachs-setup.mjs
backend/src/scripts/backfill-seat-addons.ts
backend/src/scripts/backfill-workspaces.ts
backend/src/scripts/sendbyte-templates.mjs
backend/src/server.ts
backend/src/services/auth/adminAuth.service.ts
backend/src/services/auth/admins.service.ts
backend/src/services/auth/auth.service.ts
backend/src/services/billing/bachs.service.ts
backend/src/services/billing/billing.service.ts
backend/src/services/billing/developerPool.service.ts
backend/src/services/billing/entitlements.service.ts
backend/src/services/billing/workspaces.service.ts
backend/src/services/emails/emails.service.ts
backend/src/services/feedback/feedback.service.ts
backend/src/services/feedback/sentiment.ts
backend/src/services/infra/cleanup.service.ts
backend/src/services/infra/rateLimiter.service.ts
backend/src/services/infra/sentryMetrics.service.ts
backend/src/services/plugins/community.service.ts
backend/src/services/plugins/plugins.service.ts
backend/src/services/plugins/pluginStorage.service.ts
backend/src/services/rooms/livekit.service.ts
backend/src/services/rooms/realtimeRooms.service.ts
backend/src/services/rooms/roomPasswords.service.ts
backend/src/services/rooms/rooms.service.ts
backend/src/services/rooms/roomState.service.ts
backend/src/services/rooms/voiceMetering.service.ts
backend/src/templates/payment-failed.html
backend/src/templates/plan-upgrade.html
backend/src/templates/plugin.html
backend/src/templates/welcome.html
backend/src/templates/workspace-invite.html
backend/src/utils/error.ts
backend/src/utils/logger.ts
backend/src/utils/metrics.ts
backend/src/utils/money.ts
backend/src/utils/monitoring.ts
backend/src/utils/seats.ts
backend/src/validators/feedback.validator.ts
backend/src/validators/plugin.validator.ts
backend/src/validators/room.validator.ts
backend/src/validators/socket.validator.ts
backend/src/workers/worker.ts
backend/test/entitlements.test.ts
backend/test/feedback.sentiment.test.ts
backend/test/limits.test.ts
backend/test/money.test.ts
backend/test/retention.test.ts
backend/test/seats.test.ts
[198 more files omitted for size]
```

### Dependencies

- backend/package.json: @aws-sdk/client-s3@^3.1091.0, @aws-sdk/s3-request-presigner@^3.1091.0, @hono/node-server@^1.19.6, @sendbyte/node@^0.2.1, @sentry/hono@^10.69.0, @sentry/node@^10.24.0, @socket.io/redis-adapter@^8.3.0, @types/node@^24.10.1, axios@^1.19.0, bcryptjs@^3.0.3, bullmq@^5.64.1, drizzle-kit@^0.31.10, drizzle-orm@^0.45.1, google-auth-library@^10.5.0, hono@^4.10.7, livekit-server-sdk@^2.14.0, nodemon@^3.1.9, postgres@^3.4.7, redis@^5.10.0, socket.io@^4.8.3, tsup@^8.5.1, tsx@^4.20.6, typescript@^7.0.2, winston@^3.18.3, zod@^4.2.1
- frontend/package.json: @eslint/js@^10.0.1, @livekit/components-react@^2.9.23, @radix-ui/react-avatar@^1.2.6, @radix-ui/react-dropdown-menu@^2.1.24, @radix-ui/react-hover-card@^1.1.23, @radix-ui/react-slider@^1.4.7, @radix-ui/react-toggle-group@^1.1.19, @radix-ui/react-tooltip@^1.2.16, @sentry/react@^10.24.0, @sentry/vite-plugin@^5.4.0, @tanstack/react-query@^5.101.4, @types/node@^24.13.2, @types/react@^19.2.17, @types/react-dom@^19.2.3, @vitejs/plugin-react@^6.0.3, axios@^1.18.1, eslint@^10.6.0, eslint-plugin-react-hooks@^7.1.1, eslint-plugin-react-refresh@^0.5.3, globals@^17.7.0, livekit-client@^2.21.0, lucide-react@^1.23.0, react@^19.2.7, react-dom@^19.2.7, recharts@3.2.1, socket.io-client@^4.8.3, typescript@~6.0.2, typescript-eslint@^8.62.0, vite@^8.1.1, wouter@^3.10.0, zustand@^5.0.14
- package.json: typescript@^7.0.2
- pitch-deck/package.json: pptxgenjs@^3.12.0

### Recent commits (newest first)

- feat: implement backend core services including email queuing, billing and developer revenue pool, plugin management, auth, and infrastructure utilities.
- feat: implement workspace and membership management UI with integrated subscription and invitation flows
- feat: add pitch deck generator script and support assets
- feat: add pitch deck generator and frontend TypeScript configuration
- feat: implement NotesLayer component for auto-measuring and rendering text notes
- added demon at file
- added an option for a plugin to need a preview or not. It is false by fault.
- changed email template of chalkboard.
- feat: implement useBoardSocket hook to manage collaborative state and socket event listeners
- edited view for chalkboard.
- created simple email for supporting customers.
- added support for chalkboard.
- edited email templates to use hosted favicon.
- Serve admin console at /admin without redirect
- Redirect /admin to admin console entry
- Fix missing await in Google auth handler
- Log error cause chain in unhandled request errors
- edits.
- Resolve backend hostname dynamically in nginx
- Add nginx Dockerfile for frontend with api and socket.io proxy

## Key source files (fetched from GitHub, selected and truncated for size)

### WALKTHROUGH.md

```markdown
# Chalkboard — Feature Walkthrough & Demo Guide

> A personal note before we begin: this project means a lot to me. I built it as a student who has sat through countless online classes where ideas got lost across five different tabs. I genuinely believe a tool like this could make collaborative learning feel more human, and I would love to see it get used by real classrooms and teams. If you are reading this, thank you for taking the time to look at it.

---

## What You Are Looking At

Chalkboard is a real-time collaborative canvas — think of a physical classroom blackboard, but shared over the internet. Multiple people can draw, annotate, and think together on the same surface at the same time, with live cursors, presence indicators, and synchronized strokes.

The demo GIF in the repository shows the core experience: a shared canvas where strokes appear instantly, tools switch fluidly, and the board feels alive.
g
---

## Who It Is For

Chalkboard started as a classroom idea, but the shared-canvas model is not limited to teaching. The room themes (Classroom, Workshop, Brainstorm, Meeting, Planning, Studio) exist precisely because the same board fits very different rooms:

- **Classrooms and tutoring** — a teacher works through a problem while students annotate and raise hands. The Mathematical Set plugin makes maths lessons genuinely practical: Venn diagrams, number lines, coordinate grids, and set symbols in a couple of clicks.
- **Board and executive meetings** — sketch org structures, decision trees, and quarterly plans live while everyone watches the same surface. Role controls mean the chair can present with viewers in read-only mode, then promote a colleague to instructor when it is their turn to contribute.
- **Product and design workshops** — user flows, wireframe sketches, and affinity mapping. Saved links let a large board stay navigable by naming and jumping to sections.
- **Engineering and architecture reviews** — system diagrams, sequence sketches, and incident timelines drawn together instead of one person screen-sharing a static diagram.
- **Study groups and peer tutoring** — students work problems side by side without needing to be in the same building.
- **Interviews and technical assessments** — a candidate sketches their thinking on a shared board while the interviewer observes, and the whole session stays visible in one place.
- **Research and thesis planning** — mind maps, literature relationships, and argument structures built up across sessions since the room persists.
- **Community and non-profit planning** — event layouts, budgets sketched visually, volunteer assignments.

The pattern that ties these together: any conversation where people need to *point at the same thing* while talking. Chalkboard gives that to a group, with authenticated rooms and permissions so it can be used for real work rather than only casual doodling.

---


## Running It for Real Collaboration

Because Chalkboard uses **Google Sign-In**, Google
[truncated — 9103 more characters]
```

### plugin_implementation.md

```markdown
# Chalkboard Plugin Implementation Plan

## 1. Purpose

This document describes a recommended implementation plan for adding a Figma-like plugin system to Collaborative Chalkboard.

The goal is to let Chalkboard support installable, configurable, collaborative plugin packs. For example, a `Mathematical Set` plugin could add set theory symbols, Venn diagrams, number lines, coordinate grids, and math teaching templates to the chalkboard experience.

The recommended approach is to start with a safe, first-party plugin architecture and evolve toward a marketplace-style system once the core extension points are stable.

---

## 2. Product Vision

Chalkboard is already a collaborative canvas application. A plugin system should extend the board without requiring every feature to live in the core app.

Plugins should be able to contribute:

- Toolbar buttons.
- Insertable shapes and templates.
- Commands and command palette actions.
- Side panels and modal interfaces.
- Canvas object generators.
- Room-aware collaborative actions.
- Optional backend-powered services.

Example plugin categories include:

- **Mathematical Set**: set symbols, Venn diagrams, number lines, grids, proof templates.
- **Geometry Kit**: rulers, compasses, angles, polygons, transformations.
- **Chemistry Kit**: molecules, bonds, reaction arrows, periodic table snippets.
- **Music Staff**: staves, notes, clefs, chord diagrams.
- **Teacher Templates**: Cornell notes, quizzes, diagrams, classroom games.
- **Mind Mapping**: nodes, connectors, automatic layouts.

---

## 3. Recommended Implementation Strategy

Do not begin with a fully public marketplace. The safer and more maintainable path is incremental.

### Phase 1: First-Party Plugin Runtime

Build the internal plugin API, registry, and UI integration. Plugins are trusted and bundled with the app.

### Phase 2: Built-In Plugin Packs

Implement the first plugin, `Mathematical Set`, as a bundled plugin using the same public plugin API that future third-party plugins will use.

### Phase 3: Install/Enable Configuration

Add frontend configuration for enabling and disabling plugins per user or per room.

### Phase 4: Backend Persistence

Persist plugin installation and configuration state in the backend.

### Phase 5: Sandboxed Third-Party Plugins

Load remote plugins in sandboxed iframes using a message bridge and explicit permissions.

### Phase 6: Marketplace

Add marketplace listing, versioning, review, permissions, author verification, and signed manifests.

---

## 4. Core Concepts

### 4.1 Plugin

A plugin is an extension package that registers tools, commands, panels, insertable objects, or collaborative behavior.

```ts
export interface ChalkboardPlugin {
  id: string;
  name: string;
  version: string;
  activate(api: ChalkboardPluginAPI): void | Promise<void>;
  deactivate?: () => void | Promise<void>;
}
```

### 4.2 Manifest

A manifest describes what a plugin is and what it contributes before the plugin code executes.

`
[truncated — 22236 more characters]
```

### package.json

```
{
  "devDependencies": {
    "typescript": "^7.0.2"
  }
}

```

### frontend/Dockerfile

```
FROM node:22-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM nginx:alpine
ENV BACKEND_URL=http://api:3001
COPY nginx.conf.template /etc/nginx/templates/default.conf.template
COPY --from=build /app/dist /usr/share/nginx/html
EXPOSE 80

```

### pitch-deck/package.json

```
{
  "name": "chalkboard-pitch-deck",
  "private": true,
  "version": "1.0.0",
  "description": "Generates the Chalkboard pitch deck (.pptx) using the dashboard design system.",
  "type": "module",
  "scripts": {
    "generate": "node generate.mjs"
  },
  "dependencies": {
    "pptxgenjs": "^3.12.0"
  }
}
```

### backend/Dockerfile

```
FROM node:22-alpine AS build
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM node:22-alpine AS runtime
ENV NODE_ENV=production
WORKDIR /app
COPY package.json package-lock.json ./
COPY --from=build /app/node_modules ./node_modules
COPY --from=build /app/dist ./dist
# Migrations run from this image (one-off job) before a deploy accepts traffic.
COPY --from=build /app/drizzle ./drizzle
COPY --from=build /app/drizzle.config.ts ./drizzle.config.ts
EXPOSE 3001

# Env vars come from the platform (Aeroplane), not from a .env file. The worker
# is the same image started with PROCESS_TYPE=worker. Migrations run on every
# start; drizzle-kit records applied migrations in the database, so re-runs are
# no-ops and a fresh database is migrated before the server accepts traffic.
CMD ["sh", "-c", "node node_modules/drizzle-kit/bin.cjs migrate && node dist/index.js"]
```

### frontend/package.json

```
{
  "name": "frontend",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "tsc -b && vite build",
    "lint": "eslint .",
    "preview": "vite preview"
  },
  "dependencies": {
    "@livekit/components-react": "^2.9.23",
    "@radix-ui/react-avatar": "^1.2.6",
    "@radix-ui/react-dropdown-menu": "^2.1.24",
    "@radix-ui/react-hover-card": "^1.1.23",
    "@radix-ui/react-slider": "^1.4.7",
    "@radix-ui/react-toggle-group": "^1.1.19",
    "@radix-ui/react-tooltip": "^1.2.16",
    "@sentry/react": "^10.24.0",
    "@tanstack/react-query": "^5.101.4",
    "axios": "^1.18.1",
    "livekit-client": "^2.21.0",
    "lucide-react": "^1.23.0",
    "react": "^19.2.7",
    "react-dom": "^19.2.7",
    "recharts": "3.2.1",
    "socket.io-client": "^4.8.3",
    "wouter": "^3.10.0",
    "zustand": "^5.0.14"
  },
  "devDependencies": {
    "@eslint/js": "^10.0.1",
    "@sentry/vite-plugin": "^5.4.0",
    "@types/node": "^24.13.2",
    "@types/react": "^19.2.17",
    "@types/react-dom": "^19.2.3",
    "@vitejs/plugin-react": "^6.0.3",
    "eslint": "^10.6.0",
    "eslint-plugin-react-hooks": "^7.1.1",
    "eslint-plugin-react-refresh": "^0.5.3",
    "globals": "^17.7.0",
    "typescript": "~6.0.2",
    "typescript-eslint": "^8.62.0",
    "vite": "^8.1.1"
  }
}

```

### backend/package.json

```
{
  "name": "backend",
  "version": "1.0.0",
  "type": "module",
  "main": "dist/index.js",
  "scripts": {
    "build": "tsup",
    "start": "node --env-file=.env dist/index.js",
    "dev": "node --env-file=.env --import tsx --watch src/index.ts",
    "check": "tsc --noEmit",
    "test": "node --env-file=.env --import tsx --test \"test/**/*.test.ts\"",
    "backfill:workspaces": "node --env-file=.env --import tsx src/scripts/backfill-workspaces.ts",
    "backfill:seat-addons": "node --env-file=.env --import tsx src/scripts/backfill-seat-addons.ts",
    "templates:push": "node --env-file=.env src/scripts/sendbyte-templates.mjs",
    "verify": "npm run check && npm run build",
    "db:generate": "node --env-file=.env node_modules/drizzle-kit/bin.cjs generate",
    "db:migrate": "node --env-file=.env node_modules/drizzle-kit/bin.cjs migrate"
  },
  "dependencies": {
    "@aws-sdk/client-s3": "^3.1091.0",
    "@aws-sdk/s3-request-presigner": "^3.1091.0",
    "@hono/node-server": "^1.19.6",
    "@sendbyte/node": "^0.2.1",
    "@sentry/hono": "^10.69.0",
    "@sentry/node": "^10.24.0",
    "@socket.io/redis-adapter": "^8.3.0",
    "axios": "^1.19.0",
    "bcryptjs": "^3.0.3",
    "bullmq": "^5.64.1",
    "drizzle-orm": "^0.45.1",
    "google-auth-library": "^10.5.0",
    "hono": "^4.10.7",
    "livekit-server-sdk": "^2.14.0",
    "postgres": "^3.4.7",
    "redis": "^5.10.0",
    "socket.io": "^4.8.3",
    "winston": "^3.18.3",
    "zod": "^4.2.1"
  },
  "devDependencies": {
    "@types/node": "^24.10.1",
    "drizzle-kit": "^0.31.10",
    "nodemon": "^3.1.9",
    "tsup": "^8.5.1",
    "tsx": "^4.20.6",
    "typescript": "^7.0.2"
  }
}

```

### plugin-artifacts/inscribed-circles/package.json

```
{
  "name": "demo.inscribed-circles",
  "private": true,
  "version": "0.1.0",
  "description": "A small external Chalkboard plugin that draws two concentric circles.",
  "main": "index.js",
  "files": [
    "manifest.json",
    "index.js",
    "logo.svg",
    "README.md"
  ]
}

```

### plugin-artifacts/focus-dot/package.json

```
{
  "name": "demo.focus-dot",
  "private": true,
  "version": "0.1.0",
  "description": "A small external Chalkboard plugin used to simulate upload, review, and catalogue publishing.",
  "main": "index.js",
  "files": [
    "manifest.json",
    "index.js",
    "logo.svg",
    "README.md"
  ]
}

```

[262 more indexed source files omitted to keep this export small. The full file list is in the Codebase structure section above.]