Skip to content

Self-host Material Design Lite and list.js instead of loading them from cdnjs - #133

Merged
pancakereport merged 2 commits into
mainfrom
self-host-mdl
Oct 16, 2026
Merged

pancakereport merged 2 commits into
mainfrom
self-host-mdl

Conversation

@pancakereport

@pancakereport pancakereport commented Oct 16, 2026 •

Copy link
Copy Markdown

Part of #84: Material Design Lite is no longer maintained, and Google's own CDN for it now returns 403. The pages load it from cdnjs instead, which works but leaves them depending on a third-party copy of an unmaintained library. This hosts it in the repo, along with list.js, the other library the pages loaded from cdnjs. It doesn't replace MDL, which #84 still tracks (Bootstrap 5 is the likely long-term option).

Changes

  • server/static/vendor/material-design-lite/: MDL 1.3.0's material.indigo-blue.min.css and material.min.js, plus the script's source map and MDL's Apache 2.0 LICENSE.
    • Source: the dist/ files of the official npm package material-design-lite@1.3.0. They're byte-for-byte identical to the cdnjs files the pages loaded before (SHA-256 38a6c7d1… for the CSS, 3c27eee3… for the JS), so nothing changes visually.
    • No other files needed: the stylesheet's only images are inline data: URLs.
    • Source map: material.min.js ends with a sourceMappingURL comment, so it's included to keep browser dev tools from requesting a file that 404s.
  • server/static/vendor/list.js/: List.js 1.5.0's list.min.js and its MIT LICENSE. It runs the students page's search box and column sorting.
    • Source: dist/list.min.js of the npm package list.js@1.5.0, identical to the cdnjs copy (SHA-256 62a388a7…). The version is unchanged; the latest is 2.3.1.
  • Templates: load the files with url_for('static', …) instead of from cdnjs.
    • base.html.j2 and seat.html.j2: MDL. These are the only two templates that load it.
    • students.html.j2: list.js.

No template loads anything from cdnjs anymore.

Not in this PR

Google Fonts (Roboto and Material Icons) are still loaded from Google, in base.html.j2 and seat.html.j2.

Testing

  • Test suites: unit, e2e and a11y all pass locally (312).
  • In headless Chrome against a local server:
    • MDL, on the students page and the public seat page: both files load from /static/vendor/material-design-lite/ with HTTP 200, MDL's JavaScript initializes (componentHandler is defined and the page's MDL components are set up), and the MDL layout styles apply.
    • list.js, on the students page: it loads from /static/vendor/list.js/ with HTTP 200, searching "Jimmy" narrows the three seeded students to one, and clicking the Name header twice sorts the table ascending and then descending.
    • External requests: the students page's only requests to other sites are Google Fonts.

🤖 Generated with Claude Code

Serve MDL 1.3.0's material.indigo-blue.min.css and material.min.js
(with its source map and Apache 2.0 license) from server/static/vendor,
so the pages no longer depend on a CDN for a library that's no longer
maintained. The files are the npm release's dist files, identical to
the cdnjs copies the pages loaded before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Coverage

Coverage for unit tests for Python 3.14
FileStmtsMissCoverMissing
server
   __init__.py52492%55, 65–67, 87
   cache.py6183%12
   forms.py1381490%23–25, 41–43, 70, 93, 168–171, 178, 186
   models.py2112688%60, 64, 67, 70, 73, 76–81, 143–152, 182, 200, 257, 260, 283, 327, 341
   views.py76751333%39, 49–85, 95–129, 140–144, 161–170, 186–203, 214–221, 230–252, 263–276, 285, 296–299, 317–318, 320–325, 327–328, 342–366, 375–397, 406–433, 450–452, 462–504, 544–574, 583–613, 633, 647–650, 652–655, 664–694, 703–720, 751–755, 764–810, 816–868, 880–882, 889–910, 918–939, 971, 995, 1040–1049, 1051, 1066–1067, 1072–1085, 1099, 1104, 1131–1132
server/controllers
   __init__.py821779%27–28, 36–39, 43, 72, 76, 85, 101–110
   auth_controllers.py402342%22–51, 57–59
   health_controllers.py21767%18–19, 24–28
server/services/auth
   __init__.py28389%25–26, 30
server/services/canvas
   __init__.py806124%18–25, 29, 33, 37, 43, 55–64, 69–105, 109–124, 128
   fake_canvas.py392633%9, 12, 15, 20–25, 28–29, 37–46, 49–56
server/services/core
   assign.py76396%25, 28, 113
   data.py613444%13–18, 22–26, 30–34, 38–40, 44–55, 90–92, 101–102, 106–107
   export.py27678%36–38, 40–42
   room.py611870%11–33, 57, 70–71, 74
   student.py192597%33, 37–38, 47, 284
server/services/email
   __init__.py50394%47, 74, 92
   smtp.py922573%18, 49–51, 68–76, 88–89, 101–108, 112–114, 125–126
