Skip to main content

A beautiful, modern Python framework for creating web UIs

Project description

Umara

Beautiful Python UIs — Without the Complexity

PyPI version Python 3.9+ License: MIT

Getting StartedDocumentationExamplesContributing


What is Umara?

Umara is a modern Python framework for building beautiful web applications with pure Python. No HTML, CSS, or JavaScript required.

import umara as um

um.header('Hello, Umara!')

with um.form('greeting'):
    name = um.input('Your name')
    if um.form_submit_button('Greet'):
        um.success(f'Welcome, {name}!')

Why Umara?

  • Beautiful by Default — Components look polished out of the box with modern design
  • Fast & Reactive — WebSocket-based architecture for instant UI updates
  • 12 Built-in Themes — Professional themes including dark mode, ocean, forest, and more
  • Flexible Layouts — Columns, grids, cards, tabs, sidebars with precise control
  • Hot Reload — See changes instantly during development
  • Smart State — Efficient updates without full page re-runs

Getting Started

1. Install Umara

pip install umara

2. Create Your App

Create a file called app.py:

import umara as um

um.set_theme('ocean')

um.header('My First App')
um.text('Building beautiful UIs is easy!')

with um.card():
    with um.form('hello_form'):
        name = um.input('Enter your name', placeholder='John Doe')

        if um.form_submit_button('Say Hello'):
            um.success(f'Hello, {name}!')

3. Run Your App

umara run app.py

4. Open in Browser

Navigate to http://localhost:8501 in your browser.

That's it! Your app is running with hot reload enabled — any changes to app.py will automatically refresh in the browser.


Core Concepts

Components

Umara provides 120+ components for building UIs:

# Typography
um.title('Page Title')
um.header('Section Header')
um.text('Regular text')

# Inputs
name = um.input('Name', placeholder='Enter name...')
age = um.slider('Age', 0, 100, 25)
color = um.select('Color', ['Red', 'Green', 'Blue'])
agreed = um.checkbox('I agree')

# Feedback
um.success('Operation completed!')
um.error('Something went wrong')
um.warning('Please check your input')
um.info('Helpful tip here')

# Data Display
um.metric('Users', '12,543', delta=12.5)
um.progress(75, label='Completion')
um.dataframe(data)  # Works with pandas DataFrames

Layouts

Organize content with flexible layout components:

# Columns
with um.columns(3):
    with um.column():
        um.metric('Users', '1,234')
    with um.column():
        um.metric('Revenue', '$5,678')
    with um.column():
        um.metric('Growth', '12.5%')

# Cards
with um.card(title='Dashboard'):
    um.text('Card content here')

# Tabs
with um.tabs(['Overview', 'Data', 'Settings']):
    with um.tab('Overview'):
        um.text('Overview content')
    with um.tab('Data'):
        um.dataframe(data)
    with um.tab('Settings'):
        um.toggle('Enable feature', key='feature_toggle')

# Grid
with um.grid(columns=4, gap='16px'):
    for i in range(8):
        with um.card():
            um.text(f'Item {i + 1}')

Themes

Switch between 12 professional themes:

um.set_theme('light')     # Clean, minimal
um.set_theme('dark')      # Modern dark mode
um.set_theme('ocean')     # Calming blues
um.set_theme('forest')    # Earthy greens
um.set_theme('slate')     # Corporate gray
um.set_theme('nord')      # Arctic, Scandinavian
um.set_theme('midnight')  # Deep purple dark
um.set_theme('rose')      # Warm pink
um.set_theme('copper')    # Premium bronze
um.set_theme('lavender')  # Soft purple
um.set_theme('sunset')    # Warm orange
um.set_theme('mint')      # Fresh teal

Themes persist in localStorage and respect system dark/light mode preferences.

State Management

Use session_state to persist data across interactions:

# Initialize state
um.session_state.setdefault('counter', 0)

# Display current value
um.text(f'Count: {um.session_state.counter}')

# Update state
if um.button('Increment'):
    um.session_state.counter += 1

Keys and Forms

Standalone inputs require a key parameter to persist values across reruns:

