This is the hsx Reference Manual, version 1.2.0, generated automatically by Declt version 4.0 beta 2 "William Riker" on Fri May 15 12:26:17 2026 GMT+0.
The main system appears first, followed by any subsystem dependency.
hsxComponent-oriented HTML DSL
Akira Tempaku <paku@skyizwhite.dev>
Akira Tempaku, Bo Yao
MIT
# HSX – HTML S-expression
HSX is a declarative, component-oriented HTML DSL for Common Lisp.
It lets you describe HTML structures and reusable components directly in Lisp, safely render them to HTML strings, and seamlessly integrate with your web applications.
→ [Example Project](https://github.com/skyizwhite/website)
—
## How It Works
HSX translates Lisp S-expressions into HTML by expanding them into calls to ‘create-element‘.
Each tag or component inside an ‘(hsx ...)‘ form becomes:
“‘lisp
(create-element type props children)
“‘
For example:
“‘lisp
(hsx
(article :class "container"
(h1 "Title")
(p "Paragraph")
(~share-button :service :x)))
“‘
Expands into:
“‘lisp
(create-element :article
(list :class "container")
(list (create-element :h1 nil (list "Title"))
(create-element :p nil (list "Paragraph"))
(create-element #’~share-button
(list :service :x)
nil)))
“‘
—
## Quick Example
“‘lisp
(hsx
(div :id "main" :class "container"
(h1 "Hello, HSX!")
(p "This is a simple paragraph.")))
“‘
↓
“‘html
<div id="main" class="container">
<h1>Hello, HSX!</h1>
<p>This is a simple paragraph.</p>
</div>
“‘
—
## Basic Usage
### Step 1: Create a Component
Components are defined using ‘defcomp‘.
They are simple Lisp functions that return HSX elements.
Component names must start with ‘~‘ and props should be declared with ‘&key‘ and/or ‘&rest‘.
The special ‘children‘ key automatically receives any nested elements.
“‘lisp
(defcomp ~button (&key href class children)
(hsx
(a :href href :class (clsx "btn" class)
children)))
“‘
### Step 2: Combine Components
HSX allows composition of components just like JSX.
“‘lisp
(defcomp ~card (&key title children)
(hsx
(div :class "card"
(h2 title)
(div :class "content"
children))))
(defparameter *view*
(hsx
(div :class "container"
(~card :title "Hello"
(~button :href "/start" :class "primary"
"Get Started"))
(~card :title "Docs"
(p "Read the documentation to learn more.")))))
“‘
### Step 3: Render to HTML
Use ‘render-to-string‘ to produce a full HTML string.
Pass ‘:pretty t‘ for indented, human-readable output.
“‘lisp
(render-to-string *view* :pretty t)
“‘
Output:
“‘html
<div class="container">
<div class="card">
<h2>Hello</h2>
<div class="content">
<a href="/start" class="btn primary">Get Started</a>
</div>
</div>
<div class="card">
<h2>Docs</h2>
<div class="content">
<p>Read the documentation to learn more.</p>
</div>
</div>
</div>
“‘
—
## Fragments
### ‘<>‘ — Fragment
Combine multiple elements without creating an extra parent tag.
“‘lisp
(hsx
(<>
(li "One")
(li "Two")))
“‘
↓
“‘html
<li>One</li>
<li>Two</li>
“‘
Fragments are useful when returning multiple sibling elements from a component.
### ‘raw!‘ — Raw Fragment
HSX automatically escapes unsafe characters in text and attribute values to prevent injection attacks.
If you need to insert raw, unescaped HTML, you can do so — but use it only with trusted content, as it disables automatic escaping and may expose security risks.
“‘lisp
(hsx
(script (raw! "alert(’unsafe if user-generated!’)")))
“‘
—
## Expressions and Logic
You can embed any Lisp expression directly inside an HSX form.
Since HSX is just Lisp syntax, you can use if, when, loop, or any other macro to build dynamic content.
### Conditional Rendering
“‘lisp
(hsx
(div
(if (> (random 10) 5)
(hsx (p "High!"))
(hsx (p "Low!")))))
“‘
### Loop Rendering
“‘lisp
(hsx
(ul
(loop :for item :in items :collect
(hsx (li item)))))
“‘
### Dynamic Props
HSX supports both inline plist props and dynamic plist props.
“‘lisp
(let ((props ’(:class "btn" :href "/")))
(hsx (a props "Dynamic Link")))
“‘
—
## Utilities
### ‘register-web-components‘
Makes Web Components usable in HSX.
“‘lisp
(register-web-components
custom1 custom2)
(hsx
(custom1 :prop "val"
(custom2)))
“‘
↓
“‘html
<custom1 prop="val">
<custom2></custom2>
</custom1>
“‘
### ‘clear-web-components‘
Clears all registered Web Components.
### ‘clsx‘
Builds class strings conditionally.
Removes ‘nil‘ and joins the remaining strings with spaces.
“‘lisp
(clsx "btn" nil "primary")
;; => "btn primary"
“‘
—
## License
MIT License
© 2024 Akira Tempaku
© 2018 Bo Yao (original [flute](https://github.com/ailisp/flute) project)
1.2.0
hsx/main (system).
hsx/mainAkira Tempaku <paku@skyizwhite.dev>
Akira Tempaku, Bo Yao
MIT
hsx/element (system).
hsx/dsl (system).
hsx/utils (system).
hsx/builtin (system).
hsx/web-components (system).
hsx/elementAkira Tempaku <paku@skyizwhite.dev>
Akira Tempaku, Bo Yao
MIT
alexandria (system).
str (system).
hsx/utils (system).
hsx/utilsAkira Tempaku <paku@skyizwhite.dev>
Akira Tempaku, Bo Yao
MIT
alexandria (system).
hsx/dslAkira Tempaku <paku@skyizwhite.dev>
Akira Tempaku, Bo Yao
MIT
alexandria (system).
hsx/element (system).
hsx/builtinAkira Tempaku <paku@skyizwhite.dev>
Akira Tempaku, Bo Yao
MIT
hsx/dsl (system).
hsx/web-componentsAkira Tempaku <paku@skyizwhite.dev>
Akira Tempaku, Bo Yao
MIT
Files are sorted by type and then listed depth-first from the systems components trees.
hsx/hsx.asdhsx/main/file-type.lisphsx/element/file-type.lisphsx/utils/file-type.lisphsx/dsl/file-type.lisphsx/builtin/file-type.lisphsx/web-components/file-type.lisphsx/element/file-type.lisphsx/element (system).
component (class).
create-element (function).
element (class).
element-children (reader method).
element-props (reader method).
element-type (reader method).
expand-component (method).
fragment (class).
html-tag (class).
print-object (method).
print-object (method).
print-object (method).
print-object (method).
print-object (method).
raw-fragment (class).
render-to-string (generic function).
self-closing-tag (class).
tag (class).
element-props-with-children (method).
render-children (method).
render-children (method).
render-props (method).
render-type (method).
self-closing-tag-sym (type).
hsx/utils/file-type.lisphsx/utils (system).
clsx (function).
escape-html-attribute (function).
escape-html-text-content (function).
*attribute-escape-map* (special variable).
*text-content-escape-map* (special variable).
escape-char (function).
escape-string (function).
hsx/dsl/file-type.lisphsx/dsl (system).
clear-web-components (function).
defcomp (macro).
deftag (macro).
hsx (macro).
register-web-components (macro).
%create-element (function).
defhsx (macro).
detect-component (function).
detect-elements (function).
external-symbol (function).
parse-body (function).
plist-p (function).
start-with-tilde-p (function).
hsx/builtin/file-type.lisphsx/builtin (system).
<> (macro).
a (macro).
abbr (macro).
address (macro).
area (macro).
article (macro).
aside (macro).
audio (macro).
b (macro).
base (macro).
bdi (macro).
bdo (macro).
blockquote (macro).
body (macro).
br (macro).
button (macro).
canvas (macro).
caption (macro).
cite (macro).
code (macro).
col (macro).
colgroup (macro).
data (macro).
datalist (macro).
dd (macro).
del (macro).
details (macro).
dfn (macro).
dialog (macro).
div (macro).
dl (macro).
dt (macro).
em (macro).
embed (macro).
fieldset (macro).
figcaption (macro).
figure (macro).
footer (macro).
form (macro).
h1 (macro).
h2 (macro).
h3 (macro).
h4 (macro).
h5 (macro).
h6 (macro).
head (macro).
header (macro).
hr (macro).
html (macro).
i (macro).
iframe (macro).
img (macro).
input (macro).
ins (macro).
kbd (macro).
label (macro).
legend (macro).
li (macro).
link (macro).
main (macro).
map (macro).
mark (macro).
meta (macro).
meter (macro).
nav (macro).
noscript (macro).
object (macro).
ol (macro).
optgroup (macro).
option (macro).
output (macro).
p (macro).
param (macro).
picture (macro).
pre (macro).
progress (macro).
q (macro).
raw! (macro).
rp (macro).
rt (macro).
ruby (macro).
s (macro).
samp (macro).
script (macro).
section (macro).
select (macro).
small (macro).
source (macro).
span (macro).
strong (macro).
style (macro).
sub (macro).
summary (macro).
sup (macro).
svg (macro).
table (macro).
tbody (macro).
td (macro).
template (macro).
textarea (macro).
tfoot (macro).
th (macro).
thead (macro).
time (macro).
title (macro).
tr (macro).
track (macro).
u (macro).
ul (macro).
var (macro).
video (macro).
wbr (macro).
register-builtin-tags (macro).
hsx/web-components/file-type.lisphsx/web-components (system).
Packages are listed by definition order.
hsx/utilscommon-lisp.
hsx.
clsx (function).
escape-html-attribute (function).
escape-html-text-content (function).
*attribute-escape-map* (special variable).
*text-content-escape-map* (special variable).
escape-char (function).
escape-string (function).
hsx/builtincommon-lisp.
<> (macro).
a (macro).
abbr (macro).
address (macro).
area (macro).
article (macro).
aside (macro).
audio (macro).
b (macro).
base (macro).
bdi (macro).
bdo (macro).
blockquote (macro).
body (macro).
br (macro).
button (macro).
canvas (macro).
caption (macro).
cite (macro).
code (macro).
col (macro).
colgroup (macro).
data (macro).
datalist (macro).
dd (macro).
del (macro).
details (macro).
dfn (macro).
dialog (macro).
div (macro).
dl (macro).
dt (macro).
em (macro).
embed (macro).
fieldset (macro).
figcaption (macro).
figure (macro).
footer (macro).
form (macro).
h1 (macro).
h2 (macro).
h3 (macro).
h4 (macro).
h5 (macro).
h6 (macro).
head (macro).
header (macro).
hr (macro).
html (macro).
i (macro).
iframe (macro).
img (macro).
input (macro).
ins (macro).
kbd (macro).
label (macro).
legend (macro).
li (macro).
link (macro).
main (macro).
map (macro).
mark (macro).
meta (macro).
meter (macro).
nav (macro).
noscript (macro).
object (macro).
ol (macro).
optgroup (macro).
option (macro).
output (macro).
p (macro).
param (macro).
picture (macro).
pre (macro).
progress (macro).
q (macro).
raw! (macro).
rp (macro).
rt (macro).
ruby (macro).
s (macro).
samp (macro).
script (macro).
section (macro).
select (macro).
small (macro).
source (macro).
span (macro).
strong (macro).
style (macro).
sub (macro).
summary (macro).
sup (macro).
svg (macro).
table (macro).
tbody (macro).
td (macro).
template (macro).
textarea (macro).
tfoot (macro).
th (macro).
thead (macro).
time (macro).
title (macro).
tr (macro).
track (macro).
u (macro).
ul (macro).
var (macro).
video (macro).
wbr (macro).
register-builtin-tags (macro).
hsx/elementcommon-lisp.
hsx.
component (class).
create-element (function).
element (class).
element-children (generic reader).
element-props (generic reader).
element-type (generic reader).
expand-component (generic function).
fragment (class).
html-tag (class).
raw-fragment (class).
render-to-string (generic function).
self-closing-tag (class).
tag (class).
element-props-with-children (generic function).
render-children (generic function).
render-props (generic function).
render-type (generic function).
self-closing-tag-sym (type).
hsx/dslcommon-lisp.
hsx.
clear-web-components (function).
defcomp (macro).
deftag (macro).
hsx (macro).
register-web-components (macro).
%create-element (function).
defhsx (macro).
detect-component (function).
detect-elements (function).
external-symbol (function).
parse-body (function).
plist-p (function).
start-with-tilde-p (function).
Definitions are sorted by export status, category, package, and then by lexicographic order.
Define an HSX component:
- name: must begin with a tilde (~)
- props: must be declared using &key, &rest, or both
the ‘children‘ key receives the component’s child elements
- body: must return a valid HSX element
Automatically detect html tags, registered Web Components, and user-defined HSX components.
All other expressions are evaluated as regular Lisp forms.
To create HSX elements within a Lisp form, use the ‘hsx‘ macro again.
Constructing class strings conditionally.
It removes ‘nil‘ from the string list, then joins the remaining strings with spaces.
Render an HSX element to an HTML string.
self-closing-tag) stream) ¶raw-fragment)) ¶| Jump to: | %
<
A B C D E F G H I K L M N O P Q R S T U V W |
|---|
| Jump to: | %
<
A B C D E F G H I K L M N O P Q R S T U V W |
|---|
| Jump to: | *
C P S T |
|---|
| Jump to: | *
C P S T |
|---|
| Jump to: | C E F H P R S T |
|---|
| Jump to: | C E F H P R S T |
|---|