Skip to content

Boilerplate migration - #1

Merged
pip-install-python merged 22 commits into
mainfrom
boilerplate-migration
Aug 3, 2026
Merged

Boilerplate migration#1
pip-install-python merged 22 commits into
mainfrom
boilerplate-migration

Conversation

@pip-install-python

Copy link
Copy Markdown
Owner

No description provided.

pip-install-python and others added 22 commits August 1, 2026 19:27
lib/analytics.py — append-only per-day hit log; doc rows from a
before_request hook (crawlers), spa rows from the url.pathname callback
(rendered page views). lib/traffic_report.py — hourly signed rollup to
the 2plot.ai hub (HMAC, prod-gated), /healthz liveness probe, hub-rule
sessions/median/pages/countries. verify_traffic.py — headless
verification incl. the hub's own ingest verifier (loads the hub's real
lib.network_directory by path so its app-id folding import resolves).

app.py wires the recorder + reporter + healthz; render.yaml declares
CROSS_APP_WEBHOOK_SECRET / ANALYTICS_DIR and moves healthCheckPath to
/healthz; .gitignore excludes the local analytics/ hit log.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
kebabMenuItems entries may now be a leaf {label, value, icon?}, a
{divider: true} rule, or a submenu {label, icon?, children} (recursive;
a leaf anywhere in the chain closes the menu and fires kebabAction).
kebabMenuItemsById overrides the global menu per node. Rebuilt bundle +
regenerated wrappers; version 1.3.0 -> 1.4.0. Not published to PyPI.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
scripts/route_parity.py — the migration's proof gate: fingerprints all
40 routes (component tree by type, ids, dash_mui_charts mount counts),
the app shell, the callback census and an HTTP status sweep against a
committed baseline (40 routes, 194 mounts, 113 callbacks, all 200).

requirements-deploy.txt deleted: it had drifted (no `requests`), so the
Docker image could not import app.py while Render, installing
requirements.txt, masked it. One requirements file now serves both;
Dockerfile gains PYTHONUNBUFFERED=1 so boot diagnostics reach logs.

