Skip to main content

Lofi GUI tooling

Project description

lofigui

Latest: v0.17.20

Lofi GUI - A minimalist library for creating really simple web-based GUIs for CLI tools and small projects. Available in both Python and Go, it provides a print-like interface for building lightweight web UIs with minimal complexity.

The aplication is where you have a single real object (eg machine or long running) processing which then have a number of pages around it to show various aspects of it.

Python Version Go Version License: MIT

🚀 Now Available in Go!

Check out the Go version for:

  • 10-100x faster performance
  • Single binary deployment
  • WebAssembly support (~2MB vs ~10MB for Python)
  • Type safety at compile time

Choose the version that fits your needs - same simple API, different strengths!

Overview

lofigui provides a print-like interface for building lightweight web applications with minimal complexity. Perfect for:

  • Creating quick GUIs for command-line tools
  • Internal tools for small teams (1-10 users)
  • Single-process or single-object front-ends
  • Rapid prototyping without JavaScript overhead

Key Features

  • Simple API: Print-like interface (print(), markdown(), html(), table())
  • No JavaScript: Pure HTML/CSS using the Bulma framework to make it look prettier as I am terrible at design.
  • MVC Architecture: Model, view, and controller architecture
  • Async-ready: Built on asyncio for modern web frameworks (FastAPI, etc.)
  • Type-safe: Full type hints and mypy support
  • Secure: HTML escaping by default to prevent XSS attacks

Element

Your project is essentially a web site. To make design simple you completely refresh pages so no code for partial refreshes. To make things dynamic it has to be asynchonous so for python using fastapi as a server and Uvicorn to provide the https server.

Like a normal terminal program you essentially just print things to a screen but now have the ability to print enriched objects.

model view controller architecture

All I really want to do is to write the model. The controller and view (in the browser and templating system) are a necessary evil. The controller includes the routing and webserver. The controller is split between the app (single instance) and a model specific controller. The view is the html templating and the browser.

Buffer

In order to be able to decouple the display from the output and to be able to refesh you need to be able to buffer the output. It is more efficient to buffer the output in the browser but more complicated. Moving the buffer to the server simplifies the software but requires you to refresh the whole page. lofigui relies on hyperlinks to perform updates. Forms are useful for nice buttons but in general to get the right level of interactivity (click on somthing and it changes) you don't want to have forms. HTMLx would play nicely here if you were intersted in improving interactivity and spending a bit more time on the UI.

Installation

Using pip

pip install lofigui

Using uv

uv add lofigui

From source

git clone https://github.com/drummonds/lofigui.git
cd lofigui
uv sync --all-extras

Quick Start

Look at the example for a quick start.

API Reference

Output Functions

print(msg, ctx=None, end="\n", escape=True)

Print text to the buffer as HTML paragraphs.

Parameters:

  • msg (str): Message to print
  • ctx (PrintContext, optional): Custom context (default: global context)
  • end (str): End character - "\n" for paragraphs, "" for inline
  • escape (bool): Escape HTML entities (default: True)

Example:

import lofigui as lg

lg.print("Hello world")  # <p>Hello world</p>
lg.print("Inline", end="")  # &nbsp;Inline&nbsp;
lg.print("<script>alert('safe')</script>")  # Escaped by default
lg.print("<b>Bold</b>", escape=False)  # Raw HTML (use with caution!)

markdown(msg, ctx=None)

Convert markdown to HTML and add to buffer.

Parameters:

  • msg (str): Markdown-formatted text
  • ctx (PrintContext, optional): Custom context

Example:

lg.markdown("# Heading\n\nThis is **bold** text")

html(msg, ctx=None)

Add raw HTML to buffer (no escaping).

WARNING: Only use with trusted input to avoid XSS vulnerabilities.

Parameters:

  • msg (str): Raw HTML
  • ctx (PrintContext, optional): Custom context

Example:

lg.html("<div class='notification is-info'>Custom HTML</div>")

table(table, header=None, ctx=None, escape=True)

Generate an HTML table with Bulma styling.

Parameters:

  • table (Sequence[Sequence]): Table data as nested sequences
  • header (List[str], optional): Column headers
  • ctx (PrintContext, optional): Custom context
  • escape (bool): Escape cell content (default: True)

Example:

data = [
    ["Alice", 30, "Engineer"],
    ["Bob", 25, "Designer"],
]
lg.table(data, header=["Name", "Age", "Role"])

Buffer Management

buffer(ctx=None)

Get accumulated HTML output.

Returns: str

Example:

content = lg.buffer()

reset(ctx=None)

Clear the buffer.

Example:

lg.reset()

Context Management

PrintContext(max_buffer_size=None)

Context manager for buffering HTML output.

Parameters:

  • max_buffer_size (int, optional): Warn if buffer exceeds this size

