Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Cms Laravel Package

orchid/cms

Orchid is a Laravel package for rapidly building admin panels and CMS-style backends. It offers screens, flexible layouts, form fields, filters, and CRUD tooling, letting developers create rich, data-driven management interfaces with minimal boilerplate.

View on GitHub
Deep Wiki
Context7

Getting Started

Prerequisites. Laravel with orchid/platform already installed and working (admin user, config/platform.php, routes/platform.php, storage link). Press is a domain module on top of Orchid — it will not install usefully into a plain Blade, Filament, or Nova admin, and it adds no delivery layer of its own.

Minimal install sequence.

# 1. Read the actual composer.json constraints before committing
composer show orchid/platform
composer require orchidcommunity/press

# 2. Discover the provider name; don't guess it
grep -A5 '"autoload"' vendor/orchidcommunity/press/composer.json
ls vendor/orchidcommunity/press/src

Then:

  1. Register the service provider if it isn't auto-discovered — Laravel 11+: bootstrap/providers.php; Laravel 10-: config/app.php.
  2. Publish and run migrations: php artisan vendor:publish --provider="…PressServiceProvider" then php artisan migrate. Inspect the published migrations before running them — check foreign keys to users and any assumptions about the attachments table from orchid/platform.
  3. Create/confirm an admin: php artisan orchid:admin [email protected] password.
  4. Verify the screen mounts: log in and look for the Press menu group. Then php artisan route:list --path=platform to confirm the screen routes registered.

Where to look first, in this order:

