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

Focus Laravel Package

awcodes/focus

Focus adds a distraction-free mode to Filament panels, letting you hide the sidebar and topbar so you can concentrate on the task at hand. Toggle focus mode from the user menu or with a keyboard shortcut.

View on GitHub
Deep Wiki
Context7

Getting Started

Focus generates documentation screenshots and share cards for a Laravel package's Workbench app by driving Playwright/Chromium against it. It is a build-time asset generator, not a runtime dependency — install it in require-dev.

Prerequisites, in the order they bite:

  1. PHP 8.3+ — required by 1.0. This propagates from a dev dependency into every consumer's CI matrix, so check the floor before you commit.
  2. A bootable Workbench app — the package you're documenting must serve real pages (vendor/bin/testbench serve or the workbench equivalent) with seeded data.
  3. Node + Chromium on the machine that runs the CLI: npx playwright install chromium.
composer require --dev awcodes/focus
npx playwright install chromium
php vendor/bin/focus list        # confirm the binary and its commands

Where to look first. Read vendor/awcodes/focus/docs/ before anything else, and confirm the package identity while you're there: the public repo description describes an unrelated Filament "focus mode" UI plugin, while the release notes and docs describe this Playwright screenshot generator. Run composer show awcodes/focus and make sure you installed the generator.

The only surface you own. The public, semver-protected API is the manifest — ScreenshotSuite, Screenshot, Card — plus the enums, contracts, exceptions, the CLI (commands, options, exit codes), the output file names, and the card template contract. Everything under Runtime\*, Manifest\*, Console\*, Capture, and ScreenshotSuite::plan() is marked @internal and can change in any release.

First use case. Screenshot one page, then add one share card. Don't build the full manifest on day one:

// Illustrative manifest shape — confirm exact signatures against vendor/awcodes/focus/docs
use Awcodes\Focus\{ScreenshotSuite, Screenshot, Card};

final class DocsScreenshots extends ScreenshotSuite
{
    public function screenshots(): array
    {
        return [
            Screenshot::make('dashboard')
                ->url('/admin'),
        ];
    }

    public function cards(): array
    {
        return [
            Card::make('og-image'),
        ];
    }
}

Run it, open the output directory, and check the image is right, not merely present.

Implementation Patterns

One suite per feature area, one manifest per package. Keep the manifest plain PHP and boring — it is your exit ramp if the project stalls. A suite per resource/page group gives you targeted re-runs instead of full regeneration.

Treat output filenames as public identifiers. They are inside the semver promise, which means they are safe to hard-link from README.md and docs front matter:

![Dashboard](art/screenshots/dashboard.png)

Renaming a screenshot is therefore a breaking change for your docs, not a private refactor. Choose names once and leave them alone.

Cards are the extensible surface. The card template contract is public — supply your own Blade view for branding, and expect everything else about rendering to be internal. If your layout needs go beyond the template contract, that's the "build bespoke" case, not something to hack around.

Determinism is your job, not the tool's. Seed the Workbench database, avoid "3 minutes ago" timestamps and randomised IDs, disable animations and transitions, and pin the viewport. Every dynamic pixel is a diff you'll review forever.

CI as a pass/fail gate. The CLI's exit codes are part of 1.0's contract, which is what turns screenshot generation from a pre-release chore into a reviewable step:

- run: npx playwright install --with-deps chromium
- run: php vendor/bin/focus
- run: git diff --exit-code art/   # committed images: drift becomes a failing diff

Committed binaries make pixel drift a reviewable change; CI artifacts make it invisible until someone opens the docs. For anything customer-facing, commit the images.

Local loop. Re-run the single suite you're iterating on rather than the whole manifest — full regeneration is slow and produces noisy diffs while you're still adjusting framing.

Separate commits. When you bump Focus or regenerate, commit the dependency change apart from the regenerated images, so the pixel diff is auditable on its own.

Gotchas and Tips

Chromium is not pinned to a Focus release — this is the dominant risk and it is not fixable. A browser or OS font update changes pixels. Nominate one reference machine or container as the canonical render host, document that rule in the repo, and never promise cross-environment pixel determinism to anyone. A developer regenerating images on their laptop is how "why did 40 screenshots change?" tickets start.

The worst failure shape is a silent one. A missing font renders visibly wrong images that still exit 0. The exit code tells you the capture ran; it does not tell you the capture looks right. Keep a human glance at the rendered output in the review, and make sure your render image ships the expected fonts.

Never import from Runtime\*, Manifest\*, Console\*, Capture, or call plan(). 1.0 marked these @internal and they can change in any release — semver will not protect you. If you have direct usage, port it to the manifest API before the bump, not after. Grep for these namespaces across your packages; it's the only thing that turns a routine upgrade into a refactor.

Upgrading from 0.3 is a constraint bump plus PHP 8.3 plus one regeneration — 1.0 added no features. Use "^0.3|^1.0" only as a transitional widening with a named owner and an expiry date, since it leaves two rendering paths live simultaneously.

Auth and session state. Screenshots of admin or authenticated pages need the Workbench app to serve a logged-in session. Set that up as seeded fixture state rather than scripting a login through Playwright, otherwise every capture depends on DOM that isn't part of the contract.

Debugging an empty or wrong capture usually means the app isn't reachable, not that Focus failed. Confirm the Workbench server boots and responds at the URL before touching the manifest.

Keep the investment proportionate. Five stars, zero dependents, a single maintainer. Criticality is low — a failure blocks regenerating artwork, not shipping code — but that cuts both ways: budget internal onboarding notes rather than relying on upstream docs, and resist building elaborate manifest abstractions you'd have to unwind by hand. Because the manifest is plain PHP against a frozen public API, the switching cost is bounded to rewriting your suites and card templates.

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.
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource