Live demo · Download · Install · Privacy · Docs
Your whole semester on one page, for University of Minnesota students. MyU says where you need to be. Canvas says what you need to do. Gopher Calendar puts both in one calendar, synced from the tabs you're already logged into, and it reads the syllabus for the dates Canvas never got. No account, no server, no password.
| See which weeks will crush you | Every course against every week. Darker purple means more is due, and card-suit marks show what kind: ♣ exam, ♠ quiz, ♦ assignment, ♥ project. |
| Know where to be today | Your MyU classes on a week grid that fits one screen, with university holidays already taken out. |
| Find what Canvas is missing | Many professors put dates only in a syllabus PDF or on the course Home page. Gopher Calendar finds those files and reads them only after you say yes. New dates stay dashed until you confirm them. |
| Understand repeating events | A line like "each lab, except the first week, begins with a short quiz" becomes Quiz 1, 2, 3… on each real lab day. |
| Private by design | Read-only GET requests with the sessions already in your browser. Everything stays in chrome.storage.local. There is no Gopher Calendar server. |
| AI only if you want it | Syllabi are read by rules on your device. Bring your own Anthropic, OpenAI or Azure OpenAI key for unusual wording and scanned PDFs. |
| Take it anywhere | Export one .ics file for Google Calendar, Apple Calendar or Outlook. |
- Download
gopher-calendar-vX.Y.Z.zipfrom the latest release and unzip it. - Open
chrome://extensionsand turn on Developer mode (top right). - Click Load unpacked and pick the unzipped folder.
- Log in to Canvas and MyU in the same Chrome profile.
- Click the Gopher Calendar icon, then Sync and open calendar.
Chrome Web Store: a store listing is on the way. Until then, the release zip is the same package that will be submitted.
git clone https://github.com/kenny2077/Gopher-Calendar.gitThen follow steps 2–5 above and pick the extension/ folder.
Just looking? The live demo runs the same page with a sample semester. Everything can be browsed; buttons that sync, save or download are for show.
| Step | What you do | What happens |
|---|---|---|
| Sync | Click Sync Canvas and MyU | Deadlines from Canvas, classes from MyU, holidays from the UMN calendar. Takes about 30 seconds. |
| Approve sources | Check what's listed in Sources to read, then click Read | The syllabus and schedule files it found are read, and missing dates are filled in. |
| Confirm | Click a dashed item, or Confirm all | The date is marked as checked by you. |
| Explore | Click any week in the grid | That week's items, with the course you clicked listed first. |
| Export | Settings → Download .ics file | One file with every class meeting and deadline. |
A four-step tour opens the first time the calendar has data. Settings → Show the tour replays it.
![]() |
![]() |
| Class schedule: from MyU, holidays removed | Week view: dashed items came from the syllabus |
- Read what the university already publishes. Canvas's API gives due dates, points and whether you submitted. MyU gives your class times and rooms. UMN's public academic calendar gives holidays. This builds the calendar with plain code: no AI and no guessing.
- Find what Canvas is missing. Each course's Syllabus tab, Home page, files, pages and modules are judged by name ("syllabus", "schedule", "calendar") and by how many dates a page mentions. At most three per course are picked, and duplicate copies are dropped. Only names are looked at; nothing is downloaded yet.
- Read only what you approve. After you click Read, rules on your computer find lines like "HW 3 due Monday 9/28 at the beginning of the class", table rows like "Mon Dec 14 | FP4 slides due 11:59am", and weekly rules. Found dates are matched to the Canvas assignments that had none, and anything Canvas already has is skipped.
Approvals are remembered. You're asked again only when a file changes or a new one appears. Something outside Canvas, like a course website, gets a link and three short steps: open it, save it as a PDF, then Add a file.
Every request a sync makes
Every request is a GET, sent one at a time with a pause, from inside a Canvas or MyU tab so it
carries your existing session.
| Source | What | Endpoint |
|---|---|---|
| Canvas | courses, current term, syllabus | GET /api/v1/courses?include[]=term&include[]=syllabus_body |
| Canvas | deadlines with status | GET /api/v1/planner/items |
| Canvas | assignments with no due date | GET /api/v1/courses/:id/assignments |
| Canvas | candidate sources (names only) | …/files, …/pages, …/modules, …/front_page |
| MyU | one week of meetings | IScript_DrawSection?section=UM_SSS_ACAD_SCHEDULE&effdt=… |
| MyU | meeting pattern and dates | IScript_DrawSection?section=UM_SSS_CLASS_DETAIL&… |
| UMN (public) | closures and no-class days | https://academic-calendar.umn.edu/academic_calendar |
Quirks it handles, all covered by tests: Canvas's while(1); JSON prefix and UTC times (an
11:59pm deadline arrives as 04:59 the next day), MyU day numbers that overflow the month
(20260931), classes with several meeting rows, and MyU listing classes on university holidays.
AI is optional and off by default. Gopher Calendar works fully without a key.
| On this device (default) | With an AI model (optional) | |
|---|---|---|
| Who reads approved files | Rules in extension/lib/extract.js |
Anthropic, OpenAI or Azure OpenAI, with your own key |
| What leaves your browser | Nothing | File names while picking sources, then the text of the files you approved, the course code and Canvas item titles. Never your name, grades or submissions. |
| API key | Not needed | Stored only in this browser. Chrome asks before the extension may contact the provider. |
| Good at | Dates written in the text, tables, clear weekly quiz rules | Unusual wording, repeating events described in prose, scanned PDFs |
In AI mode the model only describes repeating events (name, weekday, first and last date). Code turns that into dates, skips holidays, and checks every answer: only real items, only dates inside the term.
| Provider | Default model | Output |
|---|---|---|
| Anthropic | claude-sonnet-5 |
Structured output (JSON schema) |
| OpenAI | gpt-6-luna |
Strict structured output (JSON schema) |
| Azure OpenAI | your deployment | Strict structured output (JSON schema) |
How good are the rules? On the maintainer's six Fall 2026 courses, the on-device rules found all 30 dates the AI found, with no false ones. That's a small sample, and the rules were tuned on it.
| Permission | Why |
|---|---|
canvas.umn.edu, www.myu.umn.edu |
The two sites the calendar is built from. GET only. |
academic-calendar.umn.edu |
Public holiday list, so classes on university holidays are hidden. |
*.instructure.com, *.inscloudgate.net, *.canvas-user-content.com |
Where Canvas serves course files. Used only for syllabus files you approved. |
scripting, tabs |
Run the read-only collectors inside a Canvas or MyU tab, and notice when you need to log in. |
storage, unlimitedStorage |
Keep the calendar and the text of approved syllabi in your browser. |
| AI provider hosts (optional) | Requested only when you save an API key. |
Full details: PRIVACY.md · SECURITY.md
Your university session expired. Sign in, including Duo, in that tab, then click Sync again. Gopher Calendar never sees your password.
Canvas has no term that is running or starts within 45 days. This is normal between semesters.
All your classes are online or have no meeting times yet. Deadlines from Canvas still work.
Only files and pages whose names look like a syllabus or schedule are offered. Download it from Canvas, then use Add a file next to the course.
| Doc | What's covered |
|---|---|
| PRIVACY.md | What is read, where it is stored, and what the optional AI mode sends |
| SECURITY.md | Permissions, keys, and how to report a vulnerability privately |
| CONTRIBUTING.md | Setup, ground rules (read-only, no real student data), commit style |
| CHANGELOG.md | What changed in each release |
| store/LISTING.md | Chrome Web Store copy, permission justifications, data disclosures |
| DESIGN.md | Visual system: colour, type, the workload grid, card-suit marks |
| PRODUCT.md | Who it's for, positioning, constraints |
extension/
manifest.json, background.js sync orchestration (read-only, one request at a time)
lib/canvas-collect.js runs inside canvas.umn.edu
lib/myu-collect.js runs inside www.myu.umn.edu
lib/normalize.js, model.js raw data → deadlines, classes, weeks, workload
lib/sources.js which syllabus/schedule sources to read; approvals; duplicates
lib/extract.js on-device reader, plus weekly-series expansion
lib/polish.js optional AI reader (Anthropic / OpenAI / Azure); PDF text via pdf.js
lib/closures.js, ics.js UMN holidays; calendar export
dashboard/, popup/ the calendar page and toolbar popup
demo/ GitHub Pages demo (same page, sample semester, inert buttons)
store/ Chrome Web Store listing and graphics
test/ node --test suites with synthetic fixtures
dev/ preview server, packaging and tools
npm install # test-only dev dependencies (Node 20+)
npm test # collectors, normalisation, calendar model, rules reader, AI request shapes
npm run preview # http://localhost:5178/dev/preview.html with a sample semester
npm run build:demo # builds the Pages demo into _site/
npm run package # builds dist/gopher-calendar-vX.Y.Z.zip for the Chrome Web StoreReleases are cut by pushing a vX.Y.Z tag; see CONTRIBUTING.md.
- Chrome Web Store listing
- "What changed since last sync"
- Study-time suggestions in the gaps between classes
- Direct Google Calendar sync
Issues and pull requests are welcome. Read CONTRIBUTING.md first. In short: read-only requests, no real student data in the repo, and a test for every new syllabus pattern.
The workload grid comes from Awesome Calendar Skill. Gopher Grades showed that MyU's schedule pages can be read from an extension, and Better Canvas did the same for Canvas's API. No code is copied from either. Gopher Calendar isn't affiliated with or endorsed by the University of Minnesota.
MIT. See LICENSE. pdf.js is Apache-2.0 and Inter is SIL OFL 1.1; their license files ship next to them.
Built by @kenny2077 at the University of Minnesota.