# Without key - value resets on every rerun (not recommended)
name = um.input('Name')

# With key - value persists across reruns (recommended)
name = um.input('Name', key='user_name')

Use forms for input + button patterns to ensure values are captured reliably:

# RECOMMENDED: Form batches inputs and submits together
with um.form('contact'):
    name = um.input('Name', key='name')
    email = um.input('Email', key='email')

    if um.form_submit_button('Submit'):
        # All values guaranteed to be current
        um.success(f'Submitted: {name}, {email}')

Why forms for input + button? Standalone inputs have a 50ms debounce. If users click a button immediately after typing, the input value may not be synced yet. Forms batch all values and submit them together, avoiding this race condition.

When to use which:

Scenario Use
Input + button action um.form() (recommended)
Real-time filtering (on every keystroke) Standalone with key
Toggle/checkbox immediate effect Standalone with key
Multi-field data entry um.form()

Documentation

Full API Reference

See docs/UMARA_COMPLETE_REFERENCE.md for complete documentation including:

  • All 120+ components with parameters and examples
  • State management and caching
  • Theming and custom styles
  • Database and API connections
  • Fragments for partial reruns
  • Best practices

Quick Reference

Input Components

Component Description Returns
um.input(label, key=...) Text input field str
um.text_area(label, key=...) Multi-line text str
um.number_input(label, key=...) Numeric input float
um.slider(label, min, max, value, key=...) Range slider float
um.select(label, options, key=...) Dropdown select str
um.multiselect(label, options, key=...) Multi-select list[str]
um.checkbox(label, key=...) Checkbox bool
um.toggle(label, key=...) Toggle switch bool
um.radio(label, options, key=...) Radio buttons str
um.date_input(label, key=...) Date picker str
um.time_input(label, key=...) Time picker str
um.color_picker(label, key=...) Color picker str
um.file_uploader(label, key=...) File upload file | None
um.button(label, key=...) Click button bool

Important: Use key parameter for inputs outside forms to persist values across reruns.

Display Components

Component Description
um.title(text) Large page title
um.header(text) Section header
um.subheader(text) Subsection header
um.text(text) Regular text
um.markdown(text) Markdown content
um.code(code, language) Syntax-highlighted code
um.metric(label, value, delta) Metric with trend
um.progress(value, label) Progress bar
um.dataframe(data) Data table (sortable)
um.json_viewer(data) JSON tree view

Feedback Components

Component Description
um.success(message) Green success alert
um.error(message) Red error alert
um.warning(message) Yellow warning alert
um.info(message) Blue info alert
um.toast(message) Temporary notification
um.spinner(text) Loading spinner

Layout Components

Component Description
um.columns(count) Multi-column layout
um.grid(columns) CSS grid layout
um.card(title) Card container
um.tabs(names) Tabbed interface
um.expander(title) Collapsible section
um.sidebar() Side navigation
um.modal(title, key) Modal dialog
um.form(key) Form container

Charts

Component Description
um.line_chart(data, x, y) Line chart
um.bar_chart(data, x, y) Bar chart
um.area_chart(data, x, y) Area chart
um.pie_chart(data, label, value) Pie chart
um.scatter_chart(data, x, y) Scatter plot
um.plotly_chart(figure) Plotly figure

Examples

Dashboard

import umara as um

um.set_theme('dark')
um.header('Analytics Dashboard')

# Metrics row
with um.columns(4):
    for label, value, delta in [
        ('Users', '12,543', 12.5),
        ('Revenue', '$48.2K', 8.2),
        ('Sessions', '1,892', -2.4),
        ('Conversion', '3.24%', 0.5),
    ]:
        with um.column():
            with um.card():
                um.metric(label, value, delta=delta)

# Chart
um.subheader('Revenue Trend')
um.line_chart(data, x='month', y='revenue')

# Data table
um.subheader('Recent Orders')
um.dataframe(orders, sortable=True)

Form

import umara as um

um.header('Contact Form')

with um.card():
    with um.form('contact'):
        name = um.input('Name', key='name')
        email = um.input('Email', type='email', key='email')
        message = um.text_area('Message', key='message')

        if um.form_submit_button('Send'):
            if name and email and message:
                um.success('Message sent!')
            else:
                um.error('Please fill all fields')

