PHPackages                             bayuasrori/ultramod - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. bayuasrori/ultramod

ActiveProject

bayuasrori/ultramod
===================

A code-first modular application platform for Laravel. Install apps, extend them without forking, keep writing normal Laravel.

v1.0.0(today)03↑2900%MITPHPPHP ^8.3

Since Aug 25Pushed todayCompare

[ Source](https://github.com/bayuasrori/ultramod)[ Packagist](https://packagist.org/packages/bayuasrori/ultramod)[ Docs](https://github.com/bayuasrori/ultramod)[ RSS](/packages/bayuasrori-ultramod/feed)WikiDiscussions main Synced today

READMEChangelogDependencies (10)Versions (2)Used By (0)

Ultramod
========

[](#ultramod)

**A code-first modular application platform for Laravel.**

Install apps. Extend them without forking. Keep writing normal Laravel.

[![Laravel](https://camo.githubusercontent.com/58d0fca600c8e5a6f10f0d64e6a67ea1e95bb90cd34f298f11564c0e03b73a59/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c61726176656c2d31332e782d4646324432303f7374796c653d666c61742d737175617265266c6f676f3d6c61726176656c)](https://laravel.com)[![PHP](https://camo.githubusercontent.com/b62a93fb4f213eea83a8e52bb4c5461696e4a6b91d7452ce2487abfd70659c7b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048502d382e322532422d3737374242343f7374796c653d666c61742d737175617265266c6f676f3d706870)](https://php.net)![Tests](https://camo.githubusercontent.com/b6d17092da46a06258ff1d1826a1eff0b4c0dc20904770bcc3b8d5b395d7679f/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f74657374732d383925323070617373696e672d627269676874677265656e3f7374796c653d666c61742d737175617265)![License](https://camo.githubusercontent.com/ac049ef4e7a0b7196b09add6ac2d4f180e544c0ac779c2b2ac2fd2723a209579/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d626c75653f7374796c653d666c61742d737175617265)

*"Apps are code. The platform provides infrastructure. Applications provide behavior. Apps should be extensible without being forked."*

---

Why Ultramod?
-------------

[](#why-ultramod)

Every Laravel project rebuilds the same things: auth, roles, settings, audit logs, file handling, a dashboard, a navigation menu. Ultramod ships all of that as **platform capabilities** — and gives you a module system where applications are regular Laravel code living in `apps/`, independently installed, enabled and removed.

**The one thing you must see:** an app can extend another app *without touching its source code*. Upgrade the base app; the extension keeps working. That is the whole point of this project.

```
Platform
   │
   ├── Core Capabilities ── Identity · Roles & Permissions · Settings
   │                          Files · Audit Log · Extension Slots · Menus
   │
   ├── Applications ──────── Notes · Kanban · Calendar · Bookmarks · AI Assistant
   │
   └── Extensions ────────── Notes Status (extends Notes — zero fork)

```

It's just Laravel
-----------------

[](#its-just-laravel)

No DSL. No visual builder. No schema builder. No magic abstraction layer.

An Ultramod app contains the things you already know:

```
apps/notes/
├── platform.json                    ← app manifest (id, version, permissions, deps)
├── src/
│   ├── NotesServiceProvider.php     ← registers routes, views, migrations
│   ├── Http/Controllers/            ← plain controllers
│   ├── Http/Requests/               ← form requests
│   ├── Models/                      ← Eloquent models
│   └── Events/                      ← extension points
├── routes/web.php
├── resources/views/
├── database/migrations/
└── tests/

```

Open any app and you will think: *"this is just Laravel."* That is deliberate.

Start a project
---------------

[](#start-a-project)

```
composer create-project bayuasrori/ultramod my-app
cd my-app && php artisan serve
```

That is the whole install. `create-project` generates the app key, creates `database/database.sqlite`, runs the migrations, seeds the admin account and scans `apps/` — so the platform is up on the first run.

> Not on Packagist yet? Point Composer straight at the repository:
>
> ```
> composer create-project bayuasrori/ultramod my-app \
>   --repository='{"type":"vcs","url":"https://github.com/bayuasrori/ultramod"}'
> ```

Log in at `http://localhost:8000` with the seeded admin:

EmailPassword`admin@example.com``password`The first user to self-register on a fresh install automatically becomes the super admin.

A new project starts with every bundled app **discovered but not installed** — the launcher is empty on purpose. Install what you actually want:

```
php artisan platform:app:install notes && php artisan platform:app:enable notes
```

...or do it from **Apps** in the navbar.

Prefer a different database? Set `DB_CONNECTION` in `.env` before the first `php artisan migrate --seed`.

### Working on Ultramod itself

[](#working-on-ultramod-itself)

```
git clone https://github.com/bayuasrori/ultramod.git && cd ultramod
composer setup      # install, .env, key, migrate, npm install, npm run build
php artisan serve
```

Meet the starter apps
---------------------

[](#meet-the-starter-apps)

Six working applications ship in the box — not skeletons, real features:

AppWhat you get**Notes**Markdown notes, tags, search, attachments, revision history + restore**Kanban**Boards, columns, drag-and-drop tasks, priority, due dates, assignees, tags**Calendar**Month grid, events, all-day, locations, attendees, reminders**Bookmarks**Collections, tags, favorites, search, async metadata/favicon fetching (queued)**AI Assistant**Conversations, chat UI, OpenAI-compatible + Ollama, per-app settings**Notes Status**The showcase extension — see belowEnable what you need, ignore the rest:

```
php artisan platform:app:discover
php artisan platform:app:install notes
php artisan platform:app:enable notes
```

The showcase: Notes + Notes Status
----------------------------------

[](#the-showcase-notes--notes-status)

This is the architectural proof the platform is built around.

`notes-status` is a **separate package** that adds a status workflow (Draft → Review → Published → Archived) to Notes. It owns its own tables (`note_statuses`, `note_status_assignments`), defines its own permissions, and injects its UI into Notes pages — **without changing a single line of Notes code.**

```
Notes 1.0  ──listens──▶  Notes Status 1.0
   ↑ publishes                consumes
   NoteCreated                events + UI slots
   NoteUpdated                owns its own tables
   NoteDeleted                survives Notes upgrades

```

Try the full lifecycle yourself:

```
php artisan platform:app:install notes && php artisan platform:app:enable notes
php artisan platform:app:install notes-status && php artisan platform:app:enable notes-status
```

- Create a note → it automatically gets a **Draft** badge and a status dropdown.
- Disable `notes-status` → the status UI vanishes. Notes keeps working, data intact.
- Re-enable it → status returns instantly.
- Try `php artisan platform:app:disable notes` while the extension is enabled → rejected: *"Cannot disable Notes because Notes Status depends on it."*
- Upgrade Notes 1.0 → 1.1 → Notes Status doesn't need a single change.

### How extensions plug in

[](#how-extensions-plug-in)

Four small, intentional mechanisms — all Laravel-native:

MechanismHow**Events**Apps dispatch `NoteCreated`, `NoteUpdated`, …; extensions listen. The app never knows who's listening.**UI slots**Apps render `@extensionslot('note.metadata', ['note' => $note])`; extensions register views for that slot. Generic — no app names hardcoded.**Permissions**Extensions declare `notes-status.view` etc. in their manifest; the platform registers gates automatically.**Menus**Any enabled app can contribute nav entries via `MenuProvider`.Build your own app in 60 seconds
--------------------------------

[](#build-your-own-app-in-60-seconds)

```
php artisan platform:make-app weather
```

Scaffolds a working skeleton under `apps/weather/` — service provider, controller, route, view, migration folder, manifest, Composer autoload entry — then install &amp; enable it from the dashboard or CLI.

Want full CRUD? Use the **scaffolder in the web UI** (`/platform/apps/create`): enter a table name and columns, and Ultramod generates migration, model (fillable + casts), controller, form request with validation, resource routes and Bootstrap index/form views. Generated code is ordinary Laravel — edit it freely.

```
App name:  inventory
Table:     products
Columns:   id  (big integer · primary key · auto increment — always generated)
           name:string · price:decimal · active:boolean   ← add as many as you like
                ↓ generate
Migration · Product model · Controller · StoreProductRequest · routes · views

```

Column types are the common ones only: `string`, `text`, `integer`, `float`, `decimal`, `boolean`, `date`, `datetime`. `id`, `created_at` and `updated_at`are generated for every table and cannot be declared by hand.

Core capabilities
-----------------

[](#core-capabilities)

Infrastructure every app consumes — no app rebuilds these:

CapabilityWhat it provides**Identity &amp; Auth**Login/register/logout (rate-limited), login history, profile, password change**Roles &amp; Permissions**Roles UI, per-app permission catalogues, dynamic gates, super-admin bypass. Apps just declare `notes.create` and call `$user->can('notes.create')`**Settings**`SettingsManager` — platform-wide and per-app key/value settings with cache**Files**`FileManager` — upload/download/delete with metadata; morph attachments to any app model**Audit log**`AuditLogger` — actor, action, target, metadata for every meaningful event**App registry**Discovery, lifecycle, version constraint checks, dependency graphAll admin pages (users, roles, apps) are Bootstrap, responsive, and permission-gated.

App lifecycle
-------------

[](#app-lifecycle)

```
discovered ──install──▶ installed ──enable──▶ enabled
     ▲                     │  ▲                  │
     └────── uninstall ◀── disabled ◀──disable───┘

```

```
php artisan platform:app:list          # all apps + status
php artisan platform:app:discover      # scan apps/ for new manifests
php artisan platform:app:install notes # run migrations, register permissions
php artisan platform:app:enable notes  # routes/views/listeners go live
php artisan platform:app:update notes  # new version? runs new migrations only
php artisan platform:app:disable notes # out of the runtime, data kept
php artisan platform:app:uninstall notes
```

### Upgrading an app

[](#upgrading-an-app)

Bump the version in `platform.json`, ship the new code, and the dashboard shows `1.0.0 → 1.1.0 · upgrade available` next to the app with an **Upgrade** button. Clicking it opens the plan — pending migrations, upgrade steps, permission changes, apps that have to come along — and confirming runs the whole thing:

```
pre steps (oldest version first) → schema migrations → post steps → permissions → version bump

```

Data migrations that belong to one version live next to the app, and are returned the way a Laravel migration is returned — no autoload entry needed:

```
apps/notes/upgrades/
├── 1.1.0/
│   ├── PreUpgrade.php    ← runs before the schema changes
│   └── PostUpgrade.php   ← runs after; backfill new columns here
└── 1.2.0/
    └── PostUpgrade.php

```

```
