11# HSX
22
3- SSR-only JSX/TSX renderer for Deno that compiles HTMX-style attributes to ` hx-* `
4- on the server.
3+ First things, first... What the hack does HSX stand for? I'll say it's '** H** TML
4+ for ** S** erver-Side e** X** tensions'. :0
5+
6+ But, silently, I prefer: ** H** TML ** S** laps ** X** tremely :)
7+
8+ SSR-only JSX/TSX renderer for Deno that hides HTMX-style attributes away during the rendering process, and compiles them to ` hx-* ` attributes.
59
610> Disclaimer: this was a quick hack in my free time, held together by vibe
7- > coding and espresso. I like it a lot, but consider it an early release.
11+ > coding and espresso. I like it a lot, but consider it an early release. I feel it is getting better (a lot)
812
913## TL;DR: : Like JSX, but for SSR HTML + HTMX.
1014
@@ -35,30 +39,40 @@ Or import directly:
3539import { id , render , route } from " jsr:@srdjan/hsx" ;
3640```
3741
38- ### Selective Imports (Tree-Shaking)
42+ ### Separate Packages
3943
40- HSX supports modular imports for smaller bundles :
44+ HSX is a monorepo with two packages :
4145
4246``` ts
43- // Core only - rendering + type-safe routes (excludes hsxComponent/ hsxPage)
44- import { render , route , id , Fragment } from " jsr:@srdjan/hsx/core " ;
47+ // Core - JSX rendering, type-safe routes, hsxComponent, hsxPage
48+ import { Fragment , hsxComponent , hsxPage , id , render , route } from " jsr:@srdjan/hsx" ;
4549
46- // Component model only - higher-level abstractions
47- import { hsxComponent , hsxPage } from " jsr:@srdjan/hsx/component-model" ;
50+ // Styles - ready-to-use CSS with theming support
51+ import { HSX_STYLES_PATH , hsxStyles } from " jsr:@srdjan/hsx-styles" ;
52+ ```
4853
49- // Everything (default)
50- import { render , route , hsxComponent , hsxPage } from " jsr:@srdjan/hsx" ;
54+ Install individually:
5155
52- // Optional styles - ready-to-use CSS with theming support
53- import { hsxStyles , HSX_STYLES_PATH } from " jsr:@srdjan/hsx/styles" ;
56+ ``` bash
57+ deno add jsr:@srdjan/hsx
58+ deno add jsr:@srdjan/hsx-styles
59+ ```
60+
61+ ### Legacy Exports (Backward Compatible)
62+
63+ For backward compatibility, subpath exports still work:
64+
65+ ``` ts
66+ import { Fragment , id , render , route } from " jsr:@srdjan/hsx/core" ;
67+ import { HSX_STYLES_PATH , hsxStyles } from " jsr:@srdjan/hsx/styles" ;
5468```
5569
5670### From Source
5771
58- Clone and import:
72+ Clone and import using workspace package names :
5973
6074``` ts
61- import { id , render , route } from " ./src/index.ts " ;
75+ import { hsxComponent , hsxPage , id , render , route } from " @srdjan/hsx " ;
6276```
6377
6478## Quick Start (Low-Level API)
@@ -67,8 +81,7 @@ import { id, render, route } from "./src/index.ts";
6781> the [ hsxComponent pattern] ( #hsx-component-pattern-recommended ) below instead.
6882
6983``` tsx
70- /** @jsxImportSource ./src */
71- import { id , render , route } from " ./src/index.ts" ;
84+ import { id , render , route } from " @srdjan/hsx" ;
7285
7386const routes = {
7487 todos: route (" /todos" , () => " /todos" ),
@@ -346,7 +359,11 @@ if (url.pathname === "/static/htmx.js") {
346359HSX includes an optional CSS module with a default theme and dark variant:
347360
348361``` ts
349- import { hsxStyles , hsxStylesDark , HSX_STYLES_PATH } from " jsr:@srdjan/hsx/styles" ;
362+ import {
363+ HSX_STYLES_PATH ,
364+ hsxStyles ,
365+ hsxStylesDark ,
366+ } from " jsr:@srdjan/hsx-styles" ;
350367
351368// Serve the styles
352369if (url .pathname === HSX_STYLES_PATH ) {
@@ -356,23 +373,24 @@ if (url.pathname === HSX_STYLES_PATH) {
356373}
357374
358375// In your page head
359- < link rel = " stylesheet" href = {HSX_STYLES_PATH } / >
376+ < link rel = " stylesheet" href = {HSX_STYLES_PATH } / > ;
360377```
361378
362379** Exports:**
380+
363381- ` hsxStyles ` - Default light theme (indigo accent)
364382- ` hsxStylesDark ` - Dark theme variant
365383- ` HSX_STYLES_PATH ` - Default path: ` /static/hsx.css `
366384
367385** Customization:** Override CSS variables in your page:
368386
369387``` tsx
370- <style >{ ` :root { --hsx-accent: #10b981; --hsx-bg: #f0fdf4; } ` } </style >
388+ <style >{ ` :root { --hsx-accent: #10b981; --hsx-bg: #f0fdf4; } ` } </style >;
371389```
372390
373- Available variables: ` --hsx-accent ` , ` --hsx-bg ` , ` --hsx-surface ` , ` --hsx-border ` ,
374- ` --hsx-text ` , ` --hsx-muted ` , ` --hsx-error ` , ` --hsx-success ` , spacing ( ` --hsx-space-* ` ) ,
375- and radius (` --hsx-radius-* ` ).
391+ Available variables: ` --hsx-accent ` , ` --hsx-bg ` , ` --hsx-surface ` ,
392+ ` --hsx-border ` , ` --hsx-text ` , ` --hsx-muted ` , ` --hsx-error ` , ` --hsx-success ` ,
393+ spacing ( ` --hsx-space-* ` ), and radius (` --hsx-radius-* ` ).
376394
377395## API Reference
378396
@@ -483,34 +501,34 @@ Run examples with `deno task`:
483501## Project Structure
484502
485503```
486- src /
487- index.ts # Main entry - exports everything
488- core .ts # Core module - render, route, id, Fragment, types
489- component-model .ts # Component module - hsxComponent, hsxPage
490- styles .ts # Optional CSS module with themes
491- jsx-runtime .ts # Minimal JSX runtime (compiler requirement)
492- render .ts # SSR renderer with HTMX injection
493- hsx-normalize. ts # HSX to hx-* attribute mapping
494- hsx-component.ts # hsxComponent factory (route + handler + render)
495- hsx-page.ts # hsxPage guardrail for full-page layouts
496- hsx-types.ts # Route, Id, HsxSwap, HsxTrigger types
497- hsx-jsx.d. ts # JSX type declarations
504+ packages /
505+ hsx/ # Core package (@srdjan/hsx)
506+ mod .ts # Main entry point
507+ jsx-runtime .ts # Minimal JSX runtime (compiler requirement)
508+ render .ts # SSR renderer with HTMX injection
509+ hsx-normalize .ts # HSX to hx-* attribute mapping
510+ hsx-types .ts # Route, Id, HsxSwap, HsxTrigger types
511+ hsx-jsx.d. ts # JSX type declarations
512+ hsx-component.ts # hsxComponent factory (route + handler + render)
513+ hsx-page.ts # hsxPage guardrail for full-page layouts
514+ hsx-styles/ # Styles package (@srdjan/hsx-styles)
515+ mod. ts # Main entry point (CSS themes)
498516examples/
499- todos/ # Full todo app example
500- active-search/ # Search example
501- lazy-loading/ # Lazy load example
502- form-validation/ # Form validation example
503- polling/ # Polling example
504- tabs-modal/ # Tabs and modal example
505- hsx-components/ # HSX Component pattern example
506- hsx-page/ # hsxPage full-page guardrail example
507- low-level-api/ # Manual render/renderHtml without hsxPage/hsxComponent
517+ todos/ # Full todo app example
518+ active-search/ # Search example
519+ lazy-loading/ # Lazy load example
520+ form-validation/ # Form validation example
521+ polling/ # Polling example
522+ tabs-modal/ # Tabs and modal example
523+ hsx-components/ # HSX Component pattern example
524+ hsx-page/ # hsxPage full-page guardrail example
525+ low-level-api/ # Manual render/renderHtml without hsxPage/hsxComponent
508526vendor/htmx/
509- htmx.js # Vendored HTMX v4 (alpha)
527+ htmx.js # Vendored HTMX v4 (alpha)
510528docs/
511- USER_GUIDE.md # Comprehensive user guide
512- HSX_OVERVIEW.md # Architecture overview
513- HTMX_INTEGRATION.md # HTMX integration details
529+ USER_GUIDE.md # Comprehensive user guide
530+ HSX_OVERVIEW.md # Architecture overview
531+ HTMX_INTEGRATION.md # HTMX integration details
514532```
515533
516534## License
0 commit comments