Performance & weight¶
Shrd is designed to stay light. This page documents what it costs on the wire and on your server.
Quick report¶
JSON output for tooling:
Fail CI when bundled assets exceed budgets:
Client weight (default setup)¶
Shrd ships three JavaScript files. Only two are required for most pages:
| Asset | Gzip (approx.) | Required | Purpose |
|---|---|---|---|
htmx.min.js |
~16 KB | Yes | Server-driven updates |
shard.js |
<1 KB | Yes | HTMX request glue |
alpine.min.js |
~16 KB | No | Client-side UI state |
HTMX-only page load: ~17 KB gzip, 2 requests
With Alpine.js: ~33 KB gzip, 3 requests
No npm install, no build step, no CSS framework bundled.
Loading scripts¶
{# Default: HTMX + shard.js only (~17 KB gzip) #}
{% shard_scripts %}
{# Opt in to Alpine when you use get_client_state() or x-data #}
{% shard_scripts alpine=True %}
Or set globally:
Server weight¶
| Area | Cost |
|---|---|
| Python package | ~150 KB of code/templates (see shard_report) |
| Database | None — no migrations, no ORM models |
| Cache | One entry per mounted component instance |
| Per request | Template render + optional cache read/write |
Shrd adds no middleware and no per-request overhead beyond what your components do.
Optimizations built in¶
Scoped CSS omitted from HTMX responses¶
Component styles are injected on first render only. HTMX action responses return HTML fragments without <style> tags, avoiding duplicate CSS on every interaction.
Alpine is optional¶
Alpine.js is only loaded when you request it. Components that use only server state and HTMX do not pay the ~16 KB gzip cost.
Minimal glue script¶
shard.js is under 1 KB. It only tags HTMX requests so the server can identify Shrd actions.
Scoped CSS minification¶
Component styles are minified by default before injection (SHARD_MINIFY_CSS). This reduces transfer size on first mount without a build step.
Script preload hints¶
{% shard_scripts %} emits <link rel="preload" as="script"> for HTMX and shard.js by default so browsers can fetch them earlier during HTML parse (SHARD_PRELOAD_SCRIPTS).
Co-located CSS, not a global bundle¶
Styles are scoped per component and only included when that component mounts. There is no site-wide CSS payload from Shrd.
Tuning tips¶
- Skip Alpine on pages that only use HTMX actions
- Keep component CSS small — scoped styles still transfer on first mount
- Use Django's cache with a production backend (Redis) if you mount many components
- Enable gzip/brotli on your reverse proxy for static files (standard Django deployment)
- Set
SHARD_STATE_TIMEOUTto expire unused component state - Run
shard_report --check-budgetin CI to catch asset regressions
Size budgets¶
Shrd ships conservative gzip budgets for bundled JavaScript. CI runs:
Current limits (see shard/weight.py):
| Check | Budget |
|---|---|
htmx.min.js gzip |
17.5 KB |
shard.js gzip |
500 B |
alpine.min.js gzip |
17.5 KB |
| Required JS total | 18 KB |
| All JS (with Alpine) | 35 KB |
Raise budgets intentionally when upgrading vendored libraries.
Comparison mindset¶
Shrd is not competing with React/Vue bundle sizes — it deliberately avoids a client framework. The tradeoff:
| Shrd | Typical SPA | |
|---|---|---|
| JS transfer | ~17–33 KB gzip | 100–300+ KB gzip |
| Build tooling | None | webpack/Vite required |
| Server round-trips | Per action (HTMX) | API calls + hydration |
| SEO / first paint | Server-rendered HTML | Depends on SSR setup |
For Django teams who want components without a SPA, Shrd keeps the client payload small by keeping logic on the server.