server/services/email/templates
   __init__.py33197%20
server/typings
   exception.py34488%42, 53, 59–60
server/utils
   date.py7186%30
   misc.py16756%13–19
TOTAL238380266% 

Tests Skipped Failures Errors Time
294 0 💤 0 ❌ 0 🔥 14.753s ⏱️

@github-actions

github-actions Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Coverage

Coverage for e2e tests for Python 3.14
FileStmtsMissCoverMissing
server
   __init__.py521277%13, 16–22, 27, 55, 65–67, 87
   cache.py6183%12
   forms.py1382185%23–25, 41–43, 68–70, 92–98, 168–171, 178, 186
   models.py2117067%27, 60, 64, 67, 70, 73, 76–81, 111, 126–132, 136, 140, 143–152, 161–162, 169–170, 177–182, 189–197, 200, 214, 217–219, 222, 226, 238, 242, 246, 250–251, 257, 260, 280, 283, 304, 309, 314, 319, 324, 327, 341
   views.py76765614%38–40, 49–85, 95–129, 140–144, 161–170, 186–203, 214–221, 230–252, 263–276, 285, 296–299, 310–329, 342–366, 375–397, 406–433, 442–453, 462–504, 515–523, 531–535, 544–574, 583–613, 622–655, 664–694, 703–720, 726–729, 739–746, 751–755, 764–810, 816–868, 874–884, 889–910, 915–945, 950–954, 962–972, 976–978, 983–1016, 1026–1030, 1037–1061, 1066–1067, 1072–1085, 1094, 1099, 1104, 1120–1136, 1146–1147
server/controllers
   __init__.py824644%26–44, 47–49, 60–87, 90, 101–110, 113
   auth_controllers.py402635%14–16, 22–51, 57–59
   dev_login_controllers.py584424%17–30, 35–52, 60–61, 68–79, 84–101
   health_controllers.py211243%9, 14–19, 24–28
server/services/auth
   __init__.py28775%25–26, 30, 62–63, 68–69
server/services/canvas
   __init__.py806124%18–25, 29, 33, 37, 43, 55–64, 69–105, 109–124, 128
   fake_canvas.py392633%9, 12, 15, 20–25, 28–29, 37–46, 49–56
server/services/core
   assign.py765824%10–13, 16, 19, 22, 25, 28, 36, 40–46, 54–55, 63, 67, 83–148, 162–178
   data.py614133%13–18, 22–26, 30–34, 38–40, 44–55, 62, 72–74, 79, 90–92, 96–97, 101–102, 106–107
   export.py272219%11–45
   layout_preview.py925738%81, 85, 90, 94, 105–110, 116–119, 128–130, 140, 147, 159–162, 167–171, 175–177, 199–200, 206–209, 218–222, 227, 239–259
   room.py61568%11–33, 41–89
   student.py19215917%33, 37–38, 42, 46–48, 57–60, 70–72, 79, 88–93, 104–107, 110–114, 122–136, 140–143, 152–157, 161, 165, 172–307
server/services/csv
   __init__.py261735%11–12, 20, 27–30, 40, 54–56, 63–68
server/services/email
   __init__.py503824%23–40, 44–81, 90–101
   smtp.py927321%18, 26–39, 43–52, 57–77, 83–115, 120–126
server/services/email/templates
   __init__.py332330%9–11, 14–17, 20, 30–41, 45–47
server/services/google
   __init__.py553929%21–36, 40–43, 47–53, 57–76
server/typings
   exception.py341362%20–36, 42, 47, 53, 59–60, 69, 72
server/utils
   date.py7443%17–19, 30
   misc.py161319%5–9, 13–19, 23
TOTAL2383159533% 

Tests Skipped Failures Errors Time
14 0 💤 0 ❌ 0 🔥 26.226s ⏱️

@codecov

codecov Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 66.34%. Comparing base (4a78e5d) to head (2999ded).

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #133   +/-   ##
=======================================
  Coverage   66.34%   66.34%           
=======================================
  Files          29       29           
  Lines        2383     2383           
=======================================
  Hits         1581     1581           
  Misses        802      802           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions

Copy link
Copy Markdown

🚀 Staging Preview Deployed!

URL: https://preview-seating-pr-133-137456085712.us-west1.run.app

The students page's search and column sorting use List.js 1.5.0, loaded
from cdnjs. Serve it from server/static/vendor with its MIT license; the
file is the npm release's dist file, identical to the cdnjs copy.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@pancakereport pancakereport changed the title Self-host Material Design Lite instead of loading it from cdnjs Self-host Material Design Lite and list.js instead of loading them from cdnjs Oct 16, 2026
@pancakereport

Copy link
Copy Markdown
Author

PR preview looks good and search works still.

@pancakereport
pancakereport merged commit afdcf44 into main Oct 16, 2026
13 checks passed
@pancakereport
pancakereport deleted the self-host-mdl branch October 16, 2026 20:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant