diff --git a/README.md b/README.md
index d4647e0..61ecc37 100644
--- a/README.md
+++ b/README.md
@@ -1,11 +1,33 @@
# @justbe/webview
-A light, cross-platform library for building web-based desktop apps with [Deno](https://deno.com/).
+A light, cross-platform library for building web-based desktop apps. The project consists of a Rust backend that provides the core webview functionality, with multiple client libraries available for different languages and runtimes.
-> [!NOTE]
-> This is alpha level software that's rapidly changing. Things might break. Please let me know if you notice anything missing or not working.
+## Available Clients
-## Example
+- [Deno Client](src/clients/deno/README.md) - Build desktop apps using Deno and TypeScript
+- [Python Client](src/clients/python/README.md) - Build desktop apps using Python
+
+## Architecture
+
+This project is structured into two main components:
+
+1. A Rust backend that provides the core webview functionality, compiled into a native binary for each platform
+2. Client libraries that interface with the binary, available for multiple languages
+
+Each client library handles binary management, communication with the webview process over stdio (standard input/output), and provides a idiomatic API for its respective language/runtime.
+
+## Binary Management
+
+When using any of the clients, they will check for the required binary for interfacing with the OS's webview. If it doesn't exist, it downloads it to a cache directory and executes it. The specific behavior and permissions required may vary by client - please see the respective client's documentation for details.
+
+### Using a Custom Binary
+
+All clients support using a custom binary via the `WEBVIEW_BIN` environment variable. If present and allowed, this will override the default binary resolution process in favor of the path specified.
+
+## Examples
+
+
+Deno Example
```typescript
import { createWebView } from "jsr:@justbe/webview";
@@ -24,50 +46,37 @@ webview.on("started", async () => {
await webview.waitUntilClosed();
```
-You can run this yourself with
+
-```sh
-deno run https://raw.githubusercontent.com/zephraph/webview/refs/heads/main/examples/simple.ts
-```
-
-Checkout the [examples directory](https://github.com/zephraph/webview/tree/main/examples) for more.
-
-## Permissions
-
-When executing this package, it checks to see if you have the required binary for interfacing with the OS's webview. If it doesn't exist, it downloads it to a cache directory and executes it. This yields a few different permission code paths to be aware of.
-
-### Binary not in cache
+
+Python Example
-This will be true of a first run of the package. These are the following permission requests you can expect to see:
+```python
+import asyncio
+from justbe_webview import WebView, WebViewOptions, WebViewContentHtml, WebViewNotification
-- Read HOME env -- Used to locate the cache directory
-- Read /webview/webview- -- Tries to read the binary from cache
-- net to github.com:443 -- Connects to GitHub releases to try to download the binary (will be redirected)
-- net to objects.githubusercontent.com:443 -- GitHub's CDN for the actual download
-- Read /webview/ -- Reads the cache directory
-- Write /webview/webview- -- Writes the binary
-- Run /webview/webview- -- Runs the binary
+async def main():
+ config = WebViewOptions(
+ title="Example",
+ load=WebViewContentHtml(html="Hello, World!
"),
+ devtools=True
+ )
-### Binary cached
+ async with WebView(config) as webview:
+ async def handle_start(event: WebViewNotification):
+ await webview.open_devtools()
+ await webview.eval("console.log('This is printed from eval!')")
-On subsequent runs you can expect fewer permission requests:
+ webview.on("started", handle_start)
-- Read HOME env -- Use to locate the cache directory
-- Read /deno-webview/deno-webview-
-- Run /deno-webview/deno-webview-
-
-### Allowed `WEBVIEW_BIN`
-
-`WEBVIEW_BIN` is a special environment variable that, if present and allowed, will short circuit
-the binary resolution process in favor of the path specified. In this case there will be only one permission:
-
-- Run
+if __name__ == "__main__":
+ asyncio.run(main())
+```
-Note that this environment variable will never be _explicitly_ requested. If the script detects it's not allowed to read this env var it just skips this code path altogether.
+
## Contributing
-This project uses [mise](https://mise.jdx.dev/) to manage runtimes (like deno, rust) and run scripts. If you'd like
-to contribute, you'll need to install it.
+This project uses [mise](https://mise.jdx.dev/) to manage runtimes (like deno, python, rust) and run scripts. If you'd like to contribute, you'll need to install it.
Use the `mise tasks` command to see what you can do.
\ No newline at end of file
diff --git a/src/clients/deno/README.md b/src/clients/deno/README.md
new file mode 100644
index 0000000..12ef734
--- /dev/null
+++ b/src/clients/deno/README.md
@@ -0,0 +1,79 @@
+# @justbe/webview Deno Client
+
+A light, cross-platform library for building web-based desktop apps with
+[Deno](https://deno.com/).
+
+## Installation
+
+```typescript
+import { createWebView } from "jsr:@justbe/webview";
+```
+
+## Example
+
+```typescript
+import { createWebView } from "jsr:@justbe/webview";
+
+using webview = await createWebView({
+ title: "Example",
+ html: "
Hello, World!
",
+ devtools: true,
+});
+
+webview.on("started", async () => {
+ await webview.openDevTools();
+ await webview.eval("console.log('This is printed from eval!')");
+});
+
+await webview.waitUntilClosed();
+```
+
+You can run this yourself with:
+
+```sh
+deno run https://raw.githubusercontent.com/zephraph/webview/refs/heads/main/examples/simple.ts
+```
+
+Check out the [examples directory](examples/) for more examples.
+
+## Permissions
+
+When executing this package, it checks to see if you have the required binary
+for interfacing with the OS's webview. If it doesn't exist, it downloads it to a
+cache directory and executes it. This yields a few different permission code
+paths to be aware of.
+
+### Binary not in cache
+
+This will be true of a first run of the package. These are the following
+permission requests you can expect to see:
+
+- Read HOME env -- Used to locate the cache directory
+- Read /webview/webview- -- Tries to read the binary from cache
+- net to github.com:443 -- Connects to GitHub releases to try to download the
+ binary (will be redirected)
+- net to objects.githubusercontent.com:443 -- GitHub's CDN for the actual
+ download
+- Read /webview/ -- Reads the cache directory
+- Write /webview/webview- -- Writes the binary
+- Run /webview/webview- -- Runs the binary
+
+### Binary cached
+
+On subsequent runs you can expect fewer permission requests:
+
+- Read HOME env -- Use to locate the cache directory
+- Read /deno-webview/deno-webview-
+- Run /deno-webview/deno-webview-
+
+### Using a Custom Binary
+
+You can specify a custom binary path using the `WEBVIEW_BIN` environment
+variable. When set and allowed, this will bypass the default binary resolution
+process. In this case, only one permission is needed:
+
+- Run
+
+Note that this environment variable will never be _explicitly_ requested. If the
+script detects it's not allowed to read this env var it just skips this code
+path altogether.
diff --git a/src/clients/python/README.md b/src/clients/python/README.md
index e69de29..2e61985 100644
--- a/src/clients/python/README.md
+++ b/src/clients/python/README.md
@@ -0,0 +1,71 @@
+# justbe-webview
+
+A light, cross-platform library for building web-based desktop apps with Python.
+
+## Installation
+
+You can install justbe-webview using either `uv` (recommended) or `pip`:
+
+```bash
+# Using uv (recommended)
+uv pip install justbe-webview
+
+# Using pip
+pip install justbe-webview
+```
+
+## Example
+
+```python
+import asyncio
+from justbe_webview import (
+ WebView,
+ WebViewOptions,
+ WebViewContentHtml,
+ WebViewNotification,
+)
+
+async def main():
+ config = WebViewOptions(
+ title="Simple",
+ load=WebViewContentHtml(html="Hello, World!
"),
+ )
+
+ async with WebView(config) as webview:
+ async def handle_start(event: WebViewNotification):
+ await webview.eval("console.log('This is printed from eval!')")
+
+ webview.on("started", handle_start)
+
+if __name__ == "__main__":
+ asyncio.run(main())
+```
+
+You can find more examples in the [examples directory](examples/), including:
+- Loading URLs
+- Loading HTML content
+- Window size management
+- IPC (Inter-Process Communication)
+
+### Binary Management
+
+On first run, the client will:
+1. Check for a cached binary in the user's cache directory
+2. If not found, download the appropriate binary for the current platform
+3. Cache the binary for future use
+
+The exact cache location depends on your operating system:
+- Linux: `~/.cache/justbe-webview/`
+- macOS: `~/Library/Caches/justbe-webview/`
+- Windows: `%LOCALAPPDATA%\justbe-webview\Cache\`
+
+### Using a Custom Binary
+
+You can specify a custom binary path using the `WEBVIEW_BIN` environment variable:
+
+```bash
+export WEBVIEW_BIN=/path/to/webview/binary
+python your_app.py
+```
+
+When set, this will bypass the default binary resolution process.