Example:

from lofigui import PrintContext, print

# Using context manager (auto-cleanup)
with PrintContext() as ctx:
    print("Hello", ctx=ctx)
    # Buffer automatically reset on exit

# Or create manually
ctx = PrintContext(max_buffer_size=10000)

Favicon Support

get_favicon_response()

Get a FastAPI/Starlette Response object for serving the favicon.

Example:

@app.get("/favicon.ico")
async def favicon():
    return lg.get_favicon_response()

get_favicon_html_tag()

Get an HTML link tag with embedded favicon data URI.

Example:

# In your template <head>
{{ get_favicon_html_tag()|safe }}

save_favicon_ico(path)

Save the favicon to a file.

Example:

lg.save_favicon_ico("static/favicon.ico")

Architecture

MVC Pattern

lofigui follows the Model-View-Controller pattern:

  • Model: Your business logic (functions that call lg.print(), etc.)
  • View: Jinja2 templates that render the buffered HTML
  • Controller: FastAPI/Flask routes that orchestrate model and view

Buffering Strategy

Server-side buffering simplifies the architecture:

  1. Model functions write to a queue
  2. buffer() drains the queue and returns HTML
  3. Templates render the complete HTML
  4. Full page refresh (no partial DOM updates)

This approach trades interactivity for simplicity - perfect for internal tools.

Security

By default, all output functions escape HTML to prevent XSS attacks:

lg.print("<script>alert('xss')</script>")
# Output: <p>&lt;script&gt;alert('xss')&lt;/script&gt;</p>

Use escape=False or html() only with trusted input.

Examples & Documentation

See the documentation site for interactive examples (including WASM demos), research notes, and the roadmap.

To run examples locally, use Task:

task --list              # Show all available tasks
task go-example:09       # Run any Go example by number
task example-01          # Run any Python example by number

Development

Setup

git clone https://github.com/drummonds/lofigui.git
cd lofigui
uv sync --all-extras

Running Tests

uv run pytest

With coverage:

uv run pytest --cov=lofigui --cov-report=html

Type Checking

uv run mypy lofigui

Code Formatting

uv run black lofigui tests

Comparison with Alternatives

Feature lofigui Streamlit PyWebIO Textual
JavaScript No Yes Yes No
Complexity Very Low Medium Medium Medium
Use Case Internal tools Data apps Web apps Terminal UIs
Learning Curve Minimal Moderate Moderate Moderate
Partial Updates Via HTMX Yes Yes Yes

Choose lofigui if:

  • You want maximum simplicity
  • You're building internal tools
  • You don't need fancy interactivity
  • You want to understand every line of code

Choose alternatives if:

  • You need rich interactivity
  • You're building public-facing apps
  • You want widgets and components

Roadmap

See ROADMAP.md for planned features and future direction.

Contributing

Contributions are welcome! Please see CONTRIBUTING.md for guidelines.

License

MIT License - see LICENSE file for details.

Author

Humphrey Drummond - hum3@drummond.info

Links

Documentation https://h3-lofigui.statichost.page/
PyPI https://pypi.org/project/lofigui/
Source (Codeberg) https://codeberg.org/hum3/lofigui
Mirror (GitHub) https://github.com/drummonds/lofigui

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

lofigui-0.17.20.tar.gz (22.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

lofigui-0.17.20-py3-none-any.whl (17.5 kB view details)

Uploaded Python 3

File details

Details for the file lofigui-0.17.20.tar.gz.

File metadata

  • Download URL: lofigui-0.17.20.tar.gz
  • Upload date:
  • Size: 22.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.9 {"installer":{"name":"uv","version":"0.10.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for lofigui-0.17.20.tar.gz
Algorithm Hash digest
SHA256 2f455dd36fca07ebd866a47d5a45c7094a23d80609351dd5794fd8211bf33d72
MD5 a2acf2d45828f7532a3aa569b57df674
BLAKE2b-256 9d4e611720c9e6a49996c62776e6fdafdfc6dbd2da392a2e1467731976f81f4f

See more details on using hashes here.

File details

Details for the file lofigui-0.17.20-py3-none-any.whl.

File metadata

  • Download URL: lofigui-0.17.20-py3-none-any.whl
  • Upload date:
  • Size: 17.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.9 {"installer":{"name":"uv","version":"0.10.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for lofigui-0.17.20-py3-none-any.whl
Algorithm Hash digest
SHA256 720c964af4d7584a4aab3202c33e18bc7a4824bbd8432861486c69e5bfc46ce7
MD5 d2011f6224d0aaf41227581c3ab5f040
BLAKE2b-256 60967920fe36828f6e171cd8a8b715d13b646fe265b022c4b3a7011656f5c6da

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page