feat(ui): serve htmx, Chart.js, Gridstack and the house fonts from Steward itself (#5091)
CI / lint (push) Successful in 3s
CI / integration (push) Successful in 48s
CI / unit (push) Successful in 1m6s
CI / publish (push) Successful in 1m11s

#5091 "Local assets". base.html, the dashboard and the share view loaded
htmx and Chart.js from unpkg/jsdelivr, Gridstack from jsdelivr and their
fonts from Google. On an instance with no outbound network (rule 164) every
page lost htmx, and so every button and poll; and each page load told those
hosts about the visitor (rule 155).

- steward/static/vendor: htmx 2.0.4, Chart.js 4.4.4, Gridstack 12.6.0 (the
  versions the pages already used), with their licences (0BSD, MIT, MIT).
- steward/static/fonts: Inter, Fraunces and JetBrains Mono, the design
  system's faces (SIL OFL, licences beside them), every unicode-range
  subset, with fonts.css. The serif face is now Fraunces in place of
  EB Garamond (base) and Libertinus Serif (share view); applying Inter and
  the type scale is the tokens step.
- Templates use url_for('static'); /static already passes every gate.
- Guard (tests/test_no_remote_assets.py): no template or stylesheet loads a
  script, stylesheet, font or image from another origin (comments stripped,
  example URLs in help text allowed), with a self-test that it can fail;
  every url_for('static') file and every font the sheet names exists.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-06 14:12:31 -04:00
co-authored by Claude Opus 5.5
parent dc22a35e9d
commit bd28d3b0e7
31 changed files with 726 additions and 14 deletions
+2 -2
View File
@@ -3,7 +3,7 @@
{% block head %}
{# Gridstack renders the grid for everyone (static for viewers); editors also get
the in-place drag-resize + bottom drawer. #}
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/gridstack@12.6.0/dist/gridstack.min.css">
<link rel="stylesheet" href="{{ url_for('static', filename='vendor/gridstack-12.6.0.min.css') }}">
{% endblock %}
{% block content %}
@@ -55,7 +55,7 @@
{% endblock %}
{% block extra_scripts %}
<script src="https://cdn.jsdelivr.net/npm/gridstack@12.6.0/dist/gridstack-all.min.js"></script>
<script src="{{ url_for('static', filename='vendor/gridstack-12.6.0-all.min.js') }}"></script>
<script>
(function () {
var gridEl = document.querySelector('.grid-stack');
+4 -6
View File
@@ -4,11 +4,9 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ dashboard.name }} — Steward</title>
<script src="https://unpkg.com/htmx.org@2.0.4/dist/htmx.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.4/dist/chart.umd.min.js"></script>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Libertinus+Serif:ital,wght@0,400;0,600;0,700;1,400&display=swap" rel="stylesheet">
<script src="{{ url_for('static', filename='vendor/htmx-2.0.4.min.js') }}"></script>
<script src="{{ url_for('static', filename='vendor/chart-4.4.4.umd.min.js') }}"></script>
<link rel="stylesheet" href="{{ url_for('static', filename='fonts/fonts.css') }}">
<style>
:root {
--bg: #07071a; --bg-card: #0f0f24; --bg-elevated: #17172e;
@@ -18,7 +16,7 @@
--green: #26d96b; --green-dim: #0e3a1e;
--yellow: #e6b818; --red: #e83848; --red-dim: #3a0e14;
--orange: #e07828;
--font-serif: 'Libertinus Serif', Georgia, serif;
--font-serif: 'Fraunces', Georgia, serif;
}
* { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: system-ui, -apple-system, sans-serif; background: var(--bg); color: var(--text); line-height: 1.5; }