# Source: https://dev.writer.com/framework/custom-server.md

# Custom server

Framework uses Uvicorn and serves the app in the root path i.e. `/`. If you need to use another ASGI-compatible server or fine-tune Uvicorn, you can easily do so.

## Configure webserver

You can tune your server by adding a `server_setup.py` file to the root
of your application, next to the `main.py` files.

This file is executed before starting writer. It allows you to configure [authentication](./authentication.md),
add your own routes and middlewares on FastAPI.

```python  theme={null}
# server_setup.py
import typing

import writer.serve

if typing.TYPE_CHECKING:
    from fastapi import FastAPI

# Returns the FastAPI application associated with the writer server.
asgi_app: FastAPI = writer.serve.app

@asgi_app.get("/probes/healthcheck")
def hello():
    return "1"
```

<Warning>
  `server_setup.py` is disabled by default on edit mode. If you want to use in `edit` mode, you can launch `writer edit --enable-server-setup <app>`.
</Warning>

## Implement custom server

You can import `writer.serve` and use the function `get_asgi_app`. This returns an ASGI app created by FastAPI, which you can choose how to serve.

The following code can serve as a starting point. You can save this code as `serve.py` and run it with `python serve.py`.

```py  theme={null}
import uvicorn
import writer.serve

app_path = "." # . for current working directory
mode = "run" # run or edit

asgi_app = writer.serve.get_asgi_app(app_path, mode)

uvicorn.run(asgi_app,
    host="0.0.0.0",
    port=5328,
    log_level="warning",
    ws_max_size=writer.serve.MAX_WEBSOCKET_MESSAGE_SIZE)
```

Note the inclusion of the imported `ws_max_size` setting. This is important for normal functioning of the framework when dealing with bigger files.

Fine-tuning Uvicorn allows you to set up SSL, configure proxy headers, etc, which can prove vital in complex deployments.

If you want to disable server setup hook, you should use `enable_server_setup`:

```python  theme={null}
asgi_app = writer.serve.get_asgi_app(app_path, mode, enable_server_setup=False)
```

## Multiple apps at once

Framework is built using relative paths, so it can be served from any path. This allows multiple apps to be simultaneously served on different paths.

The example below uses the `get_asgi_app` function to obtain two separate Framework apps, which are then mounted on different paths, `/app1` and `/app2`, of a FastAPI app.

```py  theme={null}
import uvicorn
import writer.serve
from fastapi import FastAPI, Response

root_asgi_app = FastAPI(lifespan=writer.serve.lifespan)
sub_asgi_app_1 = writer.serve.get_asgi_app("../app1", "run")
sub_asgi_app_2 = writer.serve.get_asgi_app("../app2", "run")

root_asgi_app.mount("/app1", sub_asgi_app_1)
root_asgi_app.mount("/app2", sub_asgi_app_2)

@root_asgi_app.get("/")
async def init():
    return Response("""
    <h1>Welcome to the App Hub</h1>
    """)

uvicorn.run(root_asgi_app,
    host="0.0.0.0",
    port=5328,
    log_level="warning",
    ws_max_size=writer.serve.MAX_WEBSOCKET_MESSAGE_SIZE)
```