Installation
Add Atlas to a Laravel or Radicle application, wire up Vite and Tailwind, and render your first component.
Atlas installs like any Composer package, with one wrinkle: it is published to Webreact's own registry rather than Packagist, and its component styles ship as source CSS that your application's Tailwind build compiles. Get those two things right and everything else follows.
Requirements
- PHP 8.4 or newer
- Laravel 10, 11, 12 or 13 — or Acorn inside a Radicle site
- Tailwind CSS v4 with Vite
- Node 22 or newer for the asset build
Add the registry
Atlas lives on Webreact's Satis registry:
composer config repositories.webreact-satis composer https://satis.webreact.io/
Reads from the registry currently work without credentials. If that changes, add
an auth.json in the project root — and keep it out of version control:
{
"http-basic": {
"satis.webreact.io": {
"username": "your-username",
"password": "your-token"
}
}
}
Require the package
composer require webreact/atlas:dev-stable
The service provider is discovered automatically under both Laravel and Acorn,
so there is nothing to register by hand. Components are anonymous Blade
components in the atlas namespace, which means they are available immediately:
<x-atlas::button>Click me</x-atlas::button>
Import the stylesheets
Atlas ships its CSS inside the Composer package, so you import it by its path in
vendor/ — there is no npm package to install. Your application's CSS file
imports Tailwind and then Atlas:
@import 'tailwindcss'; @import '../../vendor/webreact/atlas/dist/atlas.css';
Adjust the number of ../ segments if your stylesheet does not live in
resources/css/. Atlas CSS is flattened but not compiled: it still holds
@apply, @theme and @source, so it passes through your own Tailwind build,
which is what makes token overrides and utility classes work. Its @source
directive already tells Tailwind to scan Atlas Blade templates, so you do not
need to add one yourself.
dist/atlas.css is two files in one: dist/atlas.core.css holds the component
styles and dist/atlas.theme.css holds the default token values. To bring your
own tokens from scratch instead of starting from Atlas defaults, import the
core on its own and follow it with your theme:
@import 'tailwindcss'; @import '../../vendor/webreact/atlas/dist/atlas.core.css'; @import './themes/corporate.css'; /* every token — see the theming guide */
Add the JavaScript
Several components need JavaScript: the carousel, the accordion, tabs and the hamburger. Import Atlas in your application's JS entry point:
import { Atlas } from '../../vendor/webreact/atlas/dist/atlas.js'
Atlas.start()
If you do not need to register anything of your own on Alpine, you can skip the
import and add @atlasScripts to your layout instead — see
Without Vite.
Atlas owns the Alpine instance by default — it imports Alpine, registers the
collapse plugin, wires up its component behaviours, and starts Alpine when
you call Atlas.start(). If your application bundles Alpine separately, read
JavaScript & assets before importing — the load order needs
care.
Prevent a flash of wrong theme
Atlas manages dark/light mode and theme switching through JavaScript. Because
the JS bundle loads after the initial paint, a visitor who chose dark mode or a
custom theme would see a brief flash of the default. Two directives fix that —
add them in <head>, before your Vite tags:
<head>
@atlasAppearance()
@atlasTheme()
@vite(['resources/css/app.css', 'resources/js/app.js'])
</head>
Each one is a tiny inline script that reads the stored preference from
localStorage and applies it to <html> before anything renders. They are
harmless when no preference has been stored yet, so you can include them from
the start and forget about them.
Without Vite
Applications that do not use Vite can serve Atlas pre-built assets through Blade directives:
<head>
@atlasStyles
@atlasAppearance()
@atlasTheme()
</head>
<body>
...
@atlasScripts
</body>
@atlasStyles links Atlas compiled CSS. @atlasScripts loads the JavaScript
bundle — it picks the right variant automatically (ES module, CSP-safe or UMD).
Both are served by Laravel routes under /atlas/*, the way Livewire serves its
JavaScript, until you publish them as static files.
Publish the configuration
Optional. Publish the config only when you need to change the default appearance mode, theme, CSP-safe setting or asset base URL:
php artisan atlas:config
Under Radicle or another Acorn host, run the same thing through Acorn:
wp acorn atlas:config
The configuration offers four settings:
| Key | Default | Purpose |
| --- | --- | --- |
| appearance | system | Default dark/light mode: system, light or dark |
| theme | null | Default data-theme value; null uses the base theme |
| csp_safe | false | Serve an Alpine build that avoids eval() |
| assets.base_url | null | Make the asset directives' URLs absolute (string or closure) |
Verify
Render a couple of components and load the page:
<x-atlas::heading :level="2" size="h3">Hello Atlas</x-atlas::heading> <x-atlas::button>Click me</x-atlas::button>
If the button renders but looks unstyled, the source CSS import or the @source
directive is missing. If it renders styled but a carousel does not slide, the
JavaScript import is missing or Atlas has not been started.
Serving assets as static files
This applies when you use @atlasScripts or @atlasStyles; a Vite build
bundles Atlas itself. By default those directives point at Laravel routes, so
every asset costs a PHP request. To let the web server serve the files directly,
publish them — the same idea as livewire:publish --assets:
php artisan atlas:publish --assets
Under Radicle or another Acorn host, run it through Acorn:
wp acorn atlas:publish --assets
The built JavaScript and the compiled CSS are copied to public/vendor/atlas,
and the directives switch to those copies on their own. Every URL carries the
file's content hash, and a copy that no longer matches the installed package is
ignored in favour of the route, so a forgotten republish never serves an old
runtime.
Republish them from Composer, following your host's convention for published assets.
Laravel commits published assets and republishes them on composer update,
next to the laravel-assets line a new app already has:
"post-update-cmd": [
"@php artisan vendor:publish --tag=atlas:assets --ansi --force"
]
Radicle and other Acorn hosts keep the copies out of git (add
/public/vendor/atlas to .gitignore) and republish on every install, so the
composer install a deploy runs brings them up to date. Add the line after the
entries already there — the package has to be discovered before its publish tag
exists:
"post-autoload-dump": [
"Roots\\Acorn\\ComposerScripts::postAutoloadDump",
"@php acorn vendor:publish --tag=atlas:assets --ansi --force"
]
If a Laravel app keeps public/vendor out of git instead, post-update-cmd
never runs on the server, because a deploy only runs composer install. Put the
Atlas line in post-autoload-dump after package:discover, as Acorn hosts do.
The published URLs are root-relative (/vendor/atlas/…). If your public/
directory is not the web root — a Sage theme inside Bedrock, say — set
assets.base_url to the URL that does point at it.
Serving through the routes behind NGINX
If you do not publish, the assets come from /atlas/*. On a WordPress host
these paths can be intercepted before they reach PHP, so let them through:
# Atlas asset delivery
location ^~ /atlas/ {
try_files $uri /index.php?$args;
}
On a multisite install where the site lives under a subdirectory, set
assets.base_url in the published config so the directives emit absolute
URLs.