Skip to content
wesktop
Edit
On this page

#wesktop

wesktop is a Python framework for building web-based desktop applications. It combines fastware (an ASGI micro-framework with routing, SSE, middleware, auth, and server lifecycle) with pywebview (native OS windows) to let you write Python backends that open as desktop apps -- or run headless as web servers.

#Built on fastware

wesktop re-exports the entire fastware API so consumers can import wesktop and get routing, responses, SSE, middleware, auth, dependency injection, config loading, background tasks, feature flags, audit logging, and test clients -- all without importing fastware directly. The fastware layer handles everything HTTP/ASGI; wesktop adds the desktop shell on top:

  • Desktop window -- start a granian server in a background thread, open a native OS window via pywebview, block until the user closes it
  • Desktop entries -- create and remove platform-native application shortcuts (Linux .desktop files, macOS .app bundles, Windows Start Menu shortcuts)
  • SDUI primitives -- 40 server-driven UI node types (layout, display, data, input, feedback, overlay) for building dynamic dashboards without shipping frontend code
  • Dev mode -- Vite integration for frontend hot-reload during development
  • GUI backend detection -- automatic discovery of system PyGObject/Qt in isolated venvs

For ASGI routing, middleware, auth, SSE, and server lifecycle documentation, see the fastware docs.

#Installation

$_ bash
pip install wesktop

#Minimal Desktop App

python
import wesktop

router = wesktop.Router()

@router.get("/api/health")
async def health(req: wesktop.Request):
    return {"status": "ok"}

app = wesktop.create_app(router)

# Opens a native desktop window pointing at the server
wesktop.run("myapp:app", title="My App", width=1024, height=768)

wesktop.run() starts granian in a background thread and opens a pywebview window. When the window closes, the server keeps running independently. The server binds to a random available port by default in desktop mode, so multiple instances do not collide.

#Headless Server

If you don't need a desktop window -- for example during development, in CI, or for server-only deployment -- use serve() instead of run(). The serve() function starts the Granian ASGI server with optional PID file management, port availability checks, and signal handling, but without opening any native OS windows:

python
import wesktop

router = wesktop.Router()

@router.get("/api/ping")
async def ping(req: wesktop.Request):
    return wesktop.TextResponse("pong")

app = wesktop.create_app(router)

# Blocks the process, serving on 127.0.0.1:8000
wesktop.serve("myapp:app", foreground=True, host="127.0.0.1", port=8000)

#Development Mode

For frontend development with Vite hot-reload, wesktop provides a dev() function that starts both the Vite dev server (as a subprocess) and the Granian ASGI backend in a single command, with automatic proxy routing and cleanup:

python
import wesktop

router = wesktop.Router()

@router.get("/api/data")
async def data(req: wesktop.Request):
    return {"items": [1, 2, 3]}

app = wesktop.create_app(router)

# Starts Vite dev server + granian backend
wesktop.dev("myapp:app", vite_port=5173)

#SSE (Server-Sent Events)

wesktop includes a Broadcaster class (from fastware) that manages SSE client connections with typed events. Event types must be registered before broadcast (strict mode), and disconnected clients are pruned automatically.

python
import wesktop

router = wesktop.Router()
sse = wesktop.Broadcaster()

# Register allowed event types
sse.register_event("status")
sse.register_event("progress")

# Wire the SSE stream to a route
router.add_route("GET", "/events", wesktop.sse_route(sse))

@router.get("/api/notify")
async def notify(req: wesktop.Request):
    sse.broadcast("status", {"message": "build complete"})
    return {"sent": True}

app = wesktop.create_app(router)

#Desktop Entries

Create platform-native application shortcuts so users can launch your app from their OS launcher. Supports Linux .desktop files, macOS .app bundles, and Windows Start Menu shortcuts via COM or PowerShell:

python
import wesktop

# Create a desktop shortcut
path = wesktop.create_entry(
    name="My App",
    command="/path/to/myapp-open",
    icon="/path/to/icon.png",
    comment="My wesktop application",
)

# Remove it later
wesktop.remove_entry("My App")

When using wesktop.run(), desktop entries are created automatically on first launch and self-heal if the launcher script goes missing (e.g., after reinstalling to a different venv).

#API Reference

See the API docs for all 116 wesktop-native symbols (desktop window, entries, SDUI primitives, GUI backend detection, and dev mode). For ASGI routing, middleware, auth, SSE, dependency injection, and server lifecycle, see the fastware API docs.

More tools from this site

  • claudestream Drive Claude Code from Python: run it as a subprocess and read its output as typed events, with async and sync sessions, sandbox policies, and tools you define in Python
  • claudewheel A TUI Claude Code Launcher that lets you have more than one profile, manage sessions lifecycle, pick the exact CC version, model to use (even older unlisted ones), pick which GitHub account to use, etc.
  • dirstat Fast, single-binary directory statistics CLI: every file under a tree grouped by format, with counts, sizes, and lines of code, as a colored terminal table or as JSON
  • fastware A batteries-included ASGI framework: msgspec JSON, a managed Granian server, dependency injection, SSE, WebSockets, auth, and a test client
  • go-toml-edit Zero-dep TOML editing library for Go with comment preservation
  • howmuchleft The fastest Claude Code statusline: context window, 5-hour, and weekly limit usage as three customizable gradient bars, rendering in about 6 ms
  • orxtra
  • pgdesign
  • predraw Declarative rendering pipeline: describe a scene in JSON and get SVG, PNG and WebP out, with light and dark style tokens, reusable components and text converted to path outlines
  • reposummary Turn a git repository's history into a Markdown journal: pick a time window or revision range and get a readable digest of what changed, optionally narrated by an LLM
  • rlsbl Release orchestration and project scaffolding CLI that bumps versions, validates a structured JSONL changelog, tags only the commit CI verified, and publishes to npm, PyPI, Go and more
  • safegit git wrapper CLI that gives each commit its own temporary index and retries ref updates on conflict, so concurrent agents share one repository
  • saferm Command-line replacement for rm that archives every deletion with a mandatory reason and the context it ran in, so deleted files can be listed, inspected and restored
  • selfdoc Static Site Generator that builds a project's documentation site directly from its source code, so the docs can never drift from the code they describe, with SEO/AEO, first-class blog, search, and cross-project linking built in
  • strictcli
  • stricttest An always-on test-isolation floor: a pytest plugin and a Go env-hygiene module that make a test suite structurally unable to reach real credentials, the real HOME, the network, or the development repository.
Search