Interaction Model
Interactions bring static pages to life. Momen’s interaction model is based on an Event-Driven mechanism:
- Trigger: Defines when to execute (e.g., button clicked, page loaded, scheduled time reached)
- Action: Defines what to do (e.g., update database, show toast, call API)
In Momen, there is a clear distinction between Frontend and Backend interactions:
- Frontend Interaction: Runs on the Client (Browser/Mobile), responding to user operations like clicks or swipes. It handles navigation, UI feedback, and calling backend services.
- Backend Interaction (Actionflow): Runs on the Server, handling complex business logic such as database operations, 3rd-party API calls, and scheduled tasks.
Frontend Interaction
Developer Perspective: Need to break down the above process into “when + what” logic
- When the user clicks the product card view, execute a Navigate to page action to navigate to the corresponding product detail page.
- When the user clicks the payment button on the detail page, execute a Run actionflow action to securely create the order with a pending status on the server, and upon the actionflow returning success, execute the Payment action to complete the transaction.
Corresponding Development Configuration:
- In the product card view’s “Property-Action” panel, configure a Navigate to page action under “On click”, and pass in the target page (detail page) and parameters (product id).
- In the payment button’s “Property-Action” panel, configure a Run actionflow (Create order) action under “On click” to pass the
product_idto the backend. In its “On success” branch, configure a Payment action with the order’s id and amount to be paid returned by the actionflow.
Understanding this mapping from user operations to corresponding development configurations is crucial for grasping the interaction model of Momen.
Frontend Actions
Frontend actions run on the Client (Browser), are fast, and don’t depend on the server.
In Momen, there is a clear boundary between Frontend (Client-Side) and Backend (Server-Side) interactions:
- Frontend Action (Client-Side): Runs in the user’s browser or mobile app.
- Backend Actionflow (Server-Side): Runs on the server.
Why Separate Frontend and Backend?
This separation stems from the fundamental differences in execution environments:
Security Considerations:
- Frontend code is publicly accessible and vulnerable to tampering.
- Permission-related operations (e.g., assign roles) must be executed on the backend to ensure security.
Data Consistency Guarantee:
- The frontend can be turned off at any time, or lose network connection halfway through a process. Relying on the frontend for multi-step data mutations can lead to partial updates.
- The backend database operations provide ACID transactional support, ensuring the atomicity of complex data mutations.
- Multiple database mutations that must succeed or fail together (e.g., order creation + inventory deduction) must be wrapped in a backend actionflow. (Note: Third-party API calls within a flow cannot be automatically rolled back).
Performance and Architecture:
- Computation should preferably be kept close to where the data is stored to minimize data transfer overhead and latency.
- Complex calculations, scheduled tasks, and batch processing should be executed on the server.
Logic Execution Boundaries
Frontend-Only (Client-Side Actions):
- UI operations (e.g., show/hide elements, page navigation, scroll control)
- Real-time user input validation (e.g., format checking)
- Client-side state management (e.g., set page variable)
Backend-Only (Server-Side Actionflows):
- Permission operations (e.g., assign/remove roles)
- Multi-step transactional workflows (e.g., order processing with inventory deduction)
- Scheduled tasks (e.g., daily report generation, data cleanup)
- Webhook callback handling
- Payment processing (financial operations must be server-side for security)
Can Be Done on Either:
- Database operations (CRUD)
- API calls to third-party services
- AI agent invocations
Note: For these operations, single-step actions can be placed on either the frontend or backend. However, multi-step operations should preferably be placed on the backend to ensure data consistency. Additionally, you should consider the RPS (Requests Per Second) limits when making calls from the frontend.
Frontend Interactions
Frontend interactions are configured directly in the component’s properties panel.
Trigger Types
Frontend triggers can be categorized into three types based on when they fire:
User Interaction Triggers:
- Respond to direct user actions (e.g., click, hover, scroll, gain focus).
- Used to respond to user behavior.
Parent-Child Component Trigger Order: When a parent container and a child component visually overlap and both have the same trigger configured, the execution mechanism varies depending on the specific trigger type (e.g., “On Click” behaves differently from “On Hover”). For detailed rules, refer to the Triggers Reference.
State Change Triggers:
- Respond to component state changes (e.g., input value change, video play/pause).
- Used to synchronize logic with data or status updates (e.g., validating a form immediately upon value change, triggering dependent dropdowns, or showing a ‘replay’ button when a video ends).
Lifecycle Triggers:
- Triggered automatically at specific lifecycle stages of a page, an application, or a component (Not supported yet).
- Commonly used for initializing data or cleaning up resources.
For the complete list of triggers and their use cases, refer to: Triggers Reference.
Available Actions
Frontend actions execute in the browser or mobile app and fall into four main categories:
- UI & Local Operations:
- Navigation: navigate to page, go back, open URL, etc.
- Toast & Modal: show toast, open/close modals.
- Component: set input values, scroll, switch views, play/pause media, etc.
- Operating System / Hardware Interaction: upload/download files, get location, share, clipboard, etc.
- State Management:
- Variable Control: set/reset page variables, client variables, etc.
- Data Source: refresh data sources, etc.
- Backend Calls:
- Account: sign up, sign in, sign out, reset password, etc.
- Database: create, update, delete data, transaction
- Actionflow: trigger backend workflows (e.g., payment processing, order creation)
- API: call pre-configured APIs. (When built-in actions cannot meet your needs, APIs are the tool to connect external services, such as querying weather, translating text, connecting external hardware, and other functionality. For more details, refer to: API Integration and Debugging)
- AI Agent: start/continue/stop conversations with AI agents
- Payment: initiate payments, process refunds
- Logic Control:
- Condition: condition branch processing
- For Each: execute actions for each element in a collection
Synchronous vs Asynchronous Actions
It’s important to distinguish between synchronous and asynchronous actions in frontend interactions:
-
Synchronous Actions are executed instantly. These actions cannot be interrupted, and nothing can be inserted between them. Typical examples include:
show toastshow modalnavigate to
These actions immediately update the UI or change the application state, and their completion is assumed as soon as they are called.
-
Asynchronous Actions involve a process with a beginning, waiting period, and end—they may require time to finish, and support success/failure branching. Examples include:
- Backend operations like
modify db - Triggering an
actionflow - API requests
With asynchronous actions, the next step often depends on the result (success or failure), and you can define different follow-up actions for each outcome.
- Backend operations like
Full list: Frontend Trigger & Action List.
Execution Flow
When configuring frontend interactions, multiple actions can be combined. Whether to execute sequentially or in parallel depends on how you nest actions.
Backend Interaction (Actionflow)
When actions are nested within the On success or On failure branch of a previous action, they execute sequentially.
Note: Not all actions support On success/On failure branches. Actions that involve operations requiring a response (e.g., database, API, actionflow, account) have these branches, while immediate UI operations do not.
Trigger
└─ Action A
├─ On success:
│ └─ Action B
│ └─ On success:
│ └─ Action C
└─ On failure:
└─ Action D (error handling)Backend Action Nodes
Actionflows have powerful logic capabilities and data permissions.
Use Case: When subsequent actions depend on the result of previous actions (e.g., submit an order → wait for success → use the returned order_id to navigate to the detail page)
Parallel Execution
When multiple actions are at the same level (not nested within success/failure branches), they are configured to execute parallelly. They start in sequence, but do not wait for the previous one to complete before starting the next one.
Trigger
├─ Action A
├─ Action B
└─ Action CExecution Process:
- After the trigger fires, A, B, and C start executing in sequence (A, then B, then C).
- Does not wait for any action to complete.
- Completion order is not guaranteed - actions may complete in any order.
- Error isolation - If action A fails (e.g., timeout), actions B and C will continue to execute.
Use Case: When actions are independent and you don’t need to wait for their results. Like showing a notification, then refreshing a list, then navigating to a page.
Race Condition Risk: If parallel actions access or modify the same data, the final result is unpredictable. Avoid using parallel execution when actions have data dependencies.
Backend Execution: Sync vs Async
When calling a backend Actionflow from the frontend, you can choose the mode:
- Synchronous: Calls wait for execution results. Synchronous Actionflows have ACID properties.
- Asynchronous: Returns task ID immediately (non-blocking), then listen for results. Suitable for long-running operations (e.g., calling AI Agent).
Example: Process Order
Scenario: Backend receives “Submit Order” request.
- Trigger: Called by frontend (Input: Item ID, User ID).
- Node 1 (Database): Query item inventory.
- Node 2 (Branch): Is inventory sufficient?
- Yes: Deduct inventory, create order record, return “Success”.
- No: Return “Out of Stock” error.
Context & Data Transfer
Button "On Click"
└─ Run Actionflow "submit_order"
├─ On success:
│ ├─ Show Toast "Order submitted successfully!"
│ ├─ Navigate to "order_list"
│ └─ Refresh order list
└─ On failure:
└─ Show Toast "Submission failed"Action Result
Context contains the result of the previous action. Whether in frontend serial execution or backend Actionflow, the next node can access the result of the previous node via Context.
Note: Since Toast, navigation, and refresh are configured to execute in parallel, the page will navigate immediately, and the Toast may not be visible. If you need to ensure users see the notification, handle this by using Schedule job to delay the execution.
This example demonstrates:
- Sequential / Synchronous Execution: Wait for Actionflow to complete first
- Asynchronous Execution: Multiple UI actions execute without waiting for each other after success
- Error Handling: Execute different logic on failure
Backend Logic (Actionflows)
Backend logic are configured in the Actionflow panel. Actionflows run on the server and support multi-step business logic orchestration.
Trigger Types
Actionflows can be triggered in the following ways:
Called by Frontend:
- Invoked by frontend actions to handle user requests (e.g., form submission, payment processing).
- Can pass inputs and return execution results.
Triggered by System:
- Scheduled Tasks (Cron): Automatically execute according to a schedule, for periodic tasks (e.g., daily report generation, data cleanup).
- Webhook: Receive HTTP callbacks from external systems, for system integration (e.g., payment gateway callbacks, third-party order sync).
- Data Changes: Automatically triggered by database changes, useful for automated data syncing or cascading updates (e.g., assign initial points when new user registers, sync data to external systems).
For complete list of triggers and their use cases, refer to: Triggers Reference.
Available Nodes
Actionflows are where you implement complex logic and orchestrate multi-step processes. You do that by connecting and configuring different nodes. Common node types include:
Database Operations:
- Create, read, update, delete data (Database CRUD)
Integrations:
- Call APIs
- Run other Actionflows
- Run AI Agents
Logic Operations:
- Condition
- For Each
- While Loop
Privileged Operations (Backend-only):
- Permission Operations (e.g., assign/remove roles)
- Backend Code Execution (Code Block)
Others:
- Get user information (e.g., account ID)
- File processing (save images, videos, files, etc.)
For the complete list of node types, refer to: Actionflow Nodes Reference. How to build an actionflow, refer to: Building Actionflows.
Actionflow Execution Modes
When creating an Actionflow, you must choose its execution mode:
| Mode | Response | Transaction | Timeout Limit | Use Case | | :--- | :--- | :--- | :--- | | Synchronous | Caller waits for result | Database operations support ACID transactions with rollback support. Other operations follow their own mechanisms | Entire flow: 15s (unlimited for dedicated instances) | e.g., Inventory tracking, Payment processing | | Asynchronous | Returns task ID immediately. Caller does not wait. | Not transactional | Each node: 15s (unlimited for dedicated instances) | Long-running tasks (e.g., AI agent execution, Video generation) |
Currently, the AI node must be used in asynchronous execution mode.
Example: Payment Webhook Processing Actionflow
Scenario: Backend receives payment result callback from Stripe.
Configuration:
- Trigger: Webhook
- Variables: status (Text), message (Text)
- Outputs: status (Text), message (Text)
Node Flow:
1. [Code Block Node] extract_webhook_data
Function: Extract webhook data
Output: payment_status, order_id, payment_found
2. [Condition Node] check_payment_found
Condition: payment_found = true
├─ TRUE branch (payment record exists):
│ 3. [Condition Node] check_payment_status
│ Condition: payment_status = "success"
│
│ ├─ TRUE branch (payment successful):
│ │ 4. [Database Query Node] query_payment
│ │ Query: payment_record
│ │ Where: order_id = extract_webhook_data.order_id
│ │ Output: account_id
│ │
│ │ 5. [Database Update Node] update_account
│ │ Update: account
│ │ Where: account_id = query_payment.account_id
│ │ Update: is_member = true
│ │
│ │ 6. [Set Variable Node] set_success
│ │ Set: status = "Payment Successful"
│ │
│ │ 7. [Set Variable Node] set_message
│ │ Set: message = "Membership activated"
│ │
│ └─ FALSE branch (payment failed):
│ 8. [Set Variable Node] set_failed_status
│ Set: status = "Payment Failed"
│
│ 9. [Set Variable Node] set_failed_message
│ Set: message = "Payment failed, membership not activated"
│
└─ FALSE branch (order not found):
10. [Set Variable Node] set_error_status
Set: status = "Order Not Found"
11. [Set Variable Node] set_error_message
Set: message = "Order not found, please place order again"
12. [Output Node] Return result
Output: {status, message}Action Results and Data Transfer
Action Results are output data produced by actions or nodes during execution. They are part of the Context data.
Beyond action results, the context also includes environmental data (e.g., Current User, Current Time, Current Page, Current Component). For details on these, see: Data Binding.
This section focuses on how actions produce results and how subsequent actions consume them.
Core Principles:
- Unidirectional Transfer: Data flows from earlier actions to later actions only
- Execution Order Matters: Only sequential actions (not parallel) can access previous results
- Data Scope (Branch Isolation): Action results have local scope - data created inside a branch (Condition/Loop) only exists within that branch.
- Inside a Loop branch, the system automatically injects a local
Current Itemcontext for inner nodes to reference the current iteration. - To access or pass data out of the branch, you must use a variable with global scope (Page/Client variable for frontend, Actionflow variable for backend) initialized outside the loop and updated inside.
- Inside a Loop branch, the system automatically injects a local
Accessing Execution Results
General Output Rule: Whether configuring Frontend Actions or Backend Nodes, the rule for producing results is identical: Only operations that query, mutate, or process data generate output results (e.g., Database CRUD, API calls, Account operations, Code blocks). Operations that purely control UI, routing, or internal logic flow (e.g., Navigation, Show toast, Condition, Loop, Set variable) do not produce results.
Data Binding Paths: When configuring subsequent steps, you can bind data using the following paths:
- Frontend Actions:
Context→Action results→Action name→Field name - Backend Actionflows:
Actionflow data→Node name→Field name
For complete output field schemas of specific actions/nodes, refer to: Actionflow Nodes Reference and Frontend Actions Reference.