{"id":36975359,"url":"https://github.com/jagepard/rudra-framework","last_synced_at":"2026-07-05T07:01:04.328Z","repository":{"id":10045115,"uuid":"64201852","full_name":"Jagepard/Rudra-Framework","owner":"Jagepard","description":"Rudra Framework","archived":false,"fork":false,"pushed_at":"2026-07-04T09:21:44.000Z","size":1359,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2026-07-04T11:08:33.146Z","etag":null,"topics":["framework","mvc","mvc-architecture","mvc-framework","mvc-pattern","rudra"],"latest_commit_sha":null,"homepage":"http://rudra.tdcore.ru/","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Jagepard.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"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,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2016-07-26T07:56:54.000Z","updated_at":"2026-07-04T09:21:46.000Z","dependencies_parsed_at":"2022-08-07T05:15:24.636Z","dependency_job_id":"afc8d161-27b2-4990-8b10-0de234e88e7b","html_url":"https://github.com/Jagepard/Rudra-Framework","commit_stats":{"total_commits":53,"total_committers":3,"mean_commits":"17.666666666666668","dds":0.4716981132075472,"last_synced_commit":"f8959df56f3feb0a0db6c4007d3f3f7f80d89bc8"},"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/Jagepard/Rudra-Framework","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jagepard%2FRudra-Framework","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jagepard%2FRudra-Framework/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jagepard%2FRudra-Framework/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jagepard%2FRudra-Framework/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Jagepard","download_url":"https://codeload.github.com/Jagepard/Rudra-Framework/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jagepard%2FRudra-Framework/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35145900,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-05T02:00:06.290Z","response_time":100,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["framework","mvc","mvc-architecture","mvc-framework","mvc-pattern","rudra"],"created_at":"2026-01-13T22:04:41.345Z","updated_at":"2026-07-05T07:01:04.253Z","avatar_url":"https://github.com/Jagepard.png","language":"PHP","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Maintainability](https://qlty.sh/badges/5a26568e-0d38-4daf-8772-00639e289ee2/maintainability.svg)](https://qlty.sh/gh/Jagepard/projects/Rudra-Framework)\n[![CodeFactor](https://www.codefactor.io/repository/github/jagepard/rudra-framework/badge)](https://www.codefactor.io/repository/github/jagepard/rudra-framework)\n[![PHP Version](https://img.shields.io/badge/PHP-8.3%2B-blue.svg)](https://php.net)\n[![License](https://img.shields.io/badge/license-MPL--2.0-green.svg)](./LICENSE)\n\n# Rudra Framework\n\nA lightweight, transparent PHP framework built on the principles of simplicity and clarity.\n\n**~15 MB** · Lightweight Query Builder · No hidden dependencies · No magic · PHP 8.3 Attributes · Porto Architecture\n\n## Philosophy\n\nRudra follows the **KISS principle** — every tool is visible, every dependency is explicit, and every layer does exactly one thing. No \"magic\" happens behind the scenes: if you see it in the code, that's all there is.\n\n- **Transparency** — no hidden behavior, no implicit side effects\n- **Simplicity** — minimal surface area, easy to learn and extend\n- **Explicit over implicit** — dependencies are declared, not guessed\n- **Modern PHP** — built from the ground up on PHP 8.3+ features (attributes, typed constants, fibers)\n\n## Who is this for?\n\nRudra is built for developers who:\n\n- **Prefer explicit code over framework magic** — you want to see exactly what SQL is executed, what routes are registered, and what dependencies are injected\n- **Value cognitive clarity** — you need a framework that stays out of your way and doesn't require memorizing hidden conventions\n- **Work on small-to-medium projects** — you want structure and best practices without the overhead of enterprise-grade frameworks\n- **Want full control** — you believe that understanding your tools is more important than having hundreds of features out of the box\n\nIf you're looking for a batteries-included framework with built-in ORM, pre-configured queue workers, and ready-made broadcast drivers — Rudra is not for you.  \nIf you want a lightweight, transparent foundation with simple primitives that you can extend exactly as needed — you're in the right place.\n\n## 🚀 Getting started\n\n### Via Composer (stable)\n\n```bash\ncomposer create-project --prefer-dist rudra/framework newapp\ncd newapp\n# ✅ Secret keys are generated automatically\n```\n### Via Composer (dev)\n\n```bash\ncomposer create-project --prefer-dist --stability=dev rudra/framework newapp\ncd newapp\n# ✅ Secret keys are generated automatically\n```\n### Via Git + DDEV (full environment)\n\nThe fastest way to get a fully working local environment — containers, dependencies, SSL, and database included:\n\n```bash\ngit clone git@github.com:Jagepard/Rudra-Framework.git\ncd Rudra-Framework\nddev start  # Start containers, install deps, set up SSL \u0026 DB\nddev exec php rudra secret  # Generate secret keys for all environments\nddev launch # Open the site in your browser\n```\n#### 🔑 Secret Keys\n\nSecret keys are automatically generated during Composer installation for all environments (local, ddev, production).\nIf you need to regenerate them (e.g., after cloning the repository), simply run:\n\n```bash\nphp rudra secret\n```\n### ⚙️ Configuration\nFor web requests, Rudra automatically detects the environment in `index.php`:\n\n```php\n$env = match (true) {\n    getenv('IS_DDEV_PROJECT') === 'true' =\u003e 'ddev',\n    php_sapi_name() === 'cli-server' =\u003e 'local',\n    default  =\u003e 'production',\n};\n```\n#### Console Environment\nFor CLI commands (like ```php rudra migrate```), the framework cannot auto-detect the environment. Use app_env.php to specify it manually:\n```php\n\u003c?php\n// Do NOT commit this file to Git (.gitignore)\nreturn 'local'; // ← Set to: 'local', 'ddev', or 'production'\n```\nRudra uses environment-specific configuration files. The framework automatically loads the appropriate file based on your environment:\n\n| Environment | Config File |\n|-------------|-------------|\n| DDEV | config/setting.ddev.yml\n| Local development | config/setting.local.yml\n| Production | config/setting.production.yml\n\nThese files contain database credentials, container paths, debug settings, and other environment-specific values.\n\u003e💡 Tip: When adding new containers or settings during development, update config/setting.local.yml. For production deployment, copy the relevant sections to config/setting.production.yml.\n\n## Quick Start\n\nRun the built-in development server:\n\n```bash\nphp rudra serve\n```\n## 🚀 Creating Your First Page\n\nLet's create a simple `/hello/:name` page that greets the user. This example shows the full flow: container → controller → route → browser.\n\n### 1. Create a container\n\n```bash\nphp rudra make:container\n```\n\n```\nEnter container name: web\n```\n\nThis creates the `App\\Containers\\Web\\` namespace and registers it in `config/setting.local.yml`.\n\n### 2. Create a controller\n\n```bash\nphp rudra make:controller\n```\n\n```\nEnter controller name: hello\nEnter container: web\n```\n\nThis generates `App/Containers/Web/Controller/HelloController.php`.\n\n### 3. Define the route and action\n\nOpen the controller and add a method with the `#[Routing]` attribute:\n\n```php\n\u003c?php\n\nnamespace App\\Containers\\Web\\Controller;\n\nuse App\\Containers\\Web\\WebController;\nuse Rudra\\Router\\Attribute\\Routing;\nuse Rudra\\Container\\Facades\\Request;\n\nclass HelloController extends WebController\n{\n    #[Routing(url: 'hello/:name', method: 'GET')]\n    public function greet(string $name): void\n    {\n        echo \"\u003ch1\u003eHello, {$name}!\u003c/h1\u003e\";\n        echo \"\u003cp\u003eYour lucky number is: \" . random_int(1, 100) . \"\u003c/p\u003e\";\n    }\n}\n```\n\nThat's it. The route is registered automatically via the attribute — no separate `routes.php` needed.\n\n### 4. Open in browser\n\n```\nhttp://127.0.0.1:8000/hello/world\n```\n\nYou should see: **Hello, world! Your lucky number is: 42**\n\n---\n\n### Alternative: routes.php\n\nIf you prefer to keep routes separate from controllers, create (or edit) `App/Containers/Web/routes.php`:\n\n```php\n\u003c?php\n\nuse Rudra\\Router\\RouterFacade as Router;\nuse App\\Containers\\Web\\Controller\\HelloController;\n\nRouter::get('hello/:name', [HelloController::class, 'greet']);\n```\n\n\u003e ⚠️ When using `routes.php` for manual routing, make sure the file returns an empty array to disable automatic attribute-based route registration:\n\u003e ```php\n\u003e return [];\n\u003e ```\n\n### Alternative: closure route\n\nFor quick prototyping, you can even skip the controller entirely:\n\n```php\nRouter::get('hello/:name', function (string $name) {\n    echo \"Hello, {$name}!\";\n});\n```\nThen open [http://127.0.0.1:8000](http://127.0.0.1:8000) in your browser.\n\n## 📦 Ecosystem Components\n\nRudra is built on a **modular component architecture**. Each component is a standalone Composer package — use only what you need, or install everything via `rudra/framework`.\n\n| Component | Description | Package |\n|-----------|-------------|---------|\n| 📦 **[Container](https://github.com/Jagepard/Rudra-Container)** | DI container with 5 binding patterns (string, object, factory string, factory object, closure) | `rudra/container` |\n| 🧭 **[Router](https://github.com/Jagepard/Rudra-Router)** | HTTP router with PHP 8 attributes, middleware pipeline, REST resources, method spoofing | `rudra/router` |\n| 🎯 **[Controller](https://github.com/Jagepard/Rudra-Controller)** | MVC controller abstraction with lifecycle hooks (`init`, `before`, `after`) | `rudra/controller` |\n| 💾 **[Model](https://github.com/Jagepard/Rudra-Model)** | Lightweight Query Builder + Repository pattern (not a heavy ORM) | `rudra/model` |\n| 🔐 **[Auth](https://github.com/Jagepard/Rudra-Auth)** | Authentication, session management, RBAC, \"Remember Me\" | `rudra/auth` |\n| 🔗 **[OAuthClient](https://github.com/Jagepard/Rudra-OAuthClient)** | OAuth 2.0 client (Yandex, VK, custom providers) | `rudra/oauth-client` |\n| 🎧 **[EventDispatcher](https://github.com/Jagepard/Rudra-EventDispatcher)** | Events system with Listeners (pub/sub) and Observers (stateless notifications) | `rudra/event-dispatcher` |\n| ✅ **[Validation](https://github.com/Jagepard/Rudra-Validation)** | Fluent validation with CSRF, sanitization, custom rules, field aliases | `rudra/validation` |\n| 🖼️ **[View](https://github.com/Jagepard/Rudra-View)** | Template engine (PHP + Twig support) with file-based caching | `rudra/view` |\n| 🛡️ **[Exception](https://github.com/Jagepard/Rudra-Exception)** | HTTP error handling with custom error pages and DebugBar integration | `rudra/exception` |\n| 🔀 **[Redirect](https://github.com/Jagepard/Rudra-Redirect)** | HTTP redirection with status codes (1xx-5xx) | `rudra/redirect` |\n| 📄 **[Pagination](https://github.com/Jagepard/Rudra-Pagination)** | SQL OFFSET/LIMIT calculator with page links generator | `rudra/pagination` |\n| 📜 **[Annotation](https://github.com/Jagepard/Rudra-Annotation)** | Metadata reader for PHP 8 attributes + legacy docblock annotations | `rudra/annotation` |\n| 🖥️ **[Cli](https://github.com/Jagepard/Rudra-Cli)** | CLI component with command routing | `rudra/cli` |\n| 📝 **[Docs](https://github.com/Jagepard/Rudra-Documentation-Collector)** | Auto-generates Markdown API documentation from source code | `rudra/docs` |\n\n## 🔑 Key Features in Action\n\n### 🔐 Authentication \u0026 RBAC\n\n```php\nuse Rudra\\Auth\\AuthFacade as Auth;\n\n// Registration\n$user = [\n    \"email\"    =\u003e \"user@email.com\",\n    \"password\" =\u003e Auth::bcrypt(\"password\")\n];\n\n// Authentication (plain password vs hash from DB)\nAuth::authentication($user, \"password\", [\"admin/dashboard\", \"login\"]);\n\n// Authorization check (redirects to 'login' if not authenticated)\nif (!Auth::authorization(null, \"login\")) {\n    exit;\n}\n\n// Role-Based Access Control\nif (!Auth::roleBasedAccess($currentRole, \"editor\", \"error/403\")) {\n    exit;\n}\n```\n\n### 🎧 Event Dispatcher (Listeners + Observers)\n\n```php\nuse Rudra\\EventDispatcher\\EventDispatcherFacade as Dispatcher;\n\n// Listeners — pub/sub with payload\nDispatcher::addListener('user.registered', [UserListener::class, 'onRegister']);\nDispatcher::dispatch('user.registered', ['id' =\u003e 1, 'email' =\u003e '...']);\n\n// Observers — stateless notifications (no payload)\nDispatcher::attachObserver('before', [AuditObserver::class, 'onEvent']);\nDispatcher::notify('before');\n```\n\n### ✅ Fluent Validation\n\n```php\nuse Rudra\\Container\\Facades\\Request;\nuse Rudra\\Container\\Facades\\Session;\nuse Rudra\\Validation\\ValidationFacade as V;\n\n$fields    = Request::post()-\u003eall();\n$processed = [\n    'name'        =\u003e V::sanitize($fields ['name'])-\u003erequired()-\u003emin(3)-\u003emax(50)-\u003erun(),\n    'email'       =\u003e V::email($fields ['email'])-\u003erun(),\n    'age'         =\u003e V::sanitize($fields ['age'])-\u003einteger()-\u003ebetween(18, 100)-\u003erun(),\n    'description' =\u003e V::set($fields['description'])-\u003erun(), // without validation\n    'csrf'        =\u003e V::sanitize($fields['csrf'])-\u003ecsrf(Session::get('csrf_token'))-\u003erun(),\n];\n\nif (V::approve($processed)) {\n    $data = V::getValidated($processed, [\"csrf\", \"_method\"]);\n} else {\n    $errors = V::getErrors($processed);\n}\n```\n\n### 🧭 RESTful Resources\n\nRegisters standard CRUD routes with explicit plural and singular URL patterns. \nNo magic pluralization — you define exactly what the URLs look like.\n\n```php\n$router-\u003eresource('api/users', 'api/user', UserController::class);\n```\n\nThis creates the following routes:\n\n| Method | URL | Controller Method | Description |\n|--------|-----|-------------------|-------------|\n| GET    | api/users      | index  | List all users |\n| GET    | api/user/:id   | read   | Get single user |\n| POST   | api/users      | create | Create new user |\n| PUT    | api/user/:id   | update | Full update user |\n| PATCH  | api/user/:id   | update | Partial update user |\n| DELETE | api/user/:id   | delete | Delete user |\n\u003eThe default action names are [index, read, create, update, delete].\n### Custom Method Names\nYou can override the default action names by passing a custom array of 5 methods:\n\n```php\n$router-\u003eresource('api/posts', 'api/post', PostController::class, [\n    'actionIndex',   // GET    api/posts       — list all posts\n    'actionView',    // GET    api/post/:id    — get single post\n    'actionAdd',     // POST   api/posts       — create new post\n    'actionUpdate',  // PUT/PATCH api/post/:id — update post\n    'actionDrop'     // DELETE api/post/:id    — delete post\n]);\n```\n\u003eThe array order is fixed: [index, read, create, update, delete].\n\n### 🖼️ View with Caching\n\n```php\nuse Rudra\\View\\ViewFacade as View;\n\n// Cache-first strategy with fallback\necho View::cache(['mainpage', \"+1 day\"]) ?? View::render([\"layout\", \"mainpage\"], [\n    'content' =\u003e View::cache([\"page_{$slug}\", \"+1 day\"]) \n        ?? View::view([\"page\", \"page_{$slug}\"], ['foo' =\u003e 'bar']),\n]);\n\n// Or with helpers\ndata(['content' =\u003e cache(['mainpage']) ?? view(['index', 'mainpage'])]);\nrender('layout', data());\n```\n\n## 💾 Data Access Layer (Rudra-Model)\n\nRudra includes a lightweight, transparent data access layer — **not a heavy ORM**, but a simple Query Builder with Repository pattern.\n\n### Architecture: Entity → Model → Repository\n\nA predictable delegation chain with automatic fallback:\n- **Entity** — entry point, defines the table name\n- **Model** — business logic layer (optional)\n- **Repository** — data access layer (optional, falls back to base CRUD)\n\nIf you don't create a Model or Repository, the base Repository handles standard CRUD automatically.\n\n### Zero Boilerplate\n\n```php\nnamespace App\\Containers\\User\\Entity;\n\nuse Rudra\\Model\\Entity;\n\nclass User extends Entity\n{\n    public static ?string $table = 'users';\n}\n\n// Usage — no Model or Repository needed:\n$users = User::getAll();\n$user  = User::find(1);\nUser::create(['name' =\u003e 'John', 'email' =\u003e 'john@example.com']);\n```\n\n### Custom Repository Logic\n\n```php\nnamespace App\\Containers\\User\\Repository;\n\nuse Rudra\\Model\\Repository;\n\nclass UserRepository extends Repository\n{\n    public function findActiveUsers(): array\n    {\n        return $this-\u003eqBuilder(\"SELECT * FROM {$this-\u003etable} WHERE active = 1\");\n    }\n}\n\n// Automatically routed:\n$activeUsers = User::findActiveUsers();\n```\n\n### Fluent Query Builder\n\n```php\nuse Rudra\\Model\\QBFacade as QB;\n\n$query = QB::select('id, name, email')\n    -\u003efrom('users')\n    -\u003ewhere('status = :status')\n    -\u003eand('role = :role')\n    -\u003eorderBy('created_at DESC')\n    -\u003elimit(10)\n    -\u003eget();\n\n// Execute via Repository:\n$results = User::qBuilder($query, ['status' =\u003e 'active', 'role' =\u003e 'admin']);\n```\n\n### Schema Builder\n\n```php\nuse Rudra\\Model\\Schema;\n\nSchema::create('users', function ($table) {\n    $table-\u003einteger('id', '', true) // auto-increment\n          -\u003estring('name')\n          -\u003estring('email')\n          -\u003etext('bio', 'NULL')\n          -\u003ecreated_at()\n          -\u003eupdated_at()\n          -\u003epk('id');\n})-\u003eexecute();\n```\n\n### File-Based Caching\n\nSimple, reliable JSON file caching — no Redis/Memcached required:\n\n```php\n// Cache query results\n$users = User::cache(['getAll']);\n\n// Cache with TTL\n$posts = Post::cache(['findBy', ['category', 'news']], '+1 hour');\n\n// Auto-clears on create/update/delete\n```\n\n### Why Not a Heavy ORM?\n\n- **No magic** — no hidden queries, no lazy loading surprises\n- **No hidden dependencies** — direct PDO access when needed\n- **Predictable** — you see exactly what SQL is executed\n- **Fast** — no reflection overhead, no entity hydration complexity\n- **Simple** — if you know SQL, you know Rudra-Model\n\n## 🛠️ CLI Tools\n\nRudra ships with a rich set of CLI utilities following the Porto architecture. Run `php rudra help` to see the full list.\n\n### 🚀 Launch \u0026 Help\n\n| Command | Description |\n|---------|-------------|\n| `php rudra serve` | Start the built-in dev server (alias: `run`) |\n| `php rudra help` | List all available commands |\n\n### 🛠️ Generators (`make:*`)\n\n| Command | Description |\n|---------|-------------|\n| `php rudra make:container` | 📦 Scaffold a new Porto container |\n| `php rudra make:controller` | 🧭 Generate a controller class |\n| `php rudra make:contract` | 📜 Generate an interface (contract) |\n| `php rudra make:factory` | 🏭 Generate a factory class |\n| `php rudra make:listener` | 👂 Generate an event listener |\n| `php rudra make:middleware` | 🛡️ Generate a middleware class |\n| `php rudra make:migration` | 🗄️ Generate a database migration |\n| `php rudra make:model` | 🧱 Generate Entity + Repository pair |\n| `php rudra make:observer` | 👁️ Generate an event observer |\n| `php rudra make:seed` | 🌱 Generate a database seeder |\n| `php rudra make:docs` | 📝 Generate documentation from source |\n\n### 🗄️ Database\n\n| Command | Description |\n|---------|-------------|\n| `php rudra migrate` | 🛤️ Run pending migrations (with duplicate protection) |\n| `php rudra seed` | 🌾 Execute seeders (with duplicate protection) |\n\n### 🔍 Debug\n\n| Command | Description |\n|---------|-------------|\n| `php rudra debug:router` | 🗺️ List all registered routes |\n| `php rudra debug:router:container` | 🔍 List routes for a specific container |\n| `php rudra debug:listeners` | 🎧 List registered event listeners |\n| `php rudra debug:observers` | 🔭 List registered event observers |\n\n### 🔐 Security\n\n| Command | Description |\n|---------|-------------|\n| `php rudra bcrypt` | 🔐 Hash a password with bcrypt |\n| `php rudra secret` | 🔑 Generate a cryptographic secret (APP_KEY) |\n\n### 🧹 Maintenance \u0026 Utils\n\n| Command | Description |\n|---------|-------------|\n| `php rudra cache:clear` | 🧹 Clear application cache |\n| `php rudra convert:array-to-yml` | 🔄 Convert a PHP array config to YAML (alias: `to:yml`) |\n\n## Features\n\n- **PHP 8.3 Attributes** for routing and middleware — clean, declarative syntax\n- **Automatic Dependency Injection** with autowiring\n- **5 container binding patterns**: string, object, factory string, factory object, closure\n- **Event Dispatcher** with both Listeners and Observers\n- **File-based caching** — simple, reliable, no external dependencies\n- **Porto Architecture** — clear separation between Ship (shared) and Containers (modules)\n- **DebugBar integration** with custom collectors (Security, PDO, Config)\n- **Whoops** for beautiful error pages in development\n- **Twig support** — optional, via factory binding\n- **RESTful resources** — one line registers all CRUD routes\n- **Method spoofing** — PUT/PATCH/DELETE from POST forms via `_method`\n- **CSRF protection** built into validation and controllers\n\n## License\n\nThis project is licensed under the **Mozilla Public License 2.0 (MPL-2.0)** — a free, open-source license that:\n\n- ✅ Requires preservation of copyright and license notices\n- ✅ Allows commercial and non-commercial use\n- ✅ Requires that modifications to original files remain open under MPL-2.0\n- ✅ Permits combining with proprietary code in larger works\n\n📄 Full license text: [LICENSE](./LICENSE)  \n🌐 Official MPL-2.0 page: https://mozilla.org/MPL/2.0/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjagepard%2Frudra-framework","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjagepard%2Frudra-framework","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjagepard%2Frudra-framework/lists"}