Artemis
Build Android, iOS, desktop, and web apps in Python — with almost none of the boilerplate.
Artemis is a batteries-included layer on top of Flet (Flutter, for Python). Flet gives you the raw building blocks; Artemis gives you the everyday app-shell parts — theming, navigation, forms, state, dialogs, testing — as a small set of plain functions instead of something you assemble by hand in every new project.
import artemis as art
app = art.App("Hello", theme="ocean")
@app.page("/")
def home(page):
return art.Column([
art.Title("Hello, Artemis"),
art.Button("Say hi", on_click=lambda e: app.toast("Hi!")),
], center=True)
app.run()
Run that and you get a real, native-feeling window (not a webview) with a proper Material 3 color scheme, correct fonts, and modern rounded controls — from eleven lines. Build the same file for Android and it's a real Android app, because underneath, it's Flet and Flutter the whole way down. Artemis doesn't fork Flet or invent a new rendering engine — it removes repetition.
Install
pip install artemis-ui
import artemis as art
Want charts, or automatic conversion of a custom logo into a Windows icon? Those are optional extras:
pip install "artemis-ui[charts]" # for art.LineChart / BarChart / PieChart
pip install "artemis-ui[icons]" # for converting a custom logo.png into a Windows .ico
Scaffold a new project
pip install artemis-ui
artemis new "My App"
cd "My App"
pip install -e .
python main.py
artemis new sets up a working starter app, and a GitHub Actions workflow that builds your app for Android, iOS, Windows, macOS, Linux, and Web the moment you push — so producing a real install-able app on every platform never requires setting up Flutter, the Android SDK, or Xcode on your own machine. See Building & CI/CD.
What you get
Theming. 31 named color palettes, or full manual control over background/surface/text/accent colors — each one Material 3-correct in both light and dark mode automatically.
art.App("My App", theme="sunset")
art.App("My App", background="#0B1220", surface="#161F32", text="#E5E7EB", primary="#818CF8")
Navigation that behaves like a real app. A genuine back-stack (not a page swap) with automatic back arrows, working hardware/browser back buttons, route parameters, route guards, a bottom tab bar, and a side drawer.
@app.page("/user/:id", guard=lambda: logged_in.value, redirect="/login")
def profile(page, params):
return art.Text(f"User #{params['id']}")
app.go("/user/42")
app.back()
State that just works, with a persistent and an async variant when you need them.
count = art.State(0)
theme_pref = art.PersistentState("theme", default="indigo") # survives an app restart
products = art.AsyncData(lambda: art.fetch_json(url)) # loads once, not on every re-render
Forms with real validation.
email = art.Field("", art.validators.required(), art.validators.email())
form = art.Form(email=email)
art.Input(label="Email", field=email)
art.Button("Submit", on_click=form.submit(handle_submit))
Dialogs, toasts, pickers, and shortcuts — app.alert(...), app.confirm(...), app.toast(..., action="Undo"), app.pick_date(...), app.on_key("ctrl+s", ...), clipboard access, and more, each a one-line call instead of manual control wiring.
A wide widget set — Text, Button (with an automatic loading spinner), Input, Switch, Slider, Dropdown, Column/Row/Grid, Tabs, Card, ListTile, Avatar, charts, and more — every one a plain Flet control under the hood, so anything Artemis doesn't wrap is one import flet away.
Automatic branding. A default app icon on first run, replaced instantly if you drop your own logo.png in assets/ — and a dev-only splash screen for web apps that appears on localhost and disappears the moment the same code is actually deployed, with nothing to remember to turn off.
A testing toolkit. Test your app's logic — clicks, typed input, navigation, dialogs — without opening a window:
from artemis.testing import TestApp
t = TestApp(app).build()
t.click(t.find_button("+"))
assert t.has_text("1")
Documentation
The README above is the tour. The full reference — every widget, every parameter, every subsystem, with runnable examples — lives in docs/:
- Getting Started
- Core Concepts — read this one; it explains the "why" behind how screens update
- Widget Reference
- Theming & Branding
- Navigation
- Forms & Validation
- Data & Networking
- Dialogs & Feedback
- Testing
- The
artemisCLI - Troubleshooting & FAQ
- Building & CI/CD
Full index: docs/00-index.md.
The mental model, briefly
A page is a plain function that returns a control tree:
@app.page("/")
def home(page):
return art.Text("hello")
When a button is clicked, Artemis re-runs the current screen's function and redraws it — you don't call page.update() yourself. Text inputs are the one exception, so typing doesn't lose focus or cursor position; bind them to a State instead. This is the one idea worth understanding properly before diving in further — Core Concepts covers it in full.
Examples
The examples/ folder has a complete, runnable app for nearly every feature above — a counter, a todo list, a themed dashboard with live charts, a login form, drawer navigation, keyboard shortcuts, and more:
python examples/counter.py
python examples/dashboard.py
Good to know before you start
- Screens re-render on every interaction, not just the one that changed. This keeps the mental model simple (your page function is always a fresh, correct description of the screen) at a small performance cost. Fine for typical app sizes; if you're rendering thousands of rows at once, consider pagination.
- There is no file picker. Flet's underlying
FilePickercontrol has a real, unresolved upstream registration bug that made it unreliable across machines and Python versions — rather than ship something that silently works for some people and not others, Artemis doesn't wrap it. See Troubleshooting if you need file access anyway. - Charts need an extra install (
pip install artemis-ui[charts]) — kept optional so it's not forced on projects that don't need it. - Python 3.14 has some rough edges with Flet right now. Python 3.12 or 3.13 are the most stable targets. See Troubleshooting.
- Packaging for Android/iOS/desktop genuinely requires Flutter. That's how Flet works, not something Artemis can avoid — but it auto-installs itself, and the CI workflow every
artemis newproject ships with means your own machine may never need it at all. See Building & CI/CD.
License
MIT — see LICENSE.
Metadata
Release files for artemis-ui 0.97.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| artemis_ui-0.97.0.tar.gz | 93.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| artemis_ui-0.97.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 184.7 kB
Release files / artemis_ui-0.97.0.tar.gz
| Download URL | artemis_ui-0.97.0.tar.gz |
|---|---|
| Size | 93.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e7fd299d5b274c8d805d9b091774853a2d0cb8a8481f81aa23a9ce1dc216ef8a
|
|
BLAKE2b-256 checksum How to use checksums |
61a7fa2496f850a0b6523ed4f2287505bf9aef42e1019b929e07ef62a588c306
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.3
|
Release files / artemis_ui-0.97.0-py3-none-any.whl
| Download URL | artemis_ui-0.97.0-py3-none-any.whl |
|---|---|
| Size | 90.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
44e399d2e22cad4f0aa6401544271696b192d580547782b51b61e25d46d5e492
|
|
BLAKE2b-256 checksum How to use checksums |
5d2c7e6f3acf483cd37eb6ab7a0fee6129cdd7bed5f140bfa1ddc449989f5f0b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.3
|