{"id":26949677,"url":"https://github.com/numerous-com/numerous-apps","last_synced_at":"2025-04-02T22:17:07.742Z","repository":{"id":267688689,"uuid":"902048051","full_name":"numerous-com/numerous-apps","owner":"numerous-com","description":"A new Python framework in development, aiming to provide a powerful yet simple approach for building reactive web applications. Numerous Apps empowers developers to create modern, scalable web apps with Python, maintaining a clear separation between business logic and presentation.","archived":false,"fork":false,"pushed_at":"2025-03-06T22:42:40.000Z","size":325,"stargazers_count":6,"open_issues_count":0,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-03-06T23:26:42.295Z","etag":null,"topics":["app","html","python","web"],"latest_commit_sha":null,"homepage":"https://www.numerous.com","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/numerous-com.png","metadata":{"files":{"readme":"docs/README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","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}},"created_at":"2024-12-11T20:02:35.000Z","updated_at":"2025-03-06T22:42:42.000Z","dependencies_parsed_at":"2025-01-04T15:25:03.188Z","dependency_job_id":"6e90d564-8f92-4fd4-93b4-1031d4a6477a","html_url":"https://github.com/numerous-com/numerous-apps","commit_stats":null,"previous_names":["numerous-com/numerous-apps"],"tags_count":25,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/numerous-com%2Fnumerous-apps","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/numerous-com%2Fnumerous-apps/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/numerous-com%2Fnumerous-apps/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/numerous-com%2Fnumerous-apps/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/numerous-com","download_url":"https://codeload.github.com/numerous-com/numerous-apps/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246899655,"owners_count":20851899,"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","html","python","web"],"created_at":"2025-04-02T22:17:07.241Z","updated_at":"2025-04-02T22:17:07.732Z","avatar_url":"https://github.com/numerous-com.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Numerous Apps\n\n## Quick Start\n\nTo install the framework and bootstrap your first app, run the following commands:\n\n```bash\npip install numerous-apps\nnumerous-bootstrap my_app\n```\n\nThis will copy a simple bootstrap app to the `my_app` directory, install the dependencies and start the app server on 127.0.0.1:8000.\nTo run the app subsequently, run the following command:\n\n```bash\ncd my_app\npython app.py\n```\n\nTo edit the python reactivity, edit the `app.py` file.\n\nTo edit the html template, edit the `index.html.j2` file. Its a jinja2 template file, so you can use the jinja2 syntax to define the layout of the app.\n\n## Introduction\n\nA new Python framework in development, aiming to provide a powerful yet simple approach for building reactive web applications. **Numerous Apps** empowers developers to create modern, scalable web applications using familiar Python patterns while maintaining a clean separation between business logic and presentation.\n\n## Who is this for?\n\nThis framework is for teams who want to build fantastic apps with a modular approach and a powerful Python backend. It is for apps exposing functionality built using Python requiring a reactive UI tightly integrated with the backend.\n\nIf you are:\n\n- Using standard development tools and languages.\n- Seeking to have full control over the layout, components and styling for your apps.\n- OK with a bit of boilerplate to keep your code clean and organized.\n- Creating a library of your own anywidgets that you can use in other Python app frameworks or React apps.\n\nThis framework is for you.\n\nOur framework emphasizes modularity, allowing for easy separation of concerns. While we acknowledge that the boilerplate introduced to separate business logic from presentation is a trade-off, we strive to make it as easy as possible to use.\n\n---\n\n## Planned Features\n\n### **Simple Yet Powerful**\n- **Intuitive Syntax:** Develop reactive web apps using standard Python and HTML.\n- **Quick Start:** Utilize the `numerous-bootstrap` command to create a new app in seconds.\n- **Lightweight Core:** Built atop FastAPI, Uvicorn, Jinja2, and anywidget to keep the core lightweight and simple.\n\n### **Modern Architecture**\n- **Component-Based:** Leverage [anywidget](https://anywidget.dev/) for reusable, framework-agnostic components.\n- **Clear Separation:** Use Python for logic, CSS for styling, and Jinja2 for templates.\n- **Process Isolation:** Each session runs independently, enhancing stability and scalability.\n\n### **Full Creative Control**\n- **Framework-Agnostic UI:** No enforced styling or components from our side — You have complete freedom in design.\n- **Custom Widget Support:** Easily integrate your own HTML, CSS, JS components, and static files.\n- **Flexible Templating:** Utilize Jinja2 and HTML for powerful layout composition.\n\n### **Built for Scale**\n- **Multi-Client Ready:** Designed to scale and handle multiple clients simultaneously, with support for distributed app instances.\n- **AI Integration:** Seamless integration with AI agents and models.\n- **Developer-Friendly:** Compatible with your favorite IDE and development tools—no special IDE or notebook needed.\n\n## Getting Started\n\nThis guide will help you get started with **Numerous Apps**. Since a Numerous App comprises multiple files, we'll use the bootstrap app as a foundation. The bootstrap app provides a minimal structure and example widgets to help you begin.\n\n### Installation\n\nFirst, install the framework:\n\n```bash\npip install numerous-apps\n```\n\n### Bootstrapping Your First App\n\nThen, bootstrap your first app:\n\n```bash\nnumerous-bootstrap my_app   \n```\n\nThis command creates a new directory called `my_app` with the basic structure of a Numerous App. It initializes the necessary files and folders, installs dependencies, and starts the app server (`uvicorn`). You can access the app at [http://127.0.0.1:8000](http://127.0.0.1:8000).\n\nTry out the app and start making changes to the code.\n\n## App File Structure\n\nThe minimal app consists of the following files:\n\n- `app.py`: The main application file defining widgets, business logic, and reactivity.\n- `index.html.j2`: The primary template file used to define the app's layout.\n- `static/`: A directory for static files (images, CSS, JS, etc.), served as-is by the server.\n- `requirements.txt`: Lists the app's dependencies.\n\n## Building Your App from Scratch\n\nWhile the bootstrap app is a helpful starting point, here's a walkthrough on building your app from scratch. This guide helps you understand the framework's workings and how to leverage it to develop your own apps.\n\n- Create a Python file for your app eg. `app.py`.\n\n- In the app file, create a function called `run_app()` which will be used to run the app.\n```python\ndef run_app():\n    ...\n```\n\n- In the `run_app()` function, you define your widgets and create reactivity by using callbacks passed to the widgets.\n\n```python\nimport numerous.widgets as wi\n\n...\n\ncounter = wi.Number(default=0, label=\"Counter:\", fit_to_content=True)\n\ndef on_click(event):\n    # Increment the counter\n    counter.value += 1\n\nbutton = wi.Button(label=\"Click me\", on_click=on_click)\n```\n\nYou can also use the `observe` method to create reactivity which is provided directly by the anywidget framework.\n\n```python\ndef callback(event):\n    # Do something when the widget value changes\n    ...\n\nwidget.observe(callback, names='value')\n```\n\n- At the end of the `run_app()` function, you export the widgets by returning them from the function as a dictionary where the key is the name of the widget and the value is the widget instance.\n```python\nreturn {\n    \"counter\": counter,\n    \"button\": button\n}\n```\n\n- You then create an html template file called `index.html.j2` in the same directory as your app file.\n\n- In the html template file, you can include the widgets by using the `{{ widget_key }}` syntax. Refer to the jinja2 documentation for more information on how to use jinja2 syntax in the html template.\n\n```html\n\u003cdiv style=\"display: flex; flex-direction: column; gap: 10px;\"\u003e\n    {{ counter }}\n    {{ button }}\n\u003c/div\u003e\n```\n\n- You can also include CSS, JS and image files in the static folder, and reference them in the html template like this: `\u003clink href=\"static/css/styles.css\" rel=\"stylesheet\"\u003e`\n\n- Now return to the app Python file and import the create_app function from the numerous.apps package and call it with your template file name and the run_app function as arguments.\n\n```python\nfrom numerous.apps import create_app\n...\napp = create_app(template=\"index.html.j2\", dev=True, app_generator=run_app)\n```\n\n- Finally, run the app by calling the app variable in the if `__name__ == \"__main__\"` block.\n\n```python\nif __name__ == \"__main__\":\n    import uvicorn\n    uvicorn.run(app, host=\"127.0.0.1\", port=8000)\n```\n\nYou can now run your app by running the app.py file and accessing it at `http://127.0.0.1:8000`.\n\n\n## Widgets\n\nWidgets are the building blocks of the app. They are the components that will be used to build the app. Widgets are defined in the `app.py` file.\n\nThe concept of the numerous app framework is to support anywidget and not have our own widget specification. We are adding the minimum amount of functionality to anywidget to make it work in the numerous app framework, which is basically to collect widgets, link them with your html template and then serve them.\n\nTo get started, We do supply a set of anywidgets in the numerous-widgets package. This package is used by the bootstrap app and will be installed when you bootstrap your app.\n\n## HTML Template\n\nThe html template is the main template file which will be used to define the layout of the app. It is a Jinja2 template file, which means you can use Jinja2 syntax to define the layout of the app. This allows you to compose the layout of the app using widgets, but keep it clean and separate from the business logic and reactivity.\n\nWhen you have exported your widgets from you app.py file, you can include them in your html template by using the `{{ widget_key }}` to insert the widget into the layout.\n\nYou can include CSS, JS and image files in the static folder, and reference them in the html template like this: `\u003clink href=\"static/css/styles.css\" rel=\"stylesheet\"\u003e`\n\n## Testing\n\n### Python Tests\n\nThe framework includes a comprehensive test suite for Python code using pytest. To run the tests:\n\n```bash\npytest\n```\n\nFor coverage information:\n\n```bash\npytest --cov=numerous.apps\n```\n\n### JavaScript Tests\n\nThe client-side JavaScript (`numerous.js`) can be tested using Jest. The test suite is located in the `tests/js` directory.\n\nTo run the JavaScript tests:\n\n1. Make sure you have Node.js installed\n2. Install the required npm dependencies:\n   ```bash\n   npm install\n   ```\n3. Run the tests:\n   ```bash\n   npm test\n   ```\n\nFor JavaScript test coverage:\n\n```bash\nnpm run test:coverage\n```\n\nThe JavaScript tests cover key functionality:\n- The `WidgetModel` class for state management\n- The `WebSocketManager` for client-server communication\n- Utility functions for logging and debugging\n\nTo add new JavaScript tests, follow the examples in the `tests/js` directory.\n\nJavaScript tests are automatically run:\n- As part of the pre-commit hooks when pushing code\n- In the GitHub CI/CD pipeline for every push to the repository\n- Coverage reports are generated and archived as artifacts in GitHub Actions\n\n### Pre-commit Hooks\n\nThe project uses pre-commit hooks to ensure code quality and prevent issues before they're committed. Both Python and JavaScript tests are included in the pre-commit workflow:\n\n- Python tests run automatically before pushing code\n- JavaScript tests run automatically before pushing code\n\nTo install the pre-commit hooks:\n\n```bash\npre-commit install --hook-type pre-commit --hook-type pre-push\n```\n\nThis ensures that all tests pass before code is pushed to the repository.\n\n## How It Works\n\nThe **Numerous Apps** framework is built on FastAPI and uses uvicorn to serve the app.\n\nWhen the browser requests the root URL, the server serves the HTML content by inserting a `div` with each widget's corresponding key as the ID into the HTML template using Jinja2.\n\nThe framework includes a `numerous.js` file, a JavaScript library that fetches widgets from the server and renders them. This JavaScript also acts as a WebSocket client, connecting widgets with the server and the Python app code. Widgets are passed the corresponding `div` and then render themselves within it.\n\nEach new instance or session of the app is created by running `app.py` in a new process or thread. The client obtains a session ID from the server and uses this ID to connect. The server uses this ID to route client requests to the correct process or thread.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnumerous-com%2Fnumerous-apps","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnumerous-com%2Fnumerous-apps","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnumerous-com%2Fnumerous-apps/lists"}