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

Atom Laravel Package

jiannius/atom

jiannius/atom is a Laravel/PHP package offering reusable components and utilities to streamline common development tasks. It aims to reduce boilerplate and integrate smoothly into Laravel applications, helping teams build features faster. Early-stage with limited public documentation.

View on GitHub
Deep Wiki
Context7

Getting Started

The earlier read of this package as "just a Blade component library" undersells it. The 3.38.0 release notes confirm atom also ships Artisan commands (atom:upgrade-check, atom:tiptap-migrate, atom:purge-editor-images, atom:upgrade), model traits (AtomComponent), and editor content casts (AsEditorContent, AsTiptapContent), with components rendered as <atom:…> tags rather than an <x-atom::…> namespace. Budget your first hour accordingly: commands and casts first, views second.

composer require jiannius/atom
php artisan list atom      # the real surface area: commands, not just components

First action is not a component swap — it's the read-only upgrade scan, because it tells you what your app already uses:

php artisan atom:upgrade-check

It writes nothing (unless you pass --output), so it's safe on a production checkout. Read the output before touching anything else; it names the files, the traits your AtomComponent models will need for v4, the <atom: tags in use, and which published atom views need re-checking.

Then look at:

  1. vendor/jiannius/atom/src/Console/Commands/ — the four commands above are the day-to-day workflow.
  2. vendor/jiannius/atom/src/Casts/ — AsEditorContent vs AsTiptapContent decides whether your content columns are still legacy format.
  3. v4 branch UPGRADE.md — atom:upgrade-check is generated from it, so it's the authoritative source when a finding is ambiguous.
  4. Published views/config — only relevant once the scan flags them.

First real use case: run atom:upgrade-check --json --output=storage/app/atom-upgrade.json, commit the JSON next to your upgrade ticket, and triage the findings by severity. That single artefact replaces most of the guesswork this assessment previously recommended.

Implementation Patterns

Treat atom:upgrade-check as the entry point for every upgrade, not a one-off. It runs read-only, supports --json, --output=, --path=, and --all, and every finding carries file:line, a severity (breaks at runtime / visual change / review), and whether atom:upgrade can fix it or only report it. The third column is the one that matters for planning — "report only" findings are manual work.

# CI gate: fail the build on runtime-breaking findings only
php artisan atom:upgrade-check --json --output=build/atom-upgrade.json

Filter on severity in your pipeline rather than eyeballing the console output; the human-readable report is for the ticket, the JSON is for the gate.

Scope the scan deliberately. On a large app the default run is noisy. Use --path=app/Models when you're chasing cast/trait issues, and --all only when you want the full picture:

php artisan atom:upgrade-check --path=app/Models            # trait/cast surface
php artisan atom:upgrade-check --all --output=atom-full.json

Editor content migration is now a four-stage workflow, not a command. The v2 migrate command is reversible, and you should use the reversibility:

php artisan atom:tiptap-migrate                    # dry run — writes nothing
php artisan atom:tiptap-migrate --compare          # dry run + JSONL original-vs-new review file
php artisan atom:tiptap-migrate --accept=12,48     # convert only the rows you reviewed
php artisan atom:tiptap-migrate --force            # convert all clean rows, unreviewed
php artisan atom:tiptap-migrate --status --for-v4  # gate the v4 upgrade on migration completeness

Every original is written to atom_editor_backups (created on first use), so --restore and --restore=12,48 revert byte for byte. Only prune once you're satisfied:

php artisan atom:tiptap-migrate --prune-backups --confirm-prune   # --confirm-prune for non-interactive

Prefer --accept=<ids> over --force in production. --force converts "clean rows" unreviewed, and "clean" is the command's judgement, not yours.

Switch the cast before migrating, not after. On 3.x, AsEditorContent columns can be migrated. The documented order is: change the cast to AsTiptapContent first, then fix any raw-HTML printing of the column that assumed the old cast's output, then migrate.

protected $casts = [
    'content' => AsTiptapContent::class,   // was AsEditorContent
];

Any view doing {!! $page->content !!} or {{ strip_tags($page->content) }} is the thing that breaks here — grep for raw output of the column before you run anything.

Deploy scripts need auditing, not just updating. The two behavioural changes in this release both bite unattended runs:

# WRONG after 3.38: silently does nothing in a deploy script
php artisan atom:tiptap-migrate

# RIGHT: explicit, but now can exit 1 and kill a `set -e` chain
php artisan atom:tiptap-migrate --force

