{"id":14065188,"url":"https://github.com/TexteaInc/funix","last_synced_at":"2025-07-29T20:31:39.666Z","repository":{"id":73265102,"uuid":"504765701","full_name":"TexteaInc/funix","owner":"TexteaInc","description":"Building web apps without manually creating widgets","archived":false,"fork":false,"pushed_at":"2024-10-30T05:13:43.000Z","size":42764,"stargazers_count":100,"open_issues_count":13,"forks_count":11,"subscribers_count":4,"default_branch":"main","last_synced_at":"2024-10-30T08:33:27.176Z","etag":null,"topics":["app-builder","data-science","frontend","machine-learning"],"latest_commit_sha":null,"homepage":"http://funix.io","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/TexteaInc.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","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},"funding":{"github":["TexteaInc"],"patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"lfx_crowdfunding":null,"custom":null}},"created_at":"2022-06-18T06:39:40.000Z","updated_at":"2024-10-21T07:18:06.000Z","dependencies_parsed_at":"2023-12-23T02:54:18.481Z","dependency_job_id":"40d6f9de-39b6-43ae-82ce-e14c0837609e","html_url":"https://github.com/TexteaInc/funix","commit_stats":null,"previous_names":[],"tags_count":23,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TexteaInc%2Ffunix","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TexteaInc%2Ffunix/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TexteaInc%2Ffunix/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TexteaInc%2Ffunix/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/TexteaInc","download_url":"https://codeload.github.com/TexteaInc/funix/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228046116,"owners_count":17861101,"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":["app-builder","data-science","frontend","machine-learning"],"created_at":"2024-08-13T07:04:21.427Z","updated_at":"2025-07-29T20:31:39.642Z","avatar_url":"https://github.com/TexteaInc.png","language":"Python","funding_links":["https://github.com/sponsors/TexteaInc"],"categories":["Python"],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003e\n    \u003c!-- \u003cb\u003e --\u003e\n        Funix.io\u003cbr\u003e\n    \u003c!-- \u003c/b\u003e --\u003e\n    The laziest way to build AI/Data apps in Python\n\u003c/h1\u003e\n\n\n\u003cdiv align=\"center\"\u003e\n\n[![PyPI version](https://badge.fury.io/py/funix.svg)](https://badge.fury.io/py/funix)\n[![](https://dcbadge.vercel.app/api/server/JyANAMUAHM?style=flat)](https://discord.gg/JyANAMUAHM)\n\n\u003ch4\u003e\u003ca href=\"https://youtu.be/qDkzXS270Zo\"\u003eIntro video\u003c/a\u003e | \u003ca href=\"#getting-started-with-funix\"\u003eGetting started\u003c/a\u003e |  \u003ca href=\"#gallery\"\u003e Gallery \u003c/a\u003e | \u003ca href=\"https://github.com/TexteaInc/funix-doc/blob/main/Reference.md\"\u003eReference Manual\u003c/a\u003e \u003c/h4\u003e\n\nhttps://github.com/TexteaInc/funix/assets/438579/86868ab5-ed6e-46e5-8dc5-9e3e4a3cdc3f\n\n\u003c/div\u003e\n\n## What is Funix?\n\n* Funix automatically turns an ordinary Python function or class definition into a web app, which is accessible in a browser via a shareable link. \n* Funix is the frontend/backend/fullstack engineer and the infra/ops engineer for AI/Data/Science solo stars like you. \n* Funix is the no-/low-code solution for those who write the most core and innovative code. \n* Funix is open-source and can be deployed on-premises. \n\n## Use cases\n\n* Startups: quickly build demos, iterate on MVPs, get user feedback and statistics, and pitch to investors or your mom. \n* Generative AI: instantly allow people to interact your GenAI model or idea.\n* STEM research: let people run your model and/or algorithm effortlessly. \n* Data browser: an interface to page through your data. \n* A/B test and data labeling: collect human labeling or preference.\n\n## Key advantages\n\n* **Minimalist and out-of-box**: Make no or little addition to your existing code. \n* **CSS for Python**: Widgets are generated automatically based on variable types according to a theme, rather than per-variable manually, for centralized, reusable, and consistent UI across apps. \n* **Non-intrusive and declarative**: As JSON strings, UI configurations are separated from the core logic. Your code can still be run, imported, and called as usual. \n* **Seamlessly Pythonic**: Map Python's native keywords to web app features, such as `global` for sessions, `yield` for streaming, and `print` for anything you wanna display in your app. \n* **Apps, not demos**: Out of the box support for [access control](https://github.com/TexteaInc/funix-doc/blob/main/Reference.md#secret), user tracking and Do-Not-Track options, [multipage apps](https://github.com/TexteaInc/funix-doc/blob/main/Reference.md#multipage-apps-and-sessionsstates) with data passing, session management, reactiveness, backend telemetry, etc.\n\n#### Love Funix? Give us a star\n\n![Borrowed from AppFlowy](https://github.com/AppFlowy-IO/AppFlowy/raw/main/doc/imgs/howtostar.gif)\n\n## Hello, world!\n\n1. Install Funix ([advanced installation options](#installation)):\n\n    ```sh\n    pip install funix\n    ```\n\n2. Save the code below to a file called `hello.py`:\n\n    ```python\n    def hello(your_name: str) -\u003e str:\n        return f\"Hello, {your_name}.\"\n    ```\n\n3. Running this command\n\n    ```bash\n    $ funix hello.py\n    ```\n\n4. The app will pop in a browser on `http://localhost:3000`:\n\n    ![screenshots/hello.png](https://github.com/TexteaInc/funix-doc/raw/main/screenshots/hello.png)\n\n\n\u003c!-- \u003e **Note**: The `-l` flag stands for _\"lazy\"_ meaning that only default settings are used. It cannot be used when your function is decorated by the funix decorator `@funix()` which allows you to customize your app. For more details, please refer to the [reference manual]([docs/Reference.md](https://github.com/TexteaInc/funix-doc/blob/main/Reference.md)). --\u003e\n\n## Getting started with Funix\n\n**The Zen of Funix** is to generate widgets for function I/Os based on their types, instead of manually picking and customizing the widget for each I/O. **Funix to Python is like CSS to HTML or style class to LaTeX**. UI stuff is not intermingled with the core logic but defined separately. The type-to-widget mapping is controlled by a theme and new types can be defined on top of existing types.\n\nThe example below shows how common UI compoents are generated from four Python-native data types: `str`, `bool`, `Literal` and `range`, as well as types in popular packages such as `ipywidgets.Password`. The example below further maps default values to placeholders in the UI widgets. From this example, we can see that developers need to **learn nothing about Funix or do nothing to their existing code** before they can get an app.\n\n```python\nimport typing # Python native \n\nimport ipywidgets  # popular UI library \n\ndef input_widgets_basic(\n    prompt: str = \"Who is Oppenheimer?\",\n    advanced_features: bool = True,\n    model: typing.Literal['GPT-3.5', 'GPT-4.0', 'Falcon-7B'] = 'GPT-4.0',\n    max_token: range(100, 200, 20) = 140,\n    openai_key: ipywidgets.Password = \"1234556\",\n    )  -\u003e str:\n    pass\n```\n\n![four input types](https://raw.githubusercontent.com/TexteaInc/funix-doc/main/screenshots/input_widgets.png)\n\nThe example below shows how `pandas.DataFrame` and `matplotlib.figure.Figure` that AI/data developers cannot be more familiar with are mapped to tables and charts in an app.\n\n```python\nimport pandas, matplotlib.pyplot\nfrom numpy import arange, log\nfrom numpy.random import random\n\ndef table_and_plot(\n    df: pandas.DataFrame = pandas.DataFrame({\n        \"a\": arange(500) + random(500)/5,\n        \"b\": random(500)-0.5 + log(arange(500)+1),\n        \"c\": log(arange(500)+1) })\n    ) -\u003e matplotlib.figure.Figure:\n\n    fig = matplotlib.pyplot.figure()\n    matplotlib.pyplot.plot(df[\"a\"], df[\"b\"], 'b')\n    matplotlib.pyplot.plot(df[\"a\"], df[\"c\"], 'r')\n\n    return fig\n```\n\n![table and plot screenshot](https://raw.githubusercontent.com/TexteaInc/funix-doc/main/screenshots/table_plot.png)\n\nYou can even continuously update a plot based on user input.\n\n```python\nimport funix \nimport matplotlib.pyplot, matplotlib.figure\nimport numpy \n\n@funix.funix(\n        autorun=True, \n)\ndef sine(omega: funix.hint.FloatSlider(0, 4, 0.1)) -\u003e matplotlib.figure.Figure:\n    fig = matplotlib.pyplot.figure()\n    x = numpy.linspace(0, 20, 200)\n    y = numpy.sin(x*omega)\n    matplotlib.pyplot.plot(x, y, linewidth=5)\n    return fig\n```\n\n![continuous sine function](https://raw.githubusercontent.com/TexteaInc/funix-doc/main/screenshots/continous_run_sine.gif)\n\n### Out-of-box support for classes and OOP\n\nFunix can turn each member method of a class into a page of an app. \nIn two additional lines, the example below turn a class definition into a multi-page app with the OOP experience where the instantiation of an object of the class is done in a page corresponding to the constructor of the class and the member values of the object can be viewed and updated in other pages. **No need to manually expose** the member methods of the class.\n\n```python\nfrom funix import funix_class\n\n@funix_class()  \nclass A:\n    def __init__(self, a: int):\n        self.a = a\n        return f\"`self.a` has been initialized to {self.a}\"\n\n    def set(self, b: int) -\u003e str:\n        self.a = b\n        return f\"`self.a` has been updated to {self.a}\"\n\n    def get(self) -\u003e str:\n        return f\"The value of `self.a` is {self.a}\"\n```\n\n![class demo app gif](https://raw.githubusercontent.com/TexteaInc/funix-doc/main/videos/class/class.gif)\n\nA more advanced example of class is the wordle game. You can find the source code in [`examples/wordle.py`](./examples/games/wordle.py). In less than 100 lines, you can build Wordle! The screenshot is as follows:\n\n![Wordle demo](https://github.com/TexteaInc/funix-doc/blob/main/screenshots/wordle.png?raw=true)\n\n### The quickest way to build GenAI apps\n\nYou can wrap any Python function into a web app in Funix.\nFor example, you can take the ChatGPT demo code from OpenAI's APi reference and wrap it into a str-to-str function:\n\n```python\nfrom openai import OpenAI\n\ndef ChatGPT(prompt: str) -\u003e str:    \n    client = OpenAI()\n\n    completion = client.chat.completions.create(\n        model=\"gpt-3.5-turbo\",\n        messages=[\n            {\"role\": \"user\", \"content\": prompt}\n        ]\n    )\n    return completion.choices[0].message.content\n```\n\nwhich is turned into an app by Funix like below: \n\n![screenshots/ChatGPT_lazy.png](https://github.com/TexteaInc/funix-doc/raw/main/screenshots/chatGPT_lazy.png)\n\n### Themes: the CSS for Python\n\n**Funix to Python is like CSS to HTML or macros to LaTeX.** It separates the core logic and the UI.\nAll UI stuff is centrally defined in a JSON-based theme to avoid the repetitiveness of individually configuring widgets and keep a consistent look across apps. Consequently, a data scientist or a machine learning engineer does not need to think about anything UI. Just leave it to the UI team and Funix.\n\nBelow is an example of a theme file. It defines the widget choices based on variable types and tweaks the `props` of UI components (currently only MUI ones are supported). Funix exposes frontend components and their `props` to developers, requiring them to know nothing about frontend. To know more about how to define and apply a theme, please refer to [the Themes section in the reference manual](https://github.com/TexteaInc/funix-doc/blob/main/Reference.md#themes).\n\n```jsonc\n{\n  \"name\": \"test_theme\",\n  \"widgets\": {    // dict, map types to widgets\n    \"str\": \"inputbox\", // using Funix' widget shorthand\n    \"int\": \"slider[0,100,2]\", // using Funix' widget shorthand\n    \"float\": {\n        \"widget\": \"@mui/material/Slider\", // using MUI's widget\n        // https://mui.com/material-ui/api/slider\n        \"props\": {\n            \"min\": 0,\n            \"max\": 100,\n            \"step\": 0.1\n        }\n    }, \n    \"Literal\": \"radio\"\n  },\n}\n```\n\nTo introduce a new data type, just declare a new Python class, and use a decorator to let Funix know. You can associate the type with a widget either on-the-fly (below) or via a theme file.\n\n```python\nfrom funix import funix, new_funix_type\n\n@new_funix_type(\n    widget = {\n        \"widget\": \"@mui/material/TextField\",\n        \"props\": {\n            \"type\": \"password\",\n            \"placeholder\": \"Enter a secret here.\"\n        }\n    }\n)\nclass blackout(str):\n    def print(self):\n        return self + \" is the message.\"\n\n@funix()\ndef hoho(x: blackout = \"Funix Rocks!\") -\u003e str:\n    return x.print()\n\nif __name__ == \"__main__\":\n    print (hoho(blackout('Fun'))) \n```\n\n### Python-native to web-native\n\nFunix repurposes some Python-native features to web features.\n\nFirst, Funix won't let your docstring or `print()` function calls go to waste. They will appear in the input and output panels of the web app.\n\n```python\nfrom funix import funix\n@funix(\n    print_to_web=True\n)\ndef foo() -\u003e None:\n    \"\"\"\n    ## What a great app in Funix! \n    \n    Funix won't let your docstring go to waste.\n    \"\"\"\n    print(\"It supports **Markdown**.\")\n    print (\"And \u003cb\u003eHTML\u003c/b\u003e.\")\n    return None\n```\n\n![Docstring and print to web](https://github.com/TexteaInc/funix-doc/blob/main/screenshots/docstring_and_print.png?raw=true)\n\nTo stream text to the web, simply use `yield`:\n\n```python\nimport time\n\ndef stream() -\u003e str:\n    \"\"\"\n    This function is used to test the stream feature of Funix.\n    \"\"\"\n    message = \"We the People of the United States, in Order to form a more perfect Union, establish Justice, insure domestic Tranquility, provide for the common defence, promote the general Welfare, and secure the Blessings of Liberty to ourselves and our Posterity, do ordain and establish this Constitution for the United States of America.\"\n\n    for i in range(len(message)):\n        time.sleep(0.01)\n        yield message[0:i]\n```\n\n![Streamt text to web](https://github.com/TexteaInc/funix-doc/blob/main/screenshots/stream.gif?raw=true)\n\n## Advanced features\n\n### History: Keep your call logs\n\n\u003cdetails\u003e\n\u003csummary\u003e\nClick to expand\n\u003c/summary\u003e\n\nA feature request that we hear from many users is that they do not use a Funix-converted app as a demo that they will use only a couple of time but as a real app that they will use again and again. In this case, they want to keep the call history of the app. Funix supports this feature by default. You can access the history of your app by clicking the history button on the top right corner of the app. \n\n![history sidebar](https://raw.githubusercontent.com/TexteaInc/funix-doc/main/screenshots/history_sidebar.gif)\n\n\u003c/details\u003e\n\n### Multipage data passing and session/state management\n\n\u003cdetails\u003e\n\u003csummary\u003e\nClick to expand\n\u003c/summary\u003e\n\nA real app usually comes with multiple page, e.g., setting OpenAI token key in one page and then use the token in other GenAI pages. Functions in the same `.py` script will become different pages of one app. Any global variable can be used to pass data between functions. When you start Funix with the flag `-t`, it will further sessionize the global variables so that different users can have their own sessions. Below is a simple example and the corresponding GIF animation. In the GIF animation you can see that the value `y` differs in two browser sessions. \n\n```python\nimport funix\n\ny = \"The default value of y.\"\n\n@funix.funix()\ndef set_y(x: str=\"123\") -\u003e str:\n    global y\n    y = x\n    return \"Y has been changed. Now check it in the get_y() page.\"\n\n\n@funix.funix()\ndef get_y() -\u003e str:\n    return y\n```\n\n![session](https://raw.githubusercontent.com/TexteaInc/funix-doc/main/screenshots/session.gif)\n\n\u003c/details\u003e\n\n### Prefill\n\n\u003cdetails\u003e\n\u003csummary\u003e\nClick to expand\n\u003c/summary\u003e\n\nA special case of passing data between functions is to use the return value of one function as the value in the widget of an argument of another function. This is called prefill. Funix support prefill by using a decorator attribute `pre_fill`. Below is an example and the corresponding GIF animation.\n\n\n```python\nimport funix\n\n@funix.funix()\ndef first_action(x: int) -\u003e int:\n  return x - 1\n\n@funix.funix()\ndef second_action(message: str) -\u003e list[str]:\n  return message.split(\" \")\n\n@funix.funix()\ndef third_action(x: int, y: int) -\u003e dict:\n  return {\"x\": x, \"y\": y}\n\n@funix.funix(\n  pre_fill={\n    \"a\": first_action,\n    \"b\": (second_action, -1),\n    \"c\": (third_action, \"x\")\n  }\n)\ndef final_action(a: int, b: str, c: int) -\u003e str:\n    return f\"{a} {b} {c}\"\n```\n\n\u003c!-- FIXME: ADD GIF IMAGE HERE --\u003e\n\u003c/details\u003e\n\n### Secret: Access control\n\n\u003cdetails\u003e\n\u003csummary\u003e\nClick to expand\n\u003c/summary\u003e\n\n\u003e Note: This is not a strong way to protect your app.\n\nTo protect your code (e.g., OpenAI-related functions, which may result in some financial loss), you can use the `secret` option.\n\n```bash\nfunix  my_app.py --secret  my_secret_token # use a token provided by you\n# or \nfunix  my_app.py --secret  True # randomly generate a token\n```\n\nThe token will be printed on the Terminal. For example,\n\n```bash\n$ funix hello.py --secret True\nSecrets:\n---------------\nName: hello\nSecret: 8c9f55d0eb74adbb3c87a445ea0ae92f\nLink: http://127.0.0.1:3000/hello?secret=8c9f55d0eb74adbb3c87a445ea0ae92f\n```\n\nThe token needs to be included in the URL or manually entered in order to execute the app. \n\n![secret](https://raw.githubusercontent.com/TexteaInc/funix-doc/main/screenshots/secret.gif)\n\n\u003c/details\u003e\n\n## Gallery\n\nMore examples in \u003ca href=\"https://github.com/TexteaInc/funix-doc/blob/main/Reference.md\"\u003eReference Manual\u003c/a\u003e or the \u003ccode\u003e./examples\u003c/code\u003e folder.\n\n* [ChatPaper](https://github.com/forrestbao/ChatPaper) (It's like the popular ChatPDF. But in Funix, only 70 lines of code needed.)\n* [mFlux](https://github.com/Yazawazi/MFlux) (synthetic biology)\n\n### ChatGPT, multi-turn\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003ccode\u003eexamples/AI/chatGPT_multi_turn.py\u003c/code\u003e 👈 Toggle me to show source code \u003c/summary\u003e\n\n  ```python\n    import os\n    import IPython     \n    from openai import OpenAI\n    import funix\n\n    client = OpenAI(api_key=os.environ.get(\"OPENAI_KEY\"))\n\n    messages  = []  # list of dicts, dict keys: role, content, system\n\n    @funix.funix(\n        disable=True,\n    )\n    def print_messages_html(messages):\n        printout = \"\"\n        for message in messages:\n            if message[\"role\"] == \"user\":\n                align, name = \"left\", \"You\"\n            elif message[\"role\"] == \"assistant\":\n                align, name = \"right\", \"ChatGPT\"\n            printout += f'\u003cdiv style=\"width: 100%; text-align: {align}\"\u003e\u003cb\u003e{name}\u003c/b\u003e: {message[\"content\"]}\u003c/div\u003e'\n        return printout\n\n\n    @funix.funix(\n        direction=\"column-reverse\",\n    )\n    def ChatGPT_multi_turn(current_message: str)  -\u003e IPython.display.HTML:\n        current_message = current_message.strip()\n        messages.append({\"role\": \"user\", \"content\": current_message})\n        completion = client.chat.completions.create(messages=messages,\n        model='gpt-3.5-turbo',\n        max_tokens=100)\n        chatgpt_response = completion.choices[0].message.content\n        messages.append({\"role\": \"assistant\", \"content\": chatgpt_response})\n\n        # return print_messages_markdown(messages)\n        return print_messages_html(messages)\n\n  ```\n\n\u003c/details\u003e\n\n![Multiturn chat](https://github.com/TexteaInc/funix-doc/raw/main/screenshots/chatGPT_multiturn.png)\n\n### Shortest Dall-E web app in Python\n\n```python\nfrom funix import funix                      # add line one\nfrom IPython.display import Image\nfrom openai import OpenAI                    # pip install openai\n\nimport os\nclient = OpenAI(api_key=os.environ.get(\"OPENAI_KEY\"))  \n\n\n@funix()                                     # add line two\ndef dalle(prompt: str = \"a cat\") -\u003e Image:\n    response = client.images.generate(prompt=prompt)\n    return response.data[0].url\n```\n\n![Dalle demo](https://github.com/TexteaInc/funix-doc/raw/main/screenshots/dalle.jpg)\n\n\u003c!-- Funix.io can get the same job done in half the amount of code required by Gradio, by exploiting the Python language as much as possible. Here, state/session is maintained using a global variable, while the order of the returns defines the return layout.  --\u003e\n\n### Bioinformatics: vector stripping\n\n[\u003ccode\u003eexamples/bioinformatics/vector_strip.py\u003c/code\u003e](./examples/bioinformatics/vector_strip.py) 👈 Click to see source code\n\n![bioinfo vector strip](https://raw.githubusercontent.com/TexteaInc/funix-doc/main/screenshots/bioinfo_vector_strip.png)\n\n### Multimedia inputs and outputs\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ccode\u003eexamples/multimedia/rgb2gray.py\u003c/code\u003e 👈 Toggle me to show source code\u003c/summary\u003e\n\n```python\nimport  io # Python's native \n\nimport PIL # the Python Image Library\nimport IPython \nimport funix \n\n@funix.funix(\n    title=\"Convert color images to grayscale images\",\n)\ndef gray_it(image: funix.hint.BytesImage) -\u003e IPython.display.Image:\n    img = PIL.Image.open(io.BytesIO(image))\n    gray = PIL.ImageOps.grayscale(img) \n    output = io.BytesIO()\n    gray.save(output, format=\"PNG\")\n    return output.getvalue()\n```\n\u003c/details\u003e\n\n![shipping example](https://raw.githubusercontent.com/TexteaInc/funix-doc/main/screenshots/rgb2gray.png)\n\n### Layout and EasyPost shipping\n\n[`examples/layout_easypost_shipping.py`](./examples/layout_easypost_shipping.py) 👈 Click me to see source code\n\n![shipping example](https://raw.githubusercontent.com/TexteaInc/funix-doc/main/screenshots/easypost_shipping.png)\n\n## Usage\n\n### Installation\n\n* From PyPI (stable, lacking the latest feature)\n    ```bash\n    pip install funix\n    ```\n* From GitHub (latest)\n\n    ```bash\n    pip install \"git+https://github.com/TexteaInc/funix.git@develop\" # Develop version\n    pip install \"git+https://github.com/TexteaInc/funix.git\" # Stable version\n    ```\n* Local development\n\n    ```bash\n    git clone -b develop https://github.com/TexteaInc/funix\n    cd funix\n    pip install -e .\n    ```\n    Add `--prefix=~/.local` if pip insists to install to system paths. See [#24](https://github.com/TexteaInc/funix/issues/24) and [#23](https://github.com/TexteaInc/funix/issues/23)\n\n### Additional type support\n\n1. If you want to use `git` related features (use project from GitHub), install funix by:\n    \n    ```bash\n    pip install funix[git]\n    ```\n\n2. If you want to use `ipython` features, install funix by:\n    \n    ```bash\n    pip install funix[ipython]\n    ```\n\n3. If you need to have more than one feature, you can try installing them together:\n    \n    ```bash\n    pip install funix[all]\n    ```\n\n### Building the frontend\n\nIn the last two cases above, you will need to compile the frontend by yourself. Suppose you are in the `funix` folder. Then run the following commands:\n\n1. `cd frontend`\n2. `yarn install` (you need install Node.JS and Yarn)\n3. `yarn funix:build`\n\nFor debugging:\n\n1. `yarn funix:test` (Start development mode)\n2. `funix xxx -p 8080 -F` (Use 8080 port and no frontend mode)\n\n#### Building the frontend with MUI Pro or MUI Premium\n\nOur table widget uses advanced features in MUI Pro or MUI Premium. If you have a MUI Pro or MUI premium license, you can build the frontend with MUI Pro by following the steps below:\n\n1. Install Node.js and Yarn;\n2. Run `export MUI_PRO_LICENSE_KEY=[MUI_KEY]` or `export MUI_PREMIUM_LICENSE_KEY=[MUI_KEY]`;\n3. Run `yarn install \u0026\u0026 yarn funix:build` to build the frontend;\n4. Done!\n\n### Command line options\n\nRun the command below to see the command line options:\n\n```text\nfunix -h \n```\n\n### Call `funix` in Python\n\nBesides starting Funix from the command line, you can also use a self-contained `.py` script:\n\n```python\nimport funix\n\n@funix.funix()\ndef hello(your_name: str) -\u003e str:\n    return f\"Hello, {your_name}.\"\n\nif __name__ == \"__main__\":\n    funix.run(__file__)\n```\n\n### Exposing a Funix-converted app to the public\n\n```bash\nfunix [module] --host [your_server_ip]\n```\n\n## How to contribute\n\nFunix is open-sourced under the MIT License. Community contribution is not only welcomed but desired. Feel free to fork and make a pull request when you are ready. You can also report bugs, suggest new features via the [issue tracker](https://github.com/TexteaInc/funix/issues/new) or our [Discord server](https://discord.gg/JyANAMUAHM).\n\n## Acknowledgment\n\nFunix draws inspiration from FastAPI and Python-Fire: building software interfaces by inferring from function signatures containing type hints. We port this idea from the backend (FastAPI) or the terminal (Python-Fire) to the frontend. We also thank Streamlit, Gradio, PyWebIO, and Pynecone/Reflex. They inspired us. We are just too lazy to manually define widgets imperatively. Funix’s backend is implemented in Flask and the frontend in Material UI.\n\n## Contact\n\nForrest dot Bao @ Gmail \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FTexteaInc%2Ffunix","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FTexteaInc%2Ffunix","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FTexteaInc%2Ffunix/lists"}