Frappe ships with an API for realtime events based on socket.io. Since socket.io needs a Node server to run, we run a Node process in parallel to the main web server.

Client APIs (JavaScript)

frappe.realtime.on

To listen to realtime events on the client (browser), you can use the frappe.realtime.on method:

frappe.realtime.on('event_name', (data) => {
    console.log(data)
})

frappe.realtime.off

Stop listening to an event you have subscribed to:

frappe.realtime.off('event_name')

Server APIs (Python)

frappe.publish_realtime

To publish a realtime event from the server, you can use the frappe.publish_realtime method:

frappe.publish_realtime('event_name', data={'key': 'value'})

frappe.publish_progress

You can use this method to show a progress bar in a dialog:

frappe.publish_progress(25, title='Some title', description='Some description')

frappe publish realtime

Custom Event Handlers

Note: This feature is only available in nightly (v16) version. This feature is considered experimental.

You can implement custom real-time event handlers by creating a handlers.js file in real-time folder of your app.

You need to specify a single export from this file - a function that will setup event handlers on the socket instance. E.g. if you are developing an app called "chat", here's how the file should look like

// bench/apps/chat/realtime/handlers.js

function chat_app_handlers(socket) {
    socket.on("hello_chat", () => {
    console.log("hello world!");
    });
}

module.exports = chat_app_handlers;


You can trigger this event using client side code frappe.realtime.emit("hello_chat"). Note that you might have to restart socketio server to see effect of code changes. Refer SocketIO documentation to learn more about writing custom event handlers: https://socket.io/docs/v4/

Custom Client

You can write a custom client to connect to socket.io server if you're developing a SPA or a mobile app that doesn't use Desk interface. You can refer to official socket.io documentation for building your custom client: https://socket.io/docs/v4/client-initialization/

Here are some examples of custom clients:

Authorization in custom clients

There are two ways to authenticate a connection with socket.io server:

Implementation Notes

  • Realtime server uses socket.io server. The server is written in node.js and can be found in /realtime directory.

  • Realtime client is wrapper around socket.io client library and can be found in public/js/frappe/socketio_client.js.

  • Python processes publish events to node server using Redis pub-sub channel. Realtime server subscribes to the Redis channel and publishes it to all subscribed clients.

  • Realtime server is multi-tenant, all site-related traffic is namespaced by sitename. Namespaces are dynamically created using /{sitename} format where sitename is name of site's folder in sites directory or frappe.local.site.

  • Realtime server uses main Frappe web server to authenticate connections. SID cookie or authorization header are passed to client and realtime server uses it to ensure that the connection is from a valid user and can subscribe to certain DocType or documents based on permissions.

  • Realtime implementation allows the following rooms:

    • all - Room accessible and connected by default to all System Users.

    • website - Room accessible and connected by any user, even Guests.

    • user:{username} - Dynamic room created for each user. Allowed without any permission checks.

    • doctype:{doctype} - Dynamic room created for each DocType. Only user with permission to the DocType can join said room. User is automatically subscribed to this room when they open list view or form view of the document.

    • doc:{doctype}/{name} - Dynamic room created for each document. Only user with permission to the document room can join said room. User is automatically subscribed to this room when they form view of the document.