A unified, AI-powered student productivity dashboard that aggregates Canvas LMS, campus events, and student job listings into a single real-time interface — with an intelligent chat assistant capable of answering questions about your coursework, assignments, and files.
DuckBoard solves the context-switching problem every Stevens student faces: Canvas for assignments, a separate portal for campus events, another site for student jobs, and no single place to get AI-assisted answers about your specific coursework.
Key capabilities:
- Canvas LMS integration — live assignments, courses, modules, and file access
- Campus events feed — DuckLink RSS parsed and surfaced in-app
- Workday student jobs — scraped via Puppeteer and displayed with one-click apply
- Duck AI chat sidebar — RAG-powered assistant using your actual Canvas files as context
- Daily AI briefing — LLM-generated morning summary of deadlines and upcoming events
- Progressive Web App — installable, offline-capable, with Web Push notifications
- Semantic file search — vector embeddings over Canvas course documents
┌─────────────────────────────────────────────────────────┐
│ Next.js 16 App Router │
│ ┌──────────────┐ ┌──────────────┐ ┌───────────────┐ │
│ │ Canvas API │ │ AI / RAG │ │ PWA / Push │ │
│ │ Proxy Route │ │ Chat Route │ │ Notification │ │
│ └──────┬───────┘ └──────┬───────┘ └───────────────┘ │
│ │ │ │
│ ┌──────▼───────┐ ┌──────▼───────┐ │
│ │ Upstash │ │ LangChain │ │
│ │ Redis │ │ + HuggingFace│ │
│ │ (encrypted │ │ Mistral-7B │ │
│ │ tokens) │ │ Embeddings │ │
│ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────┘
│
┌───────────▼──────────┐
│ Scraper Service │
│ Express + Puppeteer│
│ port 3001 │
│ ┌─────────────────┐ │
│ │ Workday Jobs │ │
│ │ Canvas OAuth │ │
│ │ (Okta + SAML) │ │
│ └─────────────────┘ │
└──────────────────────┘
-
Canvas data — User provides a Personal Access Token (PAT) via onboarding. PAT is AES-256-CBC encrypted and stored in Upstash Redis. All Canvas API requests are proxied server-side to avoid CORS and keep the token server-bound.
-
AI Chat (RAG pipeline):
- Canvas files are fetched and chunked at query time
sentence-transformers/all-MiniLM-L6-v2generates embeddings (HuggingFace Inference API)- LangChain
MemoryVectorStoreperforms cosine similarity search - Retrieved document chunks are injected as context into the Mistral-7B prompt
- Session history maintained in server-side
Mapfor multi-turn conversation
-
Workday scraper — Runs as a separate Express microservice. Puppeteer controls a headless Chromium browser to authenticate through Stevens' Workday instance and extract student job listings. Credentials are encrypted before transmission between Next.js and the scraper.
-
Push notifications — VAPID-signed Web Push via the
web-pushlibrary. Subscription endpoints stored in Redis. Service worker receives and displays push events.
| Technology | Version | Purpose |
|---|---|---|
| Next.js | 16.2.2 | App Router, SSR, API routes, Turbopack |
| React | 19 | UI with concurrent features |
| TypeScript | 5.x | Full-stack type safety |
| Tailwind CSS | 3.x | Utility-first styling |
| PWA / Service Worker | Web API | Offline support, installability |
| Web Push API | W3C spec | Push notifications |
| Technology | Version | Purpose |
|---|---|---|
| LangChain | 0.3.x | RAG pipeline orchestration |
@langchain/community |
0.3.x | HuggingFace embeddings adapter |
| HuggingFace Inference API | REST | Mistral-7B-Instruct + MiniLM embeddings |
| Upstash Redis | Serverless | Encrypted token storage, user data |
Node.js crypto |
Built-in | AES-256-CBC encryption |
| Technology | Version | Purpose |
|---|---|---|
| Express | 4.x | HTTP server for scraper endpoints |
| Puppeteer | 22.x | Headless Chromium automation |
| TypeScript | 5.x | Type-safe scraper code |
- Canvas LMS REST API —
sit.instructure.com/api/v1/* - Stevens DuckLink RSS — Campus events feed
- Stevens Workday — Student job listings (scraped)
- HuggingFace Inference API —
mistralai/Mistral-7B-Instruct-v0.3,sentence-transformers/all-MiniLM-L6-v2
- Active course listing with enrollment details
- Assignment tracking with due dates, point values, and submission status
- Course file browser with type-aware icons
- Module structure and content access
- Server-side proxying keeps PAT secure
- Retrieval-Augmented Generation (RAG) — answers grounded in your actual Canvas files
- Natural language queries: "What's due this week?", "Summarize the lecture notes from CS 546"
- Multi-turn conversation with session memory
- Automatic context building from Canvas + events + jobs data
- Daily briefing generation with LLM summarization
- Vector embeddings of Canvas course documents
- Cosine similarity search with
MemoryVectorStore - Relevant document chunks injected into AI prompts
- DuckLink events RSS feed with real-time parsing
- Student job listings from Workday (scraped)
- Unified timeline view
- Installable on desktop and mobile
- Service worker with cache-first strategies
- Web Push notification subscriptions
- Offline fallback UI
- AES-256-CBC encryption for all stored credentials and tokens
- Server-side only token access (never exposed to client)
- CORS-safe Canvas API proxy
- Encrypted credential transmission to scraper service
- Node.js 18+
- A Stevens student Canvas account at
sit.instructure.com - HuggingFace account (free tier works)
- Upstash Redis instance (free tier works) or use the built-in in-memory fallback
git clone https://github.com/deepakSingh-dev/duckboard.git
cd duckboard
npm install
# Scraper service
cd scraper && npm install && cd ..cp .env.example .env.localEdit .env.local:
# HuggingFace — get a free key at huggingface.co/settings/tokens
HUGGINGFACE_API_KEY=hf_your_key_here
# Encryption — any random 32+ character string
ENCRYPTION_SECRET=your_random_secret_here
# Web Push VAPID keys — generate with: npx web-push generate-vapid-keys
VAPID_PUBLIC_KEY=your_vapid_public_key
VAPID_PRIVATE_KEY=your_vapid_private_key
VAPID_SUBJECT=mailto:your@email.com
# Upstash Redis — get free instance at upstash.com
# Leave as-is to use the built-in in-memory fallback (dev only)
UPSTASH_REDIS_REST_URL=your_upstash_url
UPSTASH_REDIS_REST_TOKEN=your_upstash_token
# Scraper service URL
SCRAPER_URL=http://localhost:3001
# Cron job secret (any random string)
CRON_SECRET=your_cron_secret# Terminal 1 — Next.js
npm run dev
# Terminal 2 — Scraper microservice
cd scraper && npm run devOpen http://localhost:3000.
Navigate to /onboarding. You have two options:
Option A — DevTools Console (easiest, no PAT management)
- Log in to
sit.instructure.comin the same browser - Open DevTools Console (F12) on the Canvas tab
- Paste and run the snippet shown on the onboarding page
- The snippet generates a PAT via Canvas API and redirects back automatically
Option B — Manual PAT
- Go to Canvas → Account → Settings → New Access Token
- Paste the token into the onboarding form
duckboard/
├── src/
│ ├── app/
│ │ ├── api/
│ │ │ ├── ai/ # LangChain RAG chat endpoint
│ │ │ ├── briefing/ # Daily AI briefing generation
│ │ │ ├── canvas/ # Canvas API proxy
│ │ │ ├── events/ # DuckLink RSS parser
│ │ │ ├── jobs/ # Workday jobs (via scraper)
│ │ │ ├── notifications/ # Web Push subscription management
│ │ │ └── onboarding/ # Canvas token onboarding
│ │ ├── dashboard/ # Main dashboard page
│ │ └── onboarding/ # Onboarding UI
│ ├── components/
│ │ ├── AiBriefing.tsx # Daily briefing card
│ │ ├── AiChat.tsx # Duck AI chat sidebar
│ │ ├── CanvasWidget.tsx # Assignments & courses
│ │ ├── EventsWidget.tsx # DuckLink events
│ │ └── JobsWidget.tsx # Student jobs
│ ├── hooks/
│ │ └── useCanvasData.ts # Canvas data fetching hook
│ └── lib/
│ ├── ai-context.ts # LangChain context builder
│ ├── canvas.ts # Canvas API helpers
│ ├── encryption.ts # AES-256-CBC utilities
│ ├── redis.ts # Upstash Redis client + fallback
│ └── vector-store.ts # MemoryVectorStore builder
├── scraper/
│ ├── index.ts # Express server
│ ├── canvas-auth.ts # Puppeteer Canvas/Okta auth
│ └── workday.ts # Puppeteer Workday scraper
├── public/
│ ├── manifest.json # PWA manifest
│ └── sw.js # Service worker
└── next.config.ts
| Method | Endpoint | Description |
|---|---|---|
POST |
/api/ai |
Duck AI chat (RAG, Mistral-7B) |
POST |
/api/briefing |
Generate daily AI briefing |
GET/POST |
/api/canvas |
Canvas LMS API proxy |
GET |
/api/events |
DuckLink RSS events |
GET |
/api/jobs |
Workday student jobs |
POST |
/api/onboarding/canvas |
Store Canvas PAT |
POST |
/api/onboarding/canvas-auto |
Auto-generate token via Puppeteer |
POST |
/api/notifications/subscribe |
Web Push subscription |
POST |
/api/notifications/send |
Trigger push notification |
GET |
/api/health |
Health check |
- Ingestion — Canvas course files fetched via API, content extracted
- Chunking — Documents split into overlapping chunks (LangChain
RecursiveCharacterTextSplitter) - Embedding —
sentence-transformers/all-MiniLM-L6-v2via HuggingFace Inference API - Indexing —
MemoryVectorStorewith cosine similarity - Retrieval — Top-K similar chunks retrieved for each query
- Generation — Mistral-7B-Instruct-v0.3 generates response with retrieved context
mistralai/Mistral-7B-Instruct-v0.3— Chat + instruction following (HuggingFace Inference API)sentence-transformers/all-MiniLM-L6-v2— Semantic text embeddings (384 dimensions)
- Full-stack TypeScript across Next.js App Router, API routes, and the Express scraper microservice
- Microservices architecture — headless browser automation isolated in its own service with encrypted IPC
- RAG from scratch — no OpenAI, no Pinecone; uses open-source models and in-memory vector store
- Security-first design — credentials never touch the client; AES-256 encryption at rest and in transit between services
- Real browser automation — Puppeteer handles multi-step SSO flows (SAML → Okta → Duo MFA detection)
- Progressive Web App — full PWA with service worker, Web Push, and offline support
- React 19 + Next.js 16 — latest App Router patterns, server components, streaming
MIT — see LICENSE
Built for Stevens Institute of Technology students. Not affiliated with Stevens IT.