nenu-lang / page-apis-and-ui
StablePage APIs, Navigation, And UI
- Import an API from its root-qualified api path and call the local alias.
- Use goto with a known page route and primitive dynamic parameters.
- Open a modal with one imported component object and use toast for visible feedback.
Import And Call An API
code
1use api/expenses/list as ListExpensesApi2use "api/expenses/create" as CreateExpenseApi34fn refreshExpenses() {5 result = ListExpensesApi({ room_id })6 expenses = result.expenses7}89fn createExpense() {10 created = CreateExpenseApi({11 room_id12 payer_id13 title: draft_title14 amount: draft_amount15 note: draft_note16 })1718 expenses = expenses + [created.expense]19}- Use a root-qualified target beginning with
api/. - An unquoted target and a quoted target are equivalent.
- The alias is required and becomes the callable name.
- Call the alias with no payload only when the Request contract permits it.
- Pass one map payload when fields are required; missing or incompatible fields are type errors.
- The call result is typed from the API Response contract.
Name A Type From An API Response
code
1type ExpenseRow as Response("/expenses/list").expenses.item23ExpenseRow[] expenses = []45fn refreshExpenses() {6 result = ListExpensesApi({ room_id })7 expenses = result.expenses8}- Use
type Name as Response("/route"); the alias keyword isas, not=. - The quoted route identifies an API Response contract known to the project.
- Add selectors such as
.expenses.itemto name a nested field or an array item type. - An entity item alias includes its generated system fields, including
id,createdAt, andupdatedAt. - Response aliases are supported at Page Script top level. There is no corresponding public
Request(...)alias form.
Navigate With goto
code
1goto("/expenses")- The route string must identify a known Page path.
- Dynamic values must be
string,number, orbool. - The explicit params map is canonical, especially for a dotted value such as
expense.id. - Omit the map only when every bracket parameter has a same-name primitive local.
- A guaranteed
goto()makes later statements on that path unreachable.
Open A Typed Modal
Import a library component, then pass exactly one component object to modal.show. The component’s Page Script need block defines the required values and callbacks.
code
1use library/AddExpense as AddExpenseModal23fn handleSaved(Expense expense) {4 expenses = expenses + [expense]5 toast.success("Expense added")6}78fn openAddExpense() {9 modal.show(AddExpenseModal {10 room_id11 onSaved: handleSaved12 })13}1415fn cancelModal() {16 modal.close()17}- The component must be imported before use.
- Component values use
name: valuefields inside the object. - Callback values are handler references, not calls.
- The owner page decides how to update its state after the modal succeeds.
Show Feedback With toast
code
1toast.success("Expense saved")2toast.warning("Some shares are still missing")3toast.error("Expense could not be saved")A toast is visible page feedback. It is not a backend log, a durable audit record, or an API error contract. Put it after the page knows which outcome occurred.
Complete Room Page Script
code
1use api/expenses/list as ListExpensesApi2use api/expenses/create as CreateExpenseApi3use library/AddExpense as AddExpenseModal45need {6 room_id: string7}89Expense[] expenses = []10bool loading = false11Expense? selected_expense = ?1213fn refreshExpenses() {14 loading = true15 result = ListExpensesApi({ room_id })16 expenses = result.expenses17 loading = false18}1920fn handleSaved(Expense expense) {21 expenses = expenses + [expense]22 toast.success("Expense added")23}2425fn openCreate() {26 modal.show(AddExpenseModal {27 room_id28 onSaved: handleSaved29 })30}3132fn openExpense(Expense expense) {33 goto("/expenses/[id]", { id: expense.id })34}3536on load() {37 refreshExpenses()38}Common Mistakes
| Wrong | Correct |
|---|---|
Direct api(...) | use api/path as Alias, then Alias(...). |
Target apis/expenses/list | Target api/expenses/list. |
goto("/expenses/[expense.id]") | goto("/expenses/[id]", { id: expense.id }) |
modal.show("AddExpense") | Import the component and pass one typed component object. |
Use backend log for feedback | Use a Page Script toast. |
