{"id":15520581,"url":"https://github.com/percevalw/pret","last_synced_at":"2026-05-10T02:02:24.236Z","repository":{"id":186840477,"uuid":"641126125","full_name":"percevalw/pret","owner":"percevalw","description":"Pret is a library for building full-stack reactive user interfaces in Python, using React as a rendering engine.","archived":false,"fork":false,"pushed_at":"2025-06-23T00:31:01.000Z","size":6842,"stargazers_count":0,"open_issues_count":2,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-06-23T00:33:48.618Z","etag":null,"topics":["application","jupyter","python","react","ui","web","widget"],"latest_commit_sha":null,"homepage":"https://percevalw.github.io/pret/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/percevalw.png","metadata":{"files":{"readme":"README.md","changelog":"changelog.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2023-05-15T20:47:49.000Z","updated_at":"2025-06-15T13:54:01.000Z","dependencies_parsed_at":null,"dependency_job_id":"87c5030d-0e2e-4f71-bf6b-d17f8eef5e84","html_url":"https://github.com/percevalw/pret","commit_stats":null,"previous_names":["percevalw/pret"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/percevalw/pret","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/percevalw%2Fpret","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/percevalw%2Fpret/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/percevalw%2Fpret/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/percevalw%2Fpret/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/percevalw","download_url":"https://codeload.github.com/percevalw/pret/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/percevalw%2Fpret/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261391836,"owners_count":23151702,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["application","jupyter","python","react","ui","web","widget"],"created_at":"2024-10-02T10:28:00.077Z","updated_at":"2026-02-27T11:56:48.769Z","avatar_url":"https://github.com/percevalw.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"![Tests](https://img.shields.io/github/actions/workflow/status/percevalw/pret/tests.yml?branch=main\u0026label=tests\u0026style=flat-square)\n[![Documentation](https://img.shields.io/github/actions/workflow/status/percevalw/pret/docs.yml?branch=main\u0026label=docs\u0026style=flat-square)](https://percevalw.github.io/pret/latest/)\n[![PyPI](https://img.shields.io/pypi/v/pret?color=blue\u0026style=flat-square)](https://pypi.org/project/pret/)\n[![pret](https://labextensions.dev/api/badge/pret?metric=downloads\u0026leftColor=%23555\u0026rightColor=%23F37620\u0026style=flat)](https://labextensions.dev/extensions/pret)\n[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/percevalw/pret/main?urlpath=%2Fdoc%2Ftree%2Fexamples%2FTodos.ipynb)\n\n# PRET\n\nPret is a library for building full-stack reactive user interfaces in Python, using React as a rendering engine.\n\n## Installation\n\n```bash\npip install pret pret-joy\n```\n\nTo use it with Jupyter, if you install the library in a custom environment (conda, venv, or other),\nyou will likely need to tell Jupyter where to find the front-end files.\nYou can do this by running the following command (only once):\n\n```bash\npret update-jupyter-config --apply\n```\n\n## Features\n\n- **Python, only Python**: pret is written in Python: you can write your both your UI and server actions Python. No need to learn a new language.\n- **Client-side rendering**: unlike other Python UI frameworks, pret runs primarily in the browser. This enables a fast response time to user actions (like hover events), and a better user experience under degraded network conditions.\n- **Built on React**: pret uses React as a rendering engine, and benefits from its ecosystem.\n- **Reactive**: unlike other solutions like ipywidgets, pret is reactive. Only the parts of the UI that need to be updated are re-rendered.\n- **State management**: in addition to React's local state management (i.e. `use_state`), pret provides a global and modular state management solution that is synchronized between components, between the browser and the server, and can even be persisted to a file for collaborative editing.\n- **Modular**: pret is designed to be modular. You can easily create your own components, and reuse them in other pret-based projects.\n- **Integrated with Jupyter**: pret components can be used in Jupyter notebooks, as well as in standalone web applications.\n- **Remote execution**: pret can call and use the result of Python functions on the server from the browser\n\n## Use it in a notebook\n\nLet's write a simple todo app that should:\n\n- display a list of todos, that can be checked as done\n- display the number remaining todos\n- change the font to bold as a todo is hovered\n- allow editing the todo list directly in Python\n\nCopy and paste the following code in a notebook:\n\n```python { .render-with-pret }\nfrom pret import component, create_store, run, use_state, use_store_snapshot\nfrom pret_joy import Checkbox, Input, Stack, Typography\n\nstore = create_store(\n    {\n        \"faire à manger\": True,\n        \"faire la vaisselle\": False,\n    },\n    sync=True,\n)\n\n\n@component\ndef TodoApp():\n    todos = use_store_snapshot(store)\n    typed, set_typed = use_state(\"\")\n    num_remaining = sum(not ok for ok in todos.values())\n    plural = \"s\" if num_remaining \u003e 1 else \"\"\n\n    def on_key_down(event):\n        if event.key == \"Enter\":\n            store[typed] = False\n            set_typed(\"\")\n\n    return Stack(\n        *(\n            Checkbox(\n                label=todo,\n                checked=ok,\n                on_change=lambda e, t=todo: store.update({t: e.target.checked}),\n            )\n            for todo, ok in todos.items()\n        ),\n        Input(\n            value=typed,\n            on_change=lambda event: set_typed(event.target.value),\n            on_key_down=on_key_down,\n            placeholder=\"Add a todo\",\n        ),\n        Typography(\n            f\"Number of unfinished todo{plural}: {num_remaining}\",\n            sx={\"minWidth\": \"230px\"},  # just to avoid jittering when it's centered\n        ),\n        spacing=2,\n        sx={\"m\": 1},\n    )\n\n\nTodoApp()\n```\n\nIn comparison, the closest alternative using ipywidgets looks like the following snippet:\n\n\u003cdetails\u003e\n\u003csummary\u003eIPyWidget's implementation\u003c/summary\u003e\n\n```python { .no-exec }\nimport ipywidgets as widgets\n\nstate = {\n    \"faire à manger\": True,\n    \"faire la vaisselle\": False,\n}\n\n\nclass IPWTodoApp:\n    def __init__(self):\n        self.box = widgets.VBox()\n        self.render()\n\n    def _repr_mimebundle_(self, *args, **kwargs):\n        return self.box._repr_mimebundle_(*args, **kwargs)\n\n    def render(self, *args, **kwargs):\n        num_remaining = sum([not checked for _, checked in state.items()])\n        plural = \"s\" if num_remaining \u003e 1 else \"\"\n\n        def on_input_submit(sender):\n            state[input_widget.value] = False\n            self.render()\n\n        def create_todo_item(todo, checked):\n            def update_todo_status(*args, **kwargs):\n                state[todo] = checkbox.value\n                self.render()\n\n            checkbox = widgets.Checkbox(\n                value=checked,\n                description=todo,\n                disabled=False,\n                indent=False,\n            )\n            checkbox.observe(update_todo_status, names=\"value\")\n            return checkbox\n\n        input_widget = widgets.Text(\n            placeholder=\"Add a todo\",\n            description=\"\",\n            disabled=False,\n        )\n        input_widget.on_submit(on_input_submit)\n\n        self.box.children = [\n            *(create_todo_item(todo, checked) for todo, checked in state.items()),\n            input_widget,\n            widgets.Label(value=f\"Number of unfinished todo{plural}: {num_remaining}\"),\n        ]\n\n\nIPWTodoApp()\n```\n\u003c/details\u003e\n\nYou also lose some features:\n\n- the app stops working if the server shuts down\n- hover events cannot be listened to\n- no React dom diffing: the app must either be re-rendered entirely (as in the example),\n  or you must determine specifically which field of which widget to update\n\n## Use it in a standalone app\n\nYou can also use pret to build standalone web applications. Copy the above code in a file\nnamed `app.py`, and change the last line to\n\n```python\nif __name__ == \"__main__\":\n    run(TodoApp)\n```\n\nThen, run the following command, and voilà !\n\n```bash\npython app.py\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpercevalw%2Fpret","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpercevalw%2Fpret","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpercevalw%2Fpret/lists"}