If your deploy script runs under set -e, wrap the migration so an exit 1 alerts rather than aborts mid-deploy, or move it to a separately monitored step.

Component usage. Components are <atom:…> tags, not the <x-atom::…> form the previous assessment assumed:

<atom:button variant="primary" size="sm">Save changes</atom:button>

Confirm the registered prefix from the provider before writing templates — a wrong prefix produces "Unable to locate a class or view", which is not a helpful error. atom:upgrade-check also lists the <atom: tags in use, which is a faster inventory than grepping your templates.

Keep the agent-facing docs current. The scan checks whether the atom section of your CLAUDE.md / AGENTS.md is current, which means the package has an opinion about how AI assistants should be briefed on it. If you use either file, update that section as part of the upgrade — a stale section produces confidently wrong code from your assistant.

Wrap components in app-level components. Still the right call. A breaking change in atom becomes a one-file edit rather than a repo-wide grep:

{{-- resources/views/components/ui/button.blade.php --}}
@props(['variant' => 'primary'])
<atom:button {{ $attributes->merge(['variant' => $variant]) }}>
    {{ $slot }}
</atom:button>

Gotchas and Tips

atom:tiptap-migrate without --force is now a no-op. This is the highest-risk change in the release precisely because it's silent: a deploy script that previously converted rows now does nothing and reports success. Grep your deploy config, your CI workflows, and any Makefile/composer scripts for the bare command.

--force exiting 1 will fail set -e deploys. It exits non-zero "when a write failed or a refused value remains" — both of which are legitimate states in a partially-migrated dataset. Decide deliberately: either tolerate the exit (and alert on it) or pre-migrate out-of-band and remove the command from the deploy path entirely.

atom:purge-editor-images now reads every discovered model's connection. Because it inspects backup tables on each connection, a single unreachable secondary connection stops the whole run. Don't run it during a failover, and don't assume it's safe just because it's a cleanup command. Models with no editor column on an undefined connection are warned about and skipped rather than fatal, so read the warnings — a skip may mean the purge missed references.

The --compare JSONL file is content, not metadata. It contains original and converted editor payloads, which means user data, which means it is not a CI artefact. Keep it out of build output, out of shared storage, and delete it after review. The upgrade report has the same property — it quotes matching source lines, so treat --output files like source code for access-control purposes.

--force is not "do the migration", it's "trust the classifier". It converts clean rows unreviewed. Rows it refuses stay refused, which is why the exit code is non-zero rather than a clean success. If you see a partial run with exit 1, --status tells you what's left; --accept=<ids> is how you finish it after review.

Don't prune backups until --status --for-v4 is clean. --prune-backups deletes your only byte-for-byte route back. Gate it on the v4 status check and keep a database snapshot from before the migration as a second line of defence.

Upgrade to v4 is a separate project from 3.38.0. This release adds readiness tooling; it changes nothing in components, styles, JS, or traits. Use the breathing room to run atom:upgrade-check, migrate editor content, and clear the trait work — then take v4 with a report that's already small.

Trait work is the underestimated part. The scan lists the traits each AtomComponent model will need, per model. On an app with a dozen models that's a dozen edits and a dozen test runs; plan it as its own ticket rather than a line item in the upgrade.

Pin the version. Use an exact constraint ("jiannius/atom": "3.38.0") and read the diff before bumping. The migrate command's default-mode flip is exactly the kind of change that lands in a minor release and breaks a deploy, so treat every bump as reviewable.

Debugging resolution. When a tag "doesn't exist", confirm what's registered rather than guessing:

php artisan view:clear
grep -rn "Blade::" vendor/jiannius/atom/src
php artisan atom:upgrade-check --all --json | jq '.[] | select(.severity == "breaks at runtime")'

Extension points, in order of preference. 1) Wrap components in app-level components; 2) publish and override config; 3) publish and override individual views; 4) use --accept/--restore to stay inside the migration tooling rather than hand-editing cast columns; 5) fork. Stop at step 3 in almost all cases.

Upstream what you find. The readiness tooling is generated from a real UPGRADE.md, which suggests active maintenance — but any bug you hit is still likely unreported. A minimal reproduction (one model, one column, one command invocation) plus an issue is cheaper than owning a fork.

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.
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels
wazza/laravel-db-encryption
hokny/laravel-generator
vonsogt/backup
jengo/queues
jeremykenedy/laravel-observability
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums