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.