# Using Jupyter to write FastHTML
Writing FastHTML applications in Jupyter notebooks requires a slightly
different process than normal Python applications.
> **Download this notebook and try it yourself**
>
> The source code for this page is a [Jupyter
> notebook](https://github.com/AnswerDotAI/fasthtml/blob/main/nbs/tutorials/jupyter_and_fasthtml.ipynb).
> That makes it easy to directly experiment with it. However, as this is
> working code that means we have to comment out a few things in order
> for the documentation to build.
The first step is to import necessary libraries. As using FastHTML
inside a Jupyter notebook is a special case, it remains a special
import.
``` python
from fasthtml.common import *
from fasthtml.jupyter import JupyUvi, HTMX
```
Let’s create an app with `fast_app`.
``` python
app, rt = fast_app(pico=True)
```
Define a route to test the application.
``` python
@rt
def index():
return Titled('Hello, Jupyter',
P('Welcome to the FastHTML + Jupyter example'),
Button('Click', hx_get='/click', hx_target='#dest'),
Div(id='dest')
)
```
Create a `server` object using
[`JupyUvi`](https://www.fastht.ml/docs/api/jupyter.html#jupyuvi), which
also starts Uvicorn. The `server` runs in a separate thread from
Jupyter, so it can use normal HTTP client functions in a notebook.
``` python
server = JupyUvi(app)
```
The [`HTMX`](https://www.fastht.ml/docs/api/jupyter.html#htmx) callable
displays the server’s HTMX application in an iframe which can be
displayed by Jupyter notebook. Pass in the same `port` variable used in
the [`JupyUvi`](https://www.fastht.ml/docs/api/jupyter.html#jupyuvi)
callable above or leave it blank to use the default (8000).
``` python
# This doesn't display in the docs - uncomment and run it to see it in action
# HTMX()
```
We didn’t define the `/click` route, but that’s fine - we can define (or
change) it any time, and it’s dynamically inserted into the running app.
No need to restart or reload anything!
``` python
@rt
def click(): return P('You clicked me!')
```
## Full screen view
You can view your app outside of Jupyter by going to `localhost:PORT`,
where `PORT` is usually the default 8000, so in most cases just click
[this link](localhost:8000/).
## Graceful shutdowns
Use the `server.stop()` function displayed below. If you restart Jupyter
without calling this line the thread may not be released and the
[`HTMX`](https://www.fastht.ml/docs/api/jupyter.html#htmx) callable
above may throw errors. If that happens, a quick temporary fix is to
specify a different port number in JupyUvi and HTMX with the `port`
parameter.
Cleaner solutions to the dangling thread are to kill the dangling thread
(dependant on each operating system) or restart the computer.
``` python
server.stop()
```