Skip the bullshit
// docs / Language

Fetch, await and server functions

Typed HTTP and functions that run on the server, both checked by the compiler.

vcwl
on click {
fetch get("/api/items") as [Item] {
Ok(items) => {
list = items
}
Err(Status(404, _)) => {
error = "not found"
}
Err(e) => {
error = e.message()
}
}
}

Responses are decoded and validated against the type you ask for. Network access must be declared in the app's capabilities, and the host and the Content-Security-Policy both enforce it:

vcwl
app "My app" {
capabilities {
network: allow("self", "api.example.com")
storage: local
}
}

Server functions

vcwl
server fn sign(name: String, text: String) -> [Entry] {
let all = load<[Entry]>("entries").unwrap_or([])
.push(Entry { name: name, text: text })
save("entries", all)
all
}
// in a handler:
fetch sign(who, message) {
Ok(entries) => {
guestbook = entries
}
Err(e) => {
error = e.message()
}
}

vcwl serve runs them in a WebAssembly runtime with a small JSON key-value store. There is no auth: anyone can call them with any arguments of the right types. Plan accordingly.

await

vcwl
on click {
loading = true
let res = await get("/api/items") as [Item]
loading = false
match res {
Ok(items) => list = items,
Err(e) => error = e.message(),
}
let saved = await sign(name, text) // server functions and extern fns too
}

The handler stops at the await and the rest of it runs when the response arrives, with a Result as the value. Local variables come along (as copies), state is read fresh, and nothing runs if the component is gone by then.

SQL, HTTP, sessions and limits

vcwl
server fn recent() -> Result<[Entry], String> {
exec("insert into log(x) values (?)", ["hit"])?
query<Entry>("select name, text from entries", [])
}
server fn ping(url: String) -> Result<HttpResponse, String> {
http("GET", url, "")
}
server fn me() -> String? { session("user") }
→

query and exec use a SQLite file next to the store (<store>.sqlite); params are bound as text.

→

http(method, url, body) returns HttpResponse { status, body }. It shells out to curl with a 10 s timeout.

→

session(key), set_session(key, value) and end_session(key) use an HMAC-SHA256 signed vcwl_session cookie. The secret comes from VCWL_SECRET, or is generated and kept in the store.

→

Calls run in parallel, each in its own instance. A vcwl.limits.toml sets calls_per_minute = N and per-function limits under [functions], per client IP; going over gets a 429.