ZeroScript

Build webapps with zero JavaScript

ZeroScript is an HTML-like syntax designed for building rich web applications using languages other than JavaScript.

This goal remains unrealistic until other languages can both generate HTML and manipulate the DOM. The solution is to use an HTML-first approach — instead of putting HTML inside your logic, ZeroScript puts your logic inside your HTML.

    button onclick=...expression...
      Clicks: count
    button

This is NOT intended to be implemented by browsers or engines nor is it a proposal for the HTML spec itself. Think of it like Markdown — a small set of "preprocessor rules" for yielding predictable results regardless of underlying language or platform.

Learn ZeroScript

3 minutes

If you know HTML, you're already 90% there. Learn the rest in just 3 minutes...

Components

1 of 14

MyButton.html

button
  Click me
button

Components are just vanilla HTML files. No imports necessary.

Attributes

2 of 14

index.html

html
  body
    MyButton
      message="Click me"
    
  body
html

Use attributes to pass read-only values into a component.

index.html

html
  body
    MyButton
      message="Click me"
      max=10
      reset=false
    
  body
html

Use JSON-like syntax to strongly-type numbers and booleans (unquoted attributes).

Expressions

3 of 14

index.html

html
  body
    MyButton 
      message="Click me"
      max=10
      reset=false
      expires=date 
    
  body
html

Complex objects and arrays can be passed as attributes when escaped as an expression .

MyButton.html

button
  h1messageh1
  pLimit: maxp
  divBy: expiresdiv
button

Access attribute values inside your component using expressions.

MyButton.html

button
    h1message ?? "Click me"h1
    pLimit: max * 2p
    divBy: expires.Minutes.Agodiv
button

Any expression is valid. Full statements are not valid (i.e. code often separated by semicolons).

MyButton.html

button
    h1message ?? "Click me"h1
    pLimit: max * 2p
    divBy: expires.Minutes.Agodiv
button

Expressions serve as portals into new languages beyond just JavaScript. More on that in the script section below...

if

4 of 14

button
  if count < 10
    Clicks: count
  if
button

if is a control-flow tag that can optionally include its contents.

button
  if count < 10
    Clicks: count
  if
button

Control-flow tags include, exclude, or repeat their contents, but the parent tag (if) itself is never a part of the DOM.

if first=user?.Name?.First
  h1Greetings first!h1
if

The if tag can handle “if-let” control flow. The contents are only included if the assigned value is non-null.

else

5 of 14

if first=user?.Name?.First
  h1Greetings first!h1
if
else
  h2Loading...h2
else

Use else as a sibling tag to if. No enclosing parent tag is necessary.

else-if

6 of 14

if first=user?.Name?.First
  h1Greetings first!h1
if
else-if isLoading
  h2Loading...h2
else-if
else
  buttonSign inbutton
else

Optionally chain as many else-if tags as you like.

for

7 of 14

ul
  for article=articles
    li
      a href=article.Url
        article.Title
      a
    li
  for
ul

Repeat contents with for.

Slots

8 of 14

html
  body
    MyButton
      h1 slot="message"
        Click bmeb
      h1
    MyButton
  body
html

Use slots to pass HTML as inputs into your component. Similar to attributes, components access them with an expression, e.g. message.

Routes

9 of 14

📦 my-project
└─ 📂 blog
    ├─ 📜 index.html     example.com/blog
    └─ 📜 MyButton.html  (private)

While every .html file is a component, only index.html files have addressable routes.

📦 my-project
 └─ 📂 blog
    ├─ 📜 index.html     ex.com/blog
    └─ 📜 MyButton.html  (private)
    └─ 📂 slug
       └─ 📜 index.html  ex.com/blog/hi-there
                         ex.com/blog/one-more
                         ex.com/blog/last-one

Use the escape sequence in directory names to define dynamic routing.

state

10 of 14

state score=0 
MyButton count=score 
h1The score is scoreh1

Use state for values that change. state can be shared with and changed by other components.

state name="World" 
input value=name 
h1Hello name!h1

When state is assigned to an attribute, any changes to the attribute's value also changes the state. Here, every keypress will update the h1 tag.

style

11 of 14

MyButton.html

style
  button { color: red; }
style

button
  Click me
button

style tags inside a component will have its CSS scoped to only that component.

script

12 of 14

MyButton.html

script language="ANY-LANGUAGE"
  func handleClick(e):
    print("Button was clicked.");
script

button onclick=handleClick
  Click me
button

Use script to contain logic in any language. This tag is never included in HTML output to the browser.

MyButton.html

state count=0 
button onclick=e => count++
  Clicks: count
button

If the guest language supports inline expressions, the script tag can be optional.

Sibling Files

13 of 14

📦 my-project
├─ 📜 MyButton.html
├─ 💄 MyButton.css
└─ 🤖 MyButton.**

Instead of embedding style and script tags, optionally use separate files. No imports necessary, just use the same file name.

HTTP/X

14 of 14

HTTP:
browser ------- GET -------> server
browser <------ HTML ------- server

HTTP/X:
browser ----- DOM EVENT ---> server or wasm
browser <--- DOM CHANGES --- server or wasm

HTTP/X represents a collection of HTTP-based protocols designed for use cases where state and logic live on the server or in WASM instead of in the browser via JavaScript.

Instead of requesting HTML with a GET, HTTP/X forwards browser events to server-side (or WASM) event handlers which respond with standardized instructions for manipulating the DOM.

Read more at httpx.org.

ZeroScript

Done!


          
🎉

Now you know the ZeroScript syntax!

Get started using your favorite language:

Language Project
C# / .NET github.com/xui/xero
Java / Kotlin introduce yourself 👋
Ruby introduce yourself 👋
Python introduce yourself 👋
Go introduce yourself 👋
Rust introduce yourself 👋
Swift introduce yourself 👋
Perl introduce yourself 👋
Other? introduce yourself 👋