3. Replace src/main.luau
luastra/navigation · checked parameters · about 15 minutescomplete runnable entry module
Route definitions validate parameters and queries before a mutation can enter the stack.
When to use it
Replace the entire generated src/main.luau file; the compact layout intentionally omits host History so the router contract is visible first.
Focused example
--!strict
local Navigation = require("luastra/navigation")
local UI = require("luastra/ui")
local routes = Navigation.compile {
{ name = "home", path = "/" },
{
name = "workspace",
path = "/workspaces/:workspace_id",
params = { workspace_id = { type = "integer", minimum = 1, maximum = 999 } },
},
{
name = "document",
parent = "workspace",
path = "documents/:document_slug",
params = { document_slug = { type = "string", maximumLength = 32 } },
query = { mode = { type = "enum", values = { "read", "edit" }, required = true } },
},
}
local router = Navigation.createRouter {
compiler = routes,
initial = { name = "home", params = {}, query = {} },
}
local App = require("luastra/app")
local Root = {}
function Root.render(): UI.Node
local current = router.current()
return UI.Screen {
id = "routing-lab",
UI.Text { id = "routing/title", text = "Routing lab", variant = "title" },
UI.Text { id = "routing/name", text = "Route: " .. current.name },
UI.Text { id = "routing/location", text = router.currentLocation(), role = "status" },
UI.Actions {
id = "routing/actions",
UI.Button {
id = "routing/workspace",
text = "Open workspace",
onTap = "open-workspace",
},
UI.Button {
id = "routing/document",
text = "Open document",
onTap = "open-document",
},
UI.Button {
id = "routing/back",
text = "Back",
onTap = "back",
disabled = not router.canBack(),
},
},
}
end
function Root.handle(action: string, target: string, _value: string)
if action == "open-workspace" and target == "routing/workspace" then
router.push { name = "workspace", params = { workspace_id = 7 }, query = {} }
elseif action == "open-document" and target == "routing/document" then
router.push {
name = "document",
params = { workspace_id = 7, document_slug = "release-notes" },
query = { mode = "edit" },
}
elseif action == "back" and target == "routing/back" then
router.back()
end
end
function Root.snapshot()
return {
name = router.current().name,
location = router.currentLocation(),
}
end
return App.compose {
render = function(_outputs) return Root.render() end,
handle = Root.handle,
snapshot = Root.snapshot,
}