Getting started

Installation

Go here and copy the code in a file named rd.py.

That's it!

Your first app

Then create another file named main.py. This is where we'll create our application.

We'll go step by step

Give me the full code
import rd

@rd.get("/")
async def hello(request):
    return rd.html("""
<!doctype html>
<html lang="en">
    <head>
    <meta charset="utf-8">
    <title>Hello</title>
    <script type="module" src="https://cdn.jsdelivr.net/gh/starfederation/datastar@v1.0.4/bundles/datastar.js"></script>
    </head>
    <body>
    <main>
        <h1>Hello, world!</h1>
        <p id="message">Welcome to Red Dwarf.</p>
        <button data-on:click="@get('/message')">Simple Update</button>
        <button data-on:click="@get('/clock')">Streamed Update</button>
    </main>
    </body>
</html>
""")


@rd.get("/message")
async def message(request):
    return rd.patch("""
<p id="message">
  This text was updated by the server.
</p>
""")


@rd.get("/clock")
async def clock(request):
    while True:
        yield rd.patch(f"""
<p id="message">
  The time is {asyncio.get_running_loop().time():.0f}.
</p>
""")
        await asyncio.sleep(1)


if __name__ == "__main__":
    rd.run(reload=True)
    

Let's start with a welcome page.

import rd

@rd.get("/")
async def hello(request):
    return rd.html("""
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Hello</title>
    <script type="module" src="https://cdn.jsdelivr.net/gh/starfederation/datastar@v1.0.4/bundles/datastar.js"></script>
  </head>
  <body>
    <main>
      <h1>Hello, world!</h1>
      <p id="message">Welcome to Red Dwarf.</p>
      <button data-on:click="@get('/message')">Simple Update</button>
      <button data-on:click="@get('/clock')">Streamed Update</button>
    </main>
  </body>
</html>
""")

if __name__ == "__main__":
    rd.run(reload=True)

Then, simply run python main.py.

Open http://127.0.0.1:8080/ and you should see your first page.

Update an element

Returning a patch lets you replace part of the page without sending the whole document again.

Let's add a route to do that under our "hello" route.


@rd.get("/message")
async def message(request):
    return rd.patch("""
<p id="message">
  This text was updated by the server.
</p>
""")

Because we ran Red Dwarf with reload=True, the server restarts automatically when you save the file.

Reload your page and click on the "Simple Update" button. Magic!

Only the element with id="message" changes. Everything else stays exactly where it is.

Remember, the request has to be triggered by a Datastar action!

Streamed updates

If a route returns a Python generator, Red Dwarf keeps the connection open and sends each patch as it is produced.

import asyncio

@rd.get("/clock")
async def clock(request):
    while True:
        yield rd.patch(f"""
<p id="message">
  The time is {asyncio.get_running_loop().time():.0f}.
</p>
""")
        await asyncio.sleep(1)

Conclusion

That's all there is to it.

Your application starts with plain HTML, and whenever something changes, you send a small HTML fragment describing the new state.

Or a big one! You can morph the whole HTML if you want. We call this fat morph and view = f(state).

We encourage you to read the Docs, they're short and contain everything that Red Dwarf can do.

Now go build!