8874b35998fbb108e298a7c339491cb880a9466f
Findings from a full frontend audit (static read + live instrumentation of
production). This covers the "bleeding" and performance phases.
Bug fixes:
- StatsPanel branch collapse/expand never re-rendered. Two Svelte 5 defects:
$state(new Set()) is not proxied (proxy.js bails on non-object/array
prototypes), so .add()/.delete() were untracked; and the Svelte 4
`x = x` reactivity idiom is a no-op in runes mode, where sources use a
strict `equals` comparator. Switched to SvelteSet and dropped the
self-assignment. Verified: aria-expanded now flips and rows 28<->24.
- The closed stats panel's gold box-shadow (8px offset + 80px blur) bled
~88px past its right edge, painting a permanent olive stripe down the
left of the viewport on every page view. Offset the closed transform
past the shadow.
- data.ts shipped a placeholder repoUrl (github.com/yourusername/...), a
live 404 on the node describing this very site. Also removed the
"Tailwind CSS" techStack claim; it is not a dependency of this project.
Performance:
- nodes.ts awaited Assets.load() inside the node loop, serialising ~56 icon
round-trips before the tree could render or accept input. Now one
parallel batch. Measured: all 78 tree icon requests start at ~28ms and
complete within ~618ms.
- isLoading was cleared right after app.init(), before a single texture
existed, so the spinner resolved onto an empty screen. Moved to after
the scene graph is built.
- Renderer left antialias on (costly, ~no benefit on soft glow circles)
and resolution/autoDensity at defaults (blurry on HiDPI). Now
antialias:false, resolution:min(dpr,2), autoDensity, high-performance.
- cacheAsTexture on the fully-static gradient (16 full-screen fills) and
vignette (13); interactiveChildren:false on background containers.
- Dust ticker allocated a fresh closure per frame via forEach; replaced
with a named function and an indexed loop.
Dead weight:
- static/{headshot,profile}.jpg.original (8.6MB, 83% of the static payload)
were committed and deployed verbatim by adapter-static, publicly
fetchable and referenced by nothing. Moved to a gitignored assets-src/
so the full-res sources stay on disk without shipping.
- precompress:true so nginx gzip_static/brotli_static have siblings to
serve (the origin currently sends everything uncompressed).
build/ 11.13MB -> 3.7MB. JS wire 727.6KB raw -> 232KB gzip / 202.7KB brotli.
svelte-check clean, 14/14 tests pass.
Note: the matching nginx change lives in the gitignored homelab/default.conf
and must be applied to the container separately.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
sv
Everything you need to build a Svelte project, powered by sv.
Creating a project
If you're seeing this, you've probably already done this step. Congrats!
# create a new project in the current directory
npx sv create
# create a new project in my-app
npx sv create my-app
Developing
Once you've created a project and installed dependencies with npm install (or pnpm install or yarn), start a development server:
npm run dev
# or start the server and open the app in a new browser tab
npm run dev -- --open
Building
To create a production version of your app:
npm run build
You can preview the production build with npm run preview.
To deploy your app, you may need to install an adapter for your target environment.
Languages
TypeScript
56.7%
Svelte
36.1%
JavaScript
3.4%
Shell
2.7%
CSS
0.8%
Other
0.3%