dash_mui_charts/dash_mui_charts (a stray full copy of package.json)
removed: build:backends passed the package name to
-p/--package-info-filename; the flag now says package-info.json, which
also restores the standard full package-info copy the generator writes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
lib/constants.py — SITE_BRAND/SITE_DESCRIPTION/BASE_URL(APP_BASE_URL ->
https://muicharts.2plot.dev)/OG card block/INTERNAL_UA, with
require_owned_base_url refusing platform hostnames in production.
lib/network_directory.py — cross-host directory (dash-email's verified
copy + the muicharts entry this pass ships + MUI X in EXTERNAL).

app.py wires dash-improve-my-llms >=2.3.4: robots per-vendor policy,
register_page_metadata("/", SITE_BRAND) for the /llms.txt H1,
add_llms_routes after prose registrations, analytics before_request
kept ahead of the bot middleware. Header badge + JSON-LD + template
origin substituted from package version and constants at boot — the
five-way version drift and "9 components" claims are gone (13 is the
number; README + .claude/CLAUDE.md corrected).

All 40 register_page calls gain title/description/image_url (zero
empty meta tags verified on every route); 14 pages carry LLMS_DOC
prose sourced from SKILLS.md. templates/index.html rebuilt on the
dedup rule: only tags Dash does not emit, SPA canonical sync, bounded
favicon-avatar retry, GA4 kept.

Gates: route parity GREEN (40 routes identical), verify_traffic all
green, /llms.txt + /robots.txt + /sitemap.xml serving.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
scripts/make_social_card.py (boilerplate template; this site's MUI-blue
palette + area-chart mark, upscale-to-fit for the 180px icon) renders
the 1200x630 card. HARD GATE outstanding: hand-upload to
cdn.2plot.ai/github_assets/muicharts.2plot.dev.png + verify 200/IHDR
before the og:image deploy.

Internal-traffic contract: lib/analytics.record drops 2plot-internal
UAs at write time (before bot classification); the rollup POST and the
ad-client session send internal_ua(...) outbound.

App id converges on the directory key "muicharts": traffic_report
APP_KEY, ad_client AD_APP_ID default, bulletin app_id, /healthz.
verify_traffic assertions updated + a write-time drop check added.
NOTE: 2plotai's traffic sink still keys this app "charts" — it needs a
muicharts fold before deploy or the /traffic series forks.

lib/bulletin.py (boilerplate pattern, app_id from traffic_report):
opt-in via NETWORK_BULLETIN_URL on the SERVICE; boot line prints
wired/off.

Gates: verify_traffic all green (incl. hub-verifier round-trip with the
new id), route parity GREEN.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
tests/ (80 tests, zero secrets by design — the 17 Pro pages degrading to
their license banners IS the test): site identity, social card + template
division rules, version parity (the five-way drift fix), route smoke +
preservation invariants (url Location contract, SimpleTreeView nav,
ad-slot fork, asset contracts), internal-traffic contract both halves,
and the SPA/doc counting rule as executable arithmetic.

.github/workflows mirroring dash-email, adapted: ci.yml (flake8 with a
budgeted pages/ debt ledger + actionlint, secretless pytest + gunicorn
boot + battery, docker build/boot/battery with in-image version
fingerprints, Dash 4.1.0-4.4.1 x py3.10/3.12/3.13 matrix with Node 20
npm ci + build + validate-init, wheel build + clean-venv verify + a
measured dash==3.3.0 floor install, package x py3.9-3.13, JS parse,
advisory pip-audit); cd.yml (main -> CI -> Render hook -> 120s settle +
5 sustained healthz 200s -> network_smoke + smoke_live against the live
domain); release.yml (v* tag -> check_release gate -> OIDC trusted
publishing, no stored token).

scripts/: network_smoke.py (per-site block: this brand's H1,
/sparkline/llms.txt, hidden canaries — battery verified 9/9 in-process),
smoke_live.py (canonical copy, LESSONS §21 wake loop), check_release.py,
smoke_test.py (the matrix gate: 40 routes, 200s, >=150 chart mounts,
node parse of every JS artifact).

Two Dash floors made explicit and measured: the site needs >=4.1 (dimll
pins dash<5,>=4.1; production already resolves 4.4.x — route parity
verified byte-identical under 4.4.1), the package needs >=3.3 (setup.py
raised from the unmeasured >=3.0.0; python_requires >=3.9, 3.13 added).
gunicorn floor >=23 closes CVE-2024-6827/CVE-2024-1135, asserted inside
the Docker image.

Route parity GREEN after this phase: 40 routes, 194 mounts, 113
callbacks, identical to baseline.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
domains: [muicharts.2plot.dev] and every env var the app reads —
APP_BASE_URL / AD_APP_ID with canonical values, NETWORK_BULLETIN_URL at
the hub feed, WIDGETBOT_* optional — with the LESSONS §10 caveat inline:
blueprint envVars apply on Blueprint sync, so every value must also be
set on the SERVICE. Clerk satellite env is N/A (no auth surface in this
app). Remaining go-live steps are owner actions: card upload (HARD
GATE), service env, subdomain + DNS, merge to main, hub-side §9.

Route parity GREEN, 80 tests green, check_release clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Rebuild the docs app on the dash-documentation-boilerplate structure
(model: dash_pannellum) while preserving all 40 endpoints and every live
example, gated by chart parity instead of exact-tree parity.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
route_parity.py gains --charts-only: the migration-proof projection
(route set, per-route dash_mui_charts census, chart component ids, and
the 78 callbacks that read or write a chart id). Exact-tree mode stays
for reference; both baselines recorded from the unmodified app — 40
routes, 194 chart mounts. Entry-point import is transition-proof
(run.py if present, else app.py).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The docs app now runs on the dash-documentation-boilerplate structure
(model: dash_pannellum): run.py entry (gunicorn run:server), components/
appshell+header+navbar (family-grouped nav, header keeps the
header-avatar favicon contract and the package-version badge), lib
additions (backend/auth/proxy/access/page_tiers/hub_client/directives),
canonical ad_client (per-page aside slots, AD_APP_ID=muicharts),
pages/markdown.py serving docs/**/*.md with exec live examples and
markdown-body llms docs. THIS repo's SPA-aware analytics chain carries
over unchanged (doc/spa counting rule, same url Location id); Flask is
enforced until the hooks grow async twins.

SparklineChart family ported: 3 md pages + 11 exec modules, callbacks
verbatim, same endpoints; old pages deleted. Old-shell assets retired
(00-loading-theme.js fought the new color-scheme system,
01-nav-restore.js targeted the removed nav-tree).

Docs stack: dash>=4.4, dmc>=2.7, markdown2dash --no-deps + mistune
(LESSONS §8; Dockerfile/render/ci all use the pair), vendored
dash-clerk-auth 0.9.1 dormant. Package floor unchanged (dash>=3.3).

Gates: chart parity GREEN against the pre-migration baseline (40 routes,
194 chart mounts, 78 chart-touching callbacks identical); exact baseline
re-recorded at the M0 state to catch accidental drift in unported pages
during M1-M5. 80 tests passing zero-secrets (5 shell-invariant tests
rewritten for the new architecture), flake8 clean, in-process network
battery 9/9, smoke_test PASS under dash 4.4.1.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ude ignored

The navbar map becomes (path, label, icon) — the old sidebar's short
labels ("BARCHART / Basic") instead of redundant registry names; search
keeps the long names. The boilerplate's main.css/m2d.css/llms_copy.js
were never copied in M0 — without them the color-scheme toggle rendered
both sun and moon and nav links fell back to bare anchors. Scatter page
display name drops its stale "(0.0.8)". WidgetBot crate removed from
run.py/requirements/render.yaml/conftest. .claude/ untracked + gitignored
(files remain on disk).

80 tests green, chart parity GREEN, exact parity green, flake8 clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…>116)