Look at Why
vendor/…/Press/src/Providers/*ServiceProvider.php Defines menu(), permissions(), and often routes; this is the package's whole integration contract
vendor/…/Press/src/Screens/ Orchid Screen classes — query(), layout(), commandBar(); this is where you extend
database/migrations/ (published) The real content model; the schema is the source of truth
composer.json of the package Orchid/Laravel/PHP constraints and the last-touched date — the abandonment signal

First use case. Do a read-only spike: install into a throwaway app on your target Orchid version, create one post through the admin screen, attach one image, and render it manually from a closure route:

Route::get('/news/{post:slug}', fn ($post) => view('news.show', ['post' => $post]));

If the screen renders, the CRUD works, and the attachment URL resolves, you have the two facts that matter: it runs on your stack, and the model is queryable. If it needs patching before the first screen loads, stop and price an in-house module instead.

Implementation Patterns

Pattern 1 — fork before first commit. You are adopting code, not buying a product. Vendor it from day one:

"repositories": [{ "type": "vcs", "url": "[email protected]:yourorg/press.git" }],
"require": { "orchidcommunity/press": "dev-main#<pinned-sha>" }

Pin the Orchid major in the same composer.json and commit the lockfile. Keeping your diff against upstream small is the whole game — prefer adding your own screens over editing vendor screens.

Pattern 2 — extend by composing screens, not editing them. Add your own Orchid Screen that reuses the package model and appends fields:

class PostEditScreen extends Screen
{
    public $post;

    public function query(Post $post): iterable
    {
        return ['post' => $post->load('categories', 'attachment')];
    }

    public function layout(): iterable
    {
        return [
            Layout::rows([
                Input::make('post.title')->title('Title')->required(),
                Slug::make('post.slug')->from('post.title'),
                Markdown::make('post.body'),          // or TinyMCE via Orchid's HTML field
                Relation::make('post.categories.')
                    ->fromModel(Category::class, 'name')->multiple(),
                Input::make('post.published_at')->type('datetime-local'),
                Attach::make('post.attachment_id'),
            ]),
        ];
    }
}

Register it with Route::screen('press/posts/{post}/edit', PostEditScreen::class)->name('platform.press.posts.edit'); in routes/platform.php. Your screens survive Orchid upgrades far better than patched vendor screens.

Pattern 3 — add fields via migration, not model edits. The package won't expose a configurable model, so add columns in your migrations and swap in a subclass if you need casts/fillable:

Schema::table('press_posts', function (Blueprint $t) {
    $t->string('seo_title')->nullable();
    $t->string('canonical_url')->nullable();
    $t->index(['published_at', 'status']);
});

Override the model binding in your screen (query(Post $post) against your subclass via a Route::model binding) rather than editing vendor/.

Pattern 4 — build a thin delivery layer with explicit scopes. Press is admin-only; public routes are yours. Centralise published-state logic:

// App\Models\Post extends OrchidCommunity\Press\Models\Post
public function scopePublished($q)
{
    return $q->whereNotNull('published_at')->where('published_at', '<=', now());
}

Then cache at the controller level and invalidate with an observer rather than sprinkling Cache::forget everywhere:

static::saved(fn () => Cache::forget('press.index'));
static::deleted(fn () => Cache::forget('press.index'));

Pattern 5 — permissions and menu are provider-driven. permissions() and menu() in the package provider are the integration surface. After any change there, re-run your permission sync and re-check the role: Orchid permissions resolve at boot, and a missing permission manifests as a blank/403 screen, not an error message. Grant explicitly:

$admin->roles()->sync([Dashboard::modelClass(Role::class)::where('slug','admin')->value('id')]);

Pattern 6 — CI smoke test that actually catches breakage. The failure mode is framework drift, so test boot + render, not just models:

public function test_press_index_renders(): void
{
    $this->actingAs(User::factory()->create())
        ->get(route('platform.press.posts'))
        ->assertOk();
}

Run it against the pinned matrix (Orchid major × Laravel × PHP) on every bump. This single test is your upgrade tripwire.

Pattern 7 — seed for local dev. Add a factory for the package model in your app (database/factories) so you can populate a hundred posts and see how the list screen, pagination, and filters behave at realistic volume — not with the three rows a spike creates.

Gotchas and Tips

  • Version alignment is the actual risk, not code quality. Orchid's Screen and field APIs have broken across majors, and a zero-adoption package won't have tracked them. Before anything else, run the install against your exact Orchid major. "Composer resolves" ≠ "screens render."
  • Provider auto-discovery is not guaranteed. If the menu is missing, check bootstrap/providers.php / config/app.php before debugging Orchid. This is the single most common first-install failure.
  • Menu invisible after wiring = cache or permission. Run php artisan optimize:clear first, then verify the user's role has the package's permissions. Orchid fails silently here.
  • Migrations may assume the users table and Orchid's attachments table exist. Run Orchid's migrations first; if you see foreign-key errors, the published migration ordering is off — rename the timestamp in your fork.
  • Attachments need the storage link. php artisan orchid:link (or storage:link), and confirm which disk Orchid's Attachment config points at. If the package hard-codes public, plan a fork-level change rather than fighting it in config.
  • Rich text is untrusted input in the highest-privilege surface of the app. Sanitise on render (HTMLPurifier or similar) and never trust that the admin-only authoring surface makes stored HTML safe for outbound pages.
  • No public routes by default. Don't assume a frontend, sitemap, or SEO fields exist. Budget for slugs (unique, case-insensitive on MySQL by default — be deliberate), canonicals, and meta as your own work.
  • Slug collisions. Add a unique index and generate with a suffix loop; two posts titled "Launch" will otherwise break a {post:slug} route.
  • Watch N+1 on list screens. The index query typically hydrates author/category relations per row. Add ->with() in the screen's query(); Orchid gives you no automatic eager-loading.
  • Debugging a screen: dump() inside query() is faster than log-diving; if the screen 500s before rendering, check storage/logs/laravel.log for a field-DSL TypeError — that's usually API drift, not your code.
  • Extension points to prefer: your own screens, your own migrations, your own model subclass, Orchid's Layout/Field composition. Avoid: overriding package screens globally via container bindings, or editing vendor files you'll have to re-apply on every pull.
  • Record the ownership decision in the repo, not in chat. Add a MAINTAINERS.md next to the fork pinning the Orchid major and naming who absorbs upgrade work. Zero stars and zero dependents means no upstream fix will arrive on any timeline you can plan against — "are we prepared to maintain this?" is the question that decides adoption, not "does it work?"
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
abbasudo/artisan-route
mirvan/ippanel
ignibyte/aic-framework
glavweb/data-schema-bundle
glavweb/datagrid-bundle
tacticmedia/scim-server
uni-method/frame
neika-ai/sdk
adachsoft/php-code-style
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package