Non-Minification Page Asset Performance Inventory
This is the exhaustive source-level inventory for the current application. It excludes minification; validate byte and request impact with browser/network measurements before implementation.
Working This Inventory
Work through remaining items in the order that provides the safest measured
reduction in delivered or parsed assets; commit each verified change and
update this document in the same commit. Preserve readable source,
no-JavaScript behavior, theme behavior, static-artifact correctness, and
unrelated working-tree files. Record any item deliberately retained or
deferred with its reason before moving on.
CSS Ownership Candidates
About — .about-section and its glyph rules now load from fingerprinted about.css only for templates/pages/about.php.
Tools/bookmarklets — .tool-launcher-* now loads from fingerprinted tools.css only on tools.php and bookmarklets.php, including its mobile rules.
Tag directory — .tag-group*, .tag-thread-list, and the tag-directory card now load from fingerprinted tags.css only for templates/pages/tags.php.
Activity manifests — .activity-commit-manifest* now loads from fingerprinted activity.css on classic Activity and Forte Activity, including lazy-loaded manifest details.
Invitations — .invitation-destination-* now loads from fingerprinted invitations.css only for templates/pages/invites.php, alongside its existing invitation scripts.
Account/profile identity — .account-key-* now loads from shared fingerprinted identity.css on account, profile, invitation, thread, and post identity-detail surfaces.
Pending approvals — the responsive approvals table and .pending-approvals-* now load from fingerprinted pending-approvals.css only for users_pending.php, alongside its route-specific script.
Compose controls — inline-reply, standalone compose, normalization, compact board composer, and reply-context rules now share fingerprinted compose.css on Board, Thread, Compose Thread, and Compose Reply routes.
Post/thread interactions — .post-card-actions, .thread-reaction-*, and handoff/analysis styles now load from fingerprinted content-interactions.css on post and thread routes only.
Thread-list/density controls — .thread-density-* and compact-list rules now load from fingerprinted thread-list.css only on Board and Tag views.
SQLite viewer — 3,588 bytes of .sqlite-* and SQLite data-role rules now load from fingerprinted sqlite.css only on the SQLite tool; site.css is 3,588 bytes smaller for every standard route. The SQLite route retains the existing tool-only JS/WASM runtime and its no-JavaScript download links.
Instance/backup, profile/user-directory, feature-flag, and LLM-exchange selector families — audit found no dedicated backup or user-directory CSS, while .agent-label is shared across profile, activity, content, and Forte surfaces and remains global. The codebase-* family (1,281 bytes) now loads as fingerprinted tool-details.css only on System State, Feature Flags, and LLM Exchanges.
Already isolated — Forte is in forte.css; explicit themes are in theme-<name>.css. Do not duplicate them into page stylesheets.
Page and Render-Path Candidates
Critical CSS: account-key reduction — browser-rendered Board HTML measured a 6,337-byte fixed inline prefix. The 593-byte public-key textarea/focus block is account-only, so it now loads from fingerprinted account.css on account_key.php; every standard page’s inline critical CSS is 5,744 bytes.
Critical CSS: shared-header audit — deferred after the account-key reduction: the remaining 5,744-byte prefix is the global shell, navigation, theme menu, and card baseline. It needs a filmstrip/LCP comparison across all themes before further trimming; do not trade a visible first-paint regression for source bytes.
Shared layout markup — the only safely route-irrelevant inline branch was the density resolver, removed from non-Board/Tag pages. Navigation, the theme menu, status-bar accessibility markup, and theme resolver are shared or paint-critical and remain.
Board/thread/tag payloads — the measured Board contains 139 cards and 139 previews (85,479-byte HTML). Classic thread HTML is 24,357 bytes. No truncation was made: changing first-view card/previews requires a pagination or disclosure product decision.
Static pages — LocalAppSmokeTest::testStaticArtifactBuilderWritesApacheFriendlyArtifactLayout verifies fingerprinted referenced assets are copied for generated routes. The builder excludes per-request authentication state by rendering public routes.
Data URI glyphs — About glyphs are already in route-only about.css; remaining data-URI glyphs are explicit theme-word97.css decorations, loaded only when that theme is active. Retained to preserve its visual system without adding requests.
JavaScript and Runtime Candidates
Layout-wide scripts — audit completed for compose_draft_clear.js and invite_navigation.js: retain both globally. The former consumes a post-submit cookie on arbitrary landing routes; the latter preserves the current route when the global Invite nav link is clicked. Keep theme_toggle.js global; thread_density_toggle.js is already conditional.
Route scripts — audited explicit scriptPaths contracts for reactions, inline replies, invitations, approvals, feature flags, bookmarklets, SQLite, and Forte. SQLite/WASM, Forte readers, bookmarklets, feature flags, and pending-directory approval scripts remain route-only. Profiles without a signed approval form no longer explicitly request openpgp_loader.js, browser_signing.js, or pending_approvals.js; approved-members mode may still inject its authentication bundle. compose_draft_clear.js, invite_navigation.js, and theme_toggle.js remain global for their documented cross-route behavior.
OpenPGP/browser signing — reviewed against the route contracts: compose/account and signed interaction flows retain the loader; Board uses the existing intent-lazy loader. Do not move authenticated-session restoration scripts out of their required private-mode render path.
SQLite runtime — remains tool-only and is not preloaded elsewhere. The SQLite page’s 223,393 bytes of directly referenced source assets are supplemented only on that route by the 659,806-byte sql-wasm.wasm (322,177 bytes with gzip).
Heavy reader scripts and payload — Forte reader scripts are route-only (75,152 source bytes), but the all-content pane renders 582 thread articles and 522 reply nodes: 2,421,569-byte HTML (234,492 bytes with gzip). Deferring hidden panes needs a dedicated no-JavaScript/progressive-disclosure design, so it is deliberately deferred rather than silently removing content.
Inline head code: density resolver — the layout’s inline resolver measured 2,836 source bytes. The density branch is now emitted only when the enabled density control is rendered on Board/Tag, preserving its pre-paint compact-mode behavior while removing 592 bytes from other rendered pages. The theme resolver remains inline because it selects the active theme before first paint.
Asset Delivery and Artifact Candidates
Fingerprint caching investigation — FrontController serves validated fingerprints with Cache-Control: public, max-age=31536000, immutable; static HTML revalidates by ETag. Apache may directly serve physical /assets files, so transfer-header and CDN policy remain host configuration rather than duplicated in readable source.
Compression investigation — no repository-owned Apache/CDN compression configuration exists. Brotli or gzip for CSS, JavaScript, HTML, JSON, and SVG remains an operator/vhost task, because enabling a module-specific filter without the target host’s enabled-module and proxy validation would be unsafe. This is transfer compression, not minification.
Source maps — the tracked openpgp.min.js.map is 1,847,778 bytes. It remains available for development/debugging but is not referenced by rendered HTML, so referenced-asset static releases do not copy it.
Static artifact copying — static rendering now copies only fingerprinted assets referenced by each rendered artifact; development-only maps and stale/generated assets are not swept into releases.
Stale fingerprint chains — removed 491 ignored recursive fingerprint artifacts (66,239,690 bytes), reducing public/assets from 69 MB to 4.0 MB. AssetFingerprint now recognizes only a single hash as current and redirects both ordinary and recursive stale URLs to the canonical current fingerprint; static releases continue to copy only referenced current assets.
Preload priority — verified the layout preloads only fingerprinted site.css and loads the active theme at high priority. Route CSS/scripts, alternate themes, and tool runtimes are not preloaded; alternate themes are warmed at low priority after interaction logic permits it.
Connection and cache policy — source has no browser-side third-party asset URLs. Cache-hit rates and HTTP/2/HTTP/3 multiplexing require production/CDN observability and are deferred to the operator rather than guessed from local development.
Measurement and Guardrails
- [x] **Representative route payload baseline** — local Chromium/`curl` capture after these reductions, with direct unique fingerprint references and local gzip estimates (actual transfer, parse/execution time, LCP, and cache-hit behavior remain host/browser measurements):
| Route | HTML bytes | Referenced assets | Asset source bytes | HTML gzip bytes |
| --- | ---: | ---: | ---: | ---: |
| Board | 85,479 | 12 | 154,433 | 16,221 |
| About | 20,724 | 9 | 146,063 | 5,127 |
| Thread | 24,357 | 14 | 188,482 | 5,371 |
| Tools | 21,358 | 9 | 143,958 | 4,833 |
| Account | 29,193 | 10 | 146,102 | 6,490 |
| SQLite | 22,218 | 11 plus WASM | 883,199 | 5,178 |
| Forte | 2,421,569 | 5 | 75,152 | 234,492 |
- Establish per-route budgets before each extraction; reject a split that raises first-load requests or LCP without a compensating measured benefit.
- Test JavaScript-disabled rendering, every explicit theme, Auto/System behavior, authenticated/private routes, responsive widths, and static artifacts.
- Preserve readable source files, fingerprints, source maps in development, accessibility, and existing no-JavaScript fallback behavior.