Correction to the previous commit's message: exact parity was NOT green
there — removing the Discord crate dropped its two clientside callbacks,
so callback_count moved 118->116 (every route fingerprint was identical;
chart parity, the actual migration gate, was and is green). The exact
baseline now reflects the deliberate WidgetBot removal.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
test_version_parity read .claude/CLAUDE.md, which a CI checkout no
longer has; check_release and release.yml pointed prose at the local
publish plan. 80 tests green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
/pie (6 exec examples), /pie-props (nested-pie playground transformed
whole), /scatter (7 examples over a shared seeded _data.py so the point
clouds render exactly as before), /heatmap (7 Pro examples, color-scale
reference as a markdown table, keyless banner in the first example),
/heatmap-props (Pro playground). Endpoints, chart ids and callbacks
verbatim; old pages deleted.

Pro degradation tests re-pinned by ROUTE (17 pro routes, 6 banner
routes, set equality) — the file-scan census broke by design when pro
code moved from pages/ into docs/ exec modules. Transform bug caught by
lint: heatmap-props lost its json import (click display would crash);
restored.

Gates: chart parity GREEN (40 routes, 194 mounts, 78 chart callbacks),
exact baseline re-recorded at M1 state, 80 tests zero-secrets, flake8
clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…parity GREEN

26 of 40 routes now docs/-driven. BarChart family split per card (28 exec
modules across basic/dataset/stacking/interaction/reference/pro, seeded
_data.py modules preserving draw order), /candlestick 7 examples over a
shared OHLC generator, /live-trading transformed whole (11 callbacks).
Learned: shared-data families need underscore directories — hyphenated
packages exec fine but cannot be sibling-imported. /live-trading joined
BANNER_ROUTES (md now documents the key requirement permanently).

Gates: chart parity GREEN (40 routes, 194 mounts, 78 chart callbacks),
exact baseline re-recorded, 80 tests zero-secrets, flake8 clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Seven LineChart pages + highlighting-sync + crosshair + three
CompositeChart pages ported as whole-page transforms: one demo.py exec
module per page (ids and callbacks verbatim — sync overlays, crosshair
alerts, render-BP dashboard), md wrappers with frontmatter, overview
prose and the two LLMS_DOC bodies folded in. Per-section md split for
this family deferred to a content pass by design.