Chat Interface

import umara as um

um.set_theme('dark')
um.header('AI Chat')

# Initialize messages
um.session_state.setdefault('messages', [])

# Display chat
with um.chat_container(height='400px'):
    for msg in um.session_state.messages:
        um.chat_message(msg['content'], role=msg['role'])

# Input
user_input = um.chat_input('Type a message...')

if user_input:
    um.session_state.messages.append({'role': 'user', 'content': user_input})
    # Add your AI response logic here
    response = "This is a response"
    um.session_state.messages.append({'role': 'assistant', 'content': response})

File Upload with Size Limit

import umara as um

# Max 5MB file size
uploaded = um.file_uploader(
    'Upload Document',
    accept=['.pdf', '.docx'],
    max_file_size=5 * 1024 * 1024  # 5MB in bytes
)

if uploaded:
    um.success(f'Uploaded: {uploaded["name"]}')

CLI Commands

# Run an app
umara run app.py

# Run with custom host/port
umara run app.py --host 0.0.0.0 --port 8080

# Create new project
umara init my_project

# List available themes
umara themes

Project Structure

umara/
├── umara/                 # Python package
│   ├── core.py           # App lifecycle & component tree
│   ├── components.py     # 100+ UI components
│   ├── server.py         # WebSocket server
│   ├── frontend.py       # Frontend HTML/CSS/JS
│   ├── state.py          # State management
│   ├── themes.py         # 12 built-in themes
│   └── cli.py            # CLI commands
├── examples/             # Example applications
└── docs/                 # Documentation

Contributing

Contributions are welcome! Here's how to set up for development:

# Clone the repository
git clone https://github.com/lhassa8/umara.git
cd umara

# Create virtual environment
python -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate

# Install in development mode
pip install -e ".[dev]"

# Run tests
pytest

# Run the demo app
umara run examples/demo_app.py
# Open http://localhost:8501 in your browser

Roadmap

  • 100+ UI components
  • 12 built-in themes
  • Charts & data visualization
  • Chat/conversation components
  • Forms with batched submission
  • File uploads with size limits
  • Sortable data tables
  • ARIA accessibility labels
  • System theme detection
  • Theme persistence (localStorage)
  • Authentication helpers
  • Multi-page app support
  • Component marketplace
  • VS Code extension

Known Issues

The following issues are currently being tracked:

Issue Status Workaround
file_uploader() UI not visible Open File upload functionality is limited; upload UI may not render
Modal/dialog in complex layouts Open Avoid nesting modals inside deeply nested column layouts

License

MIT License — see LICENSE for details.


Built with Python

GitHubPyPI

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

umara-0.5.0.tar.gz (88.0 kB view details)

Uploaded Source

Built Distribution

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

umara-0.5.0-py3-none-any.whl (92.7 kB view details)

Uploaded Python 3

File details

Details for the file umara-0.5.0.tar.gz.

File metadata

  • Download URL: umara-0.5.0.tar.gz
  • Upload date:
  • Size: 88.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.5

File hashes

Hashes for umara-0.5.0.tar.gz
Algorithm Hash digest
SHA256 c79e68c276dc8df1a98a18ff5dee8e327d7440e77ee3f33d32a36f01ca103920
MD5 543b4c1f7704c5e11820b82a5230e491
BLAKE2b-256 08bfe868710626e6c88c45e0b1459e3ac6eab5012a115b0959879abebe2691d8

See more details on using hashes here.

File details

Details for the file umara-0.5.0-py3-none-any.whl.

File metadata

  • Download URL: umara-0.5.0-py3-none-any.whl
  • Upload date:
  • Size: 92.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.5

File hashes

Hashes for umara-0.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 2bb8a25b3a26d10ca36122794089ab75a02fe8ac854101d395234709ebb422e4
MD5 f1c2dcfcc224efb5c499cbbabbef0284
BLAKE2b-256 6cd82b6334b30b78034851fd9ea524ea6c2aca54119ac977dda096fd0e5ada06

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