Lesson 25 of 49 · Layout language

Layout on the web

When targeting the web, Salam's layout DSL compiles to HTML, CSS, and (when needed) JavaScript. This lesson focuses on web-specific output and runtime behavior: building, browser/DOM interactivity, and serving pages.

Building web output

salam page build page.salam produces page.html and page.css, plus page.js when scripts/events are present. Use --inline for a single self-contained HTML file. With multiple inputs (e.g. salam page build home.salam about.salam) each page gets its own HTML and they can share a common style.css. With no file name, the tool typically builds main.salam if present, otherwise layout pages in the folder.

Styles are extracted into generated classes/rules in the stylesheet so HTML stays compact and reusable.

Browser events and DOM

Event attributes such as click, submit, input, change, etc. become interactive behavior in the browser. Salam handlers attached to events are compiled into the page script for web builds. In handlers you can work with the DOM (e.g. dom.ById/dom.Query) as covered in the events lessons.

See Mouse events through State, the DOM and timers for the full browser event/DOM model.

Parameterized layouts and runtime rendering

Parameterized layouts can render HTML at runtime with request-specific data, which is useful for Salam web servers. Inserted parameter text is escaped for safety. For sensitive/structured values (URLs, colors, lengths, etc.) validate/parse them appropriately before use.

layout-runtime.salam
page Card(name: str, score: int):
    title = "Card " + name
    heading: size = 2 content = name end
    if score >= 50:
        paragraph: content = "pass" end
    else:
        paragraph: content = "fail" end
    end
end

func main:
    println Card("Ali", 70)
end
Output<!doctype html><html lang="en" dir="ltr"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>Card Ali</title></head><body><h2>Ali</h2><p>pass</p></body></html>
layout-server.salam
import net.http
import net.router

page Greeting(name: str):
    title = "Hello " + name
    heading: size = 1 content = "Hello, " + name end
    paragraph: content = "This page was rendered on the server." end
end

func home(ctx: i64):
    mut name := http.Query(ctx, "name")
    if name == "":
        name = "guest"
    end
    http.Html(ctx, Greeting(name))
end

func main:
    mut r := router.NewRouter()
    router.Get(r, "/", home)
    mut s := http.NewServer(8080)
    http.Use(s, r)
    http.Run(s)
end

Serving and web projects

Built files can be hosted on any static web server, or served locally/production with salam serve. Salam programs can also return rendered HTML using networking packages such as net.http and net.router.

layout-inbox.salam
component Badge(text: str):
    span: content = text background = #fde68a end
end

page Inbox(user: str, subjects: Vector<str>):
    title = "Inbox of " + user
    heading: size = 1 content = "Hello, " + user end
    if subjects.IsEmpty():
        paragraph: content = "No new messages" end
    else:
        paragraph: content = "Unread: " + subjects.Len() end
        list:
            each i, s in subjects:
                item: content = (i + 1) + ". " + s end
            end
        end
    end
end

func main:
    mut subjects := Vector {} as Vector<str>
    defer subjects.Free()
    subjects.Push("Meeting at 10")
    subjects.Push("<b>FREE</b> prize & more")
    println Inbox("Sara", subjects)
    println Badge("new")
end
Output<!doctype html><html lang="en" dir="ltr"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>Inbox of Sara</title></head><body><h1>Hello, Sara</h1><p>Unread: 2</p><ul><li>1. Meeting at 10</li><li>2. &lt;b&gt;FREE&lt;/b&gt; prize &amp; more</li></ul></body></html> <style>.badge-a{background:#fde68a}</style><span class="badge-a">new</span>

Notes

  • Browser features (forms behavior, media APIs, scrolling, clipboard, storage, etc.) are web-environment specific.
  • Interactive pages rely on the page script running in the browser.
  • For browserless native windows, see Layout in native apps.