BANNER_ROUTES == PRO_ROUTES now: every Pro route names MUI_PRO_API_KEY
in-page via the Pro admonition; the test pins the posture.

Transform bugs caught by the gates: LLMS_DOC code fences matching the
module cut point, prose harvested as imports, banner strip off-by-two,
dropped `import dash` on two callback-bearing pages (F821).

Gates: chart parity GREEN (40 routes, 194 mounts, 78 chart callbacks),
exact baseline re-recorded, 80 tests zero-secrets, flake8 clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Whole-page transforms for tree_{basic,simple,selection,expansion,
editing,icons,disabled,pro} and time_clock{,_lab}: ids and callbacks
verbatim, four LLMS_DOC bodies folded into md, tree-pro keeps its live
license-posture badge, time-clock-lab keeps its liquid-glass styling.
Proven 1:1 first (chart parity GREEN at 194/78), THEN /tree-simple
gained the dogfooding sidebar: a SimpleTreeView generated from
components/navbar.py's real family map that genuinely navigates the
docs, as the pre-migration shell's sidebar did. Chart baseline
re-recorded deliberately for the addition (195 mounts, 79 chart
callbacks); exact baseline re-recorded.

Only home + changelog remain in pages/. 80 tests zero-secrets, flake8
clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
TreeView and SimpleTreeView gain the data-mantine-color-scheme watcher +
MUI ThemeProvider (the pattern TreeViewPro/TimeClock already had):
checkboxes, icons and edit fields now switch with the theme toggle.
Bundle + wrappers rebuilt (wrappers pick up the current generator's
dash<=4.1 compat shim; validate-init 13/13 on dash 3.3).

The boilerplate's global ul/ol/li margins (assets/main.css markdown
styling) leaked into MUI's nested tree DOM and inflated tree heights —
a height=200 tree overflowed into the next section on /tree-icons.
Neutralized inside .MuiRichTreeView-root/.MuiSimpleTreeView-root via
dark-mode.css (upstream: the boilerplate rule wants prose-scoping).
The /tree-icons SX demo drops its hardcoded light background for
var(--mantine-color-default).

Gates: chart parity GREEN, exact parity GREEN, 80 tests, flake8 clean,
bundle parses, validate-init 13 components.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
height=200 sized the wrapper div but nothing clipped: the tree ul grows
past a fixed-height parent and divs don't clip by default, so the tree
rendered full-length over the following section (/tree-icons demo 6 over
demo 7) — the sx overflow on the tree itself could never scroll because
the tree is as tall as its content. A fixed height now implies
overflow:auto on the wrapper. Bundle + wrappers rebuilt; chart parity
GREEN, 80 tests, validate-init 13/13.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
New /api page renders every component's props via `.. kwargs::`,
generated from the dash-generate-components docstrings so the tables
match the installed version by construction. The enabling fix:
lib/directives/kwargs.py's numpy-style override (for dmc docstrings)
shadowed markdown2dash's own dash-docstring parser, rendering empty
tables for dash-built components — the hook now falls back to the base
parser on "Keyword arguments:". Navbar gains a Reference section;
EXPECTED_ROUTES 41 in tests + smoke_test; both parity baselines
re-recorded for the deliberate route addition.

Home and changelog stay bespoke Python pages by design (home mounts no
charts; both are suite-exercised).

80 tests, flake8 clean, /api boots with 13 rendered tables.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
smoke_test docstring counts 41 routes; check_release's gunicorn-floor
regex anchors to line start (the requirements comment quoting
markdown2dash's spurious >=21.2 pin matched first and failed a healthy
floor). Full battery: chart parity GREEN, exact parity GREEN, 80 tests
zero-secrets, flake8 clean, validate-init 13/13, in-process network
battery 9/9, smoke_test PASS, check_release clean (CHANGELOG cut note
pending the ship decision).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@pip-install-python
pip-install-python merged commit ce28897 into main Aug 3, 2026
16 of 17 checks passed
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