HJX is a unified declarative UI language that compiles into:
- HTML
- CSS
- JavaScript
from a single .hjx file.
The goal is to compress structure, style, and behavior into one coherent, AI-friendly language.
- Philosophy
- File Structure
- Indentation Rules
- Full Grammar (EBNF)
- Component Declaration
- State Block
- Layout Block
- Style Block
- Handlers Block
- Expressions
- Interpolation
- Current Limitations (v0.1)
HJX is:
- Declarative-first
- Scoped-by-default
- AI-friendly
- Deterministic
- Indentation-based (like Python)
A .hjx file consists of top-level blocks:
component <Name>
state:
layout:
style:
handlers:
Order is flexible but recommended in that order.
HJX is indentation-sensitive.
- Top-level blocks → 0 spaces
- Inside blocks → 2 spaces
- Each nested level → +2 spaces
- Tabs are not recommended (use spaces only)
Example:
layout:
view:
text: "Hello"
File = { SkippableLine | TopStmt } ;
TopStmt = ComponentDecl
| StateBlock
| LayoutBlock
| StyleBlock
| HandlersBlock ;
ComponentDecl = "component" SP Identifier NEWLINE ;
Identifier = Letter { Letter | Digit | "_" } ;
Letter = "A"…"Z" | "a"…"z" | "_" ;
Digit = "0"…"9" ;
Example:
component Counter
StateBlock = "state:" NEWLINE { StateLine } ;
StateLine = IND2 Identifier SP? "=" SP? StateValue NEWLINE ;
StateValue = Number | Boolean | String ;
Number = [ "-" ] Digit { Digit } [ "." Digit { Digit } ] ;
Boolean = "true" | "false" ;
String = DQString | SQString ;
DQString = """ { CharNoDQ } """ ;
SQString = "'" { CharNoSQ } "'" ;
Example:
state:
count = 0
title = "Hello"
enabled = true
LayoutBlock = "layout:" NEWLINE LayoutTree ;
LayoutTree = { LayoutLine } ;
LayoutLine = ContainerLine | LeafLine ;
ContainerLine = IND2plus NodeHead ":" NEWLINE { ChildLine } ;
LeafLine = IND2plus LeafBody NEWLINE ;
NodeHead = Tag [ IdPart ] { ClassPart } ;
Tag = Letter { Letter | Digit | "-" | "_" } ;
IdPart = "#" Identifier ;
ClassPart = "." ClassAtom ;
ClassAtom = (Letter|Digit) { Letter | Digit | "-" | "_" } ;
Examples:
view
view#main
view.card
view#main.card.primary
LeafBody = NodeHead [ ParenClause ] ":" String ;
Example:
text: "Hello"
button.primary: "Click me"
ParenClause = "(" OnClickClause ")" ;
OnClickClause = "on" SP "click" SP? "->" SP? Identifier ;
Example:
button (on click -> inc): "Increase"
BindValueClause = "bind" SP "value" SP? "<->" SP? Identifier ;
Example:
input (bind value <-> email)
StyleBlock = "style:" NEWLINE { StyleLine } ;
StyleLine = IND2 { AnyChar } NEWLINE ;
Raw CSS is allowed. Compiler automatically scopes CSS.
HandlersBlock = "handlers:" NEWLINE { HandlerDecl } ;
HandlerDecl = IND2 Identifier ":" NEWLINE
{ HandlerLine } ;
HandlerLine = IND4 Statement NEWLINE ;
Statement = SetStmt | LogStmt ;
SetStmt = "set" SP Identifier SP? "=" SP? Expr ;
LogStmt = "log" SP String ;
Example:
handlers:
inc:
set count = count + 1
debug:
log "clicked"
Expr = Term { ("+" | "-") Term } ;
Term = Factor { ("*" | "/") Factor } ;
Factor = Number | Identifier | "(" Expr ")" ;
Allowed:
- numbers
- state identifiers
-
-
-
- /
-
-
- parentheses
Inside strings:
"Hello {{name}}"
Grammar:
Interpolation = "{{" SP? Identifier SP? "}}" ;
CommentLine = { SP } "//" { AnyChar }
Example:
// This is a comment
| HJX Tag | HTML |
|---|---|
| view | div |
| text | span |
| button | button |
| input | input |
Other tags pass through directly.
component Counter
state:
count = 0
layout:
view.card:
text: "Count: {{count}}"
button.primary (on click -> inc): "Increase"
style:
.card { padding: 16px; border: 1px solid #ddd; }
handlers:
inc:
set count = count + 1
Implemented since initial v0.1 spec:
- ✅ Conditionals (
if/if !/if ===/if !=) - ✅ Loops (
for item in items) - ✅ Component composition (
imports:block with props and slots)
Current limitations:
- Only
clickevent supported (noinput,submit,changeevents in handlers DSL) - Only
bind value <-> stateKeybinding - No computed state
- No async handlers
- No multi-target codegen (React/Vue)
Planned additions:
- if / else
- for item in items
- multiple events (input, submit, change)
- attributes block
- computed state
- effects
- component composition
- multi-target codegen (React/Vue)
HJX is intentionally:
- Context-compressible
- AST-friendly
- Low-ambiguity
- LLM-safe
- Easily parsable
© 2026 HJX Language