Skip to content

API Reference ​

The full set of HTMXObjects exports, organised by use case. For walkthroughs see the Home page, Components catalog, Testing and Examples.

App scaffolding ​

HTMXObjects.@htmx Macro
julia
@htmx struct MyApp ... end

Wraps @dynamicstruct and appends a _reroute! call so that Revise-triggered re-evaluation automatically re-registers routes without a server restart. @ws property bodies are automatically wrapped in (__ws__) -> body. Inline prop = struct ... end definitions are processed as nested route structs.

source
HTMXObjects.create_app Function
julia
create_app(path; port=8000, module_name=nothing, setup=true)

Generate a new HTMXObjects app at path with the standard package + app structure:

julia
path/
├── Project.toml
├── src/<ModuleName>.jl
└── app/
    ├── Project.toml
    └── main.jl

module_name defaults to the directory basename (with .jl stripped). If setup=true (default), runs Pkg.develop and Pkg.instantiate to make the app immediately runnable. Then start with:

julia
cd path && julia -i --project=app app/main.jl
source
HTMXObjects.route! Function
julia
route!(app; prefix="", record_dir=nothing, record_base="")

Register every @get/@post/@put/@patch/@delete/@ws route declared on app's @htmx struct (and all transitively-@included sub-structs) with the Oxygen router. Returns app.

  • prefix — mount the entire app under a URL prefix (e.g. prefix="api" puts the root route at /api/). Default: root ("").

  • record_dir — if set, every served response is also persisted to disk via save_response under that directory; intended for static export.

  • record_base — URL prefix to strip from saved file paths when record_dir is set (for deploying to a non-root subpath).

route! stores (prefix, record_dir) per type in an internal registry so the _reroute! hook emitted by @htmx can re-register routes on Revise reloads — you do not need to call route! again after editing a route body.

source
HTMXObjects.Verb Type
julia
Verb{V}

Singleton type used as the first positional argument of every route IP emitted by @get/@post/@put/@patch/@delete/@ws. Routes are pure sugar over DynamicObjects' indexable properties:

julia
@get foo(x::Int) = body            # source

compute_property(::T, ::Val{:foo}, ::Verb{:GET}, x::Int) = body   # emitted

The verb being part of the dispatch signature lets a single property name host an arbitrary number of HTTP-method handlers (@get foo() = … and @post foo() = … coexist), and lets verb-keyed route IPs share a name with non-verb-keyed (data) IPs without collision. The route registrar threads Verb{V}() into the IP call at request-handling time.

Bare-form route LHS (@get foo = body) is rejected at macro-expansion time — every route must be a call form (@get foo() = body) so DO can register it as an indexable property.

source
HelperUse
@htmx struct App … endThe whole package surface — declares an app, its data, and its routes
create_app(name)Scaffold a new HTMXObjects app (web/, app/, Project.toml) on disk
route!(app)Register all @get/@post/@put/@delete/@ws markers found in the struct on the Oxygen router
Verb{V}Singleton type threaded into route IPs as the first arg, lets one property host @get/@post/… simultaneously
terminate(), serve(), staticfiles(...), dynamicfiles(...)Re-exports from Oxygen for serving

DynamicObjects re-exports ​

HTMXObjects builds on DynamicObjects.jl and re-exports the names you'll need most often:

DynamicObjects, @persist, @dynamicstruct, @memo, @cache_status, @is_cached, @cache_path, @clear_cache!, fetchindex, getstatus, cancel!, cancel_all!, PropertyComputationError, unwrap_error.

HTMX.jl re-exports ​

auto, htmx, h, Node, @__str, HyperscriptString. See the HTMX.jl docs for full details.

HTTP / request helpers ​

ExportPurpose
HTTPRe-exported HTTP module
queryparams(req)Decode ?a=1&b=2 query string into a dict
formdata(req)Decode application/x-www-form-urlencoded body into a dict
is_htmx(req)true iff the request has HX-Request header set
hx_target(req)Value of HX-Target header (or nothing)
hx_trigger(req)Value of HX-Trigger header
hx_current_url(req)Value of HX-Current-URL header
hx_boosted(req)true iff request was triggered by hx-boost
hx_prompt(req)Value of HX-Prompt header (when hx-prompt is on the trigger)

Response helpers ​

ExportPurpose
to_response(x)Coerce arbitrary content to an HTTP.Response
save_response(...)Persist a response (used by static recording)
static_transform(...)Convert dynamic responses to static-friendly form
hx_response(...)Build a response with HTMX-specific response headers (HX-Trigger, HX-Redirect, HX-Push-Url, HX-Refresh, HX-Reswap, HX-Retarget, HX-Reselect, HX-Location)
hx_link(href, label; ...)Render a link that uses hx-get + hx-push-url (HTMX boost-style)
htmx_or(htmx_value, full_value)Pick which to return based on is_htmx(req)
safely(f; obj, req)Run f() and return an inline error widget if it throws — keeps a panel from crashing the whole page

Markdown / agent-readable responses ​

For routes that should serve an agent-readable Markdown view and an HTML view from the same handler:

ExportPurpose
wants_markdown(req)true iff ?plain / ?markdown query param OR Accept: text/markdown / text/plain header is set
wants_errors(req)true iff ?error query param is set
markdown_response(...)Build a text/markdown response
html_only(...) / markdown_only(...) / HtmlOnly / MarkdownOnlyTag content for one rendering only

Error handling and tagging ​

ExportPurpose
eError-tagged HTML builder — mirrors h (e.div(...), e.p(...), …) but injects data-error="true". Pair with filter_errors and ?error to expose machine-readable error summaries from a composite page
filter_errors(html)Walk a Node tree and keep only nodes with data-error="true" (and their ancestors); used by the response pipeline when ?error is on the query
ERROR_DIRRef{String} — directory where caught route exceptions are logged (default joinpath(tempdir(), "htmxo_errors"), override via HTMXO_ERROR_DIR env var)

Forms and inputs ​

See the Components catalog for the full list with examples.

ExportReturns
post_form(url, children...; …) / get_form(url, …)Complete inline form with hidden inputs + submit button
hidden_inputs(; key=val, …)A Vector{Node} of <input type="hidden"> elements
query_url(path; …) / @query_urlURL with encoded query string, type-safe
linput, sinput, sinput_custom, soption, rinput, ninput, cinput, tinput, ainput, radio_groupForm input widgets (label, select, radio, number, checkbox, textarea, autocomplete, …)
LongMarker type for long-text fields
tabset, tabset_styles, htmx_tabsetTab navigation widgets
nav_sidebar, status_badge, lazyLayout/state widgets
loading_indicator_script, request_feedback_*, show_when_scriptUX scripts injected into the page

Tables and captions ​

ExportReturns
render_table(rows; …)Sortable HTML table with optional CSV download
sortable_table_js, download_table_jsCompanion scripts for render_table
CaptionSpec, render_caption, with_caption, caption_stylePlot/table captions

Formatting ​

fmt_time, fmt_bytes, fmt_number — concise human-readable formatters.

Theming & styles ​

HTMXObjects ships its own CSS variables and matches the host environment (raw Pico, VitePress) via a small set of bridges:

ExportPurpose
htmxo_theme()The package's CSS-variable defaults — included automatically by htmx()
pico_bridge()Map --htmxo-* onto Pico's CSS tokens — also injected by htmx() when pico_version is set
vitepress_bridge()Map --htmxo-* onto VitePress's --vp-* tokens — for docs pages embedding HTMXO components
htmxo_utility_styles()Small set of u-* utility classes (u-inline, u-w-full, u-text-success, spacing scale 0..6, …) used by built-in widgets
escape_html(s)HTML-escape via Cobweb's escaper (handles entities)
html_escape(s)Minimal & / < / > escape — used inside generated JS strings

See htmxo-semantic-styling for the project's CSS philosophy.

Editor / Git integration ​

ExportPurpose
GitRepo(path)Wrap a Git working tree as a @dynamicstruct-style object
EditorRoutesAn @htmx struct of CRUD routes for editing files in a GitRepo
editor_form, editor_stylesFront-end widgets used by EditorRoutes

Testing ​

See the dedicated Testing page.

ExportPurpose
TestRoutesAn @htmx struct you @include to mount a test runner UI under /tests/
test_list, test_run!, test_run_all!, test_run_failed!, test_run_missing!, test_run_batch!, test_clear_cache!Underlying test runner functions (call directly or via the UI)

For docs sites that want to embed a live or recorded HTMXObjects app:

ExportPurpose
GalleryItem(path)@dynamicstruct wrapping one .jl example file (label, group, source, frontmatter)
Gallery(gallery_dir)Walks a directory of example files into a vector of GalleryItems
gallery_grid(items; ...)Render a grid of cards (one per item) with section headings
gallery_toolbar, gallery_controls_scriptToolbar widget + JS for filter/group controls in the grid
record!(app; record_dir, paths, full, hx, markdown)In-process recorder — drives app's routes against the registered handlers and saves HTML / fragment / markdown variants
RecordingRoutes@htmx struct mountable under a docs build to drive record! from the running app
RECORDING_STATE, RecordingStateInternal state for the recording UI (queue, progress)
MIMEResponse(content_type, body)Escape hatch for non-HTML route returns (JS, JSON, CSS, …). Bypasses __page__ wrapping and the markdown/error branches of the response pipeline

See the htmxo-gallery skill for the canonical wiring.

Built-in route bundles ​

Drop-in @htmx structs that ship with HTMXObjects and are mounted via @include:

ExportPurpose
TestRoutesTest-runner UI (see Testing section)
EditorRoutesGit-backed inline file editor (see Editor section)
StructureRoutesIntrospection browser for an @htmx/@dynamicstruct tree
SharedOpsRoutesCommon HTMX ops (refresh, clear cache, …) reusable across apps
RecordingRoutesStatic-recording driver (see Gallery section)
You are viewing the dev branch. This branch may include code written with Claude Code with less human supervision. Only human-approved code is merged into main.