> ## Documentation Index
> Fetch the complete documentation index at: https://dev.writer.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Backend-initiated actions

Targeted, backend-initiated actions can be triggered from event handlers, using methods of `state`. Internally, this is achieved using Framework's `mail`, ephemeral state that is cleared when it reaches the intended user.

## Triggering a file download

The `file_download` method takes the `data` and `file_name` arguments. The first must contain raw bytes (a `bytes` object) or a packed file. As mentioned in the [Application State](/framework/application-state#managing-files-and-binary-data) section of the guide, a packed file is obtained using the `wf.pack_file` or `wf.pack_bytes` methods.

```py theme={null}
def handle_file_download(state):
    # Pack the file as a FileWrapper object
    data = wf.pack_file("assets/story.txt", "text/plain")
    file_name = "thestory.txt"
    state.file_download(data, file_name)
```

## Adding a notification

<img src="https://mintcdn.com/writer/eBiCs3I5_-mSTcT-/framework/images/backend-initiated-actions.notifications.png?fit=max&auto=format&n=eBiCs3I5_-mSTcT-&q=85&s=ae08937660ab594dfbefadb6b5ef8bab" alt="Notifications" width="2291" height="697" data-path="framework/images/backend-initiated-actions.notifications.png" />

Framework adds notifications when a runtime error takes place. You can add your own notifications using the `add_notification` method, which takes the `type`, `title` and `message` arguments. `type` must be one of `error`, `warning`, `info`, `success`.

```py theme={null}
def notify_of_things_that_happened(state):
    state.add_notification("error", "An Error", "Something bad happened.")
    state.add_notification("warning", "A Warning", "Be aware that something happened.")
    state.add_notification("info", "Some Info", "Something happened.")
    state.add_notification("success", "A Success", "Something good happened.")
```

## Opening a URL

Open a URL in a new tab using the `open_url` method, which takes the `url` argument.

```py theme={null}
def handle_open_website(state):
    state.open_url("https://writer.com")
```

The URL will be safely opened with `noopener` and `noreferrer` options.

<Warning>
  Popup blockers: Given that the URL is opened asynchronously, popup blockers will likely block the new window —unless the user has opted in.
</Warning>

## Changing the active page

The active page and route parameters can be changed using the methods `set_page` and `set_route_vars`. This is explained in more detail in [Page Routes](/framework/page-routes).
