Skip to content

A new application

innoboxrr/laravel-setup turns a fresh Laravel 13 application into the ecosystem's base app:

  • A public site editable from the admin panel: home, join, contact, privacy notice and terms, with a complete sample site.
  • Authentication through innoboxrr/laravel-auth: registration, login, password reset, email verification and impersonation for administrators.
  • An admin panel whose menu builds itself, with notifications, a profile with avatar and password, a site editor, and links to the logs and the .env editor.
  • Users generated by LaraPack, with the same architecture as any model you add later.

Installation is split in two on purpose: app:setup writes the files and app:install installs. In between you can review exactly what changed with git diff.

Before you start, check the requirements.

1. Create the Laravel application

bash
laravel new my-app
cd my-app

Or with Composer:

bash
composer create-project laravel/laravel my-app
cd my-app

Configure the database in .env. If the installer didn't create a repository, create one now so step 5 shows exactly what changed:

bash
git init
git add -A
git commit -m "Fresh Laravel"

2. Set APP_URL

Put the address you will open the app with in .env, port included:

dotenv
# with composer run dev or php artisan serve
APP_URL=http://127.0.0.1:8000

# with a Laragon host
APP_URL=http://my-app.test

Why it matters

The admin panel calls the API with the session cookie, and Sanctum only accepts it from the domains in SANCTUM_STATEFUL_DOMAINS: by default localhost, 127.0.0.1:8000 and the APP_URL host, among others. From any other address, login succeeds but every admin table answers 401 and sends you back to login. See Requirements.

3. Install laravel-setup

bash
composer require --dev innoboxrr/laravel-setup

4. Configure with app:setup

bash
php artisan app:setup
bash
php artisan app:setup --react

app:setup only runs on an application that looks fresh: resources/views/welcome.blade.php must exist, and laraimport.json, resources/vue/app and resources/react/app must not. Otherwise it refuses. --force overrides this, but think about what it replaces first.

It installs nothing. It does seven things:

StepWhat it does
Composer dependenciesWrites the ecosystem packages to composer.json, with LaraPack in require-dev. Removes lab404/laravel-impersonate, which laravel-auth replaces.
EnvironmentWrites the keys in the table below to .env and .env.example.
AdministratorsAdds admins to config/auth.php, read from ADMIN_EMAILS.
BackendCopies bootstrap/app.php, bootstrap/providers.php, routes/web.php, AppServiceProvider, the admin middleware, the .env editor config, a migration adding payload and soft deletes to users, SiteOptionsSeeder and laraimport.json.
InterfaceCopies package.json, vite.config.js, resources/views/app.blade.php, resources/<ui>/app/** and a placeholder resources/<ui>/routes.json.
Routes for the frontendWrites config/routes-to-json.php so route:json exports to resources/<ui>/routes.json.
Users, with LaraPackDeletes app/Models/User.php, generates the user from laraimport.json with larapack:import, creates the RouteServiceProvider and EventServiceProvider, and copies a UserPolicy that lets each user view and edit their own account.

If LaraPack rejects anything, app:setup fails and prints LaraPack's output.

What it replaces and what it deletes

  • Replaces bootstrap/app.php, bootstrap/providers.php, routes/web.php, app/Providers/AppServiceProvider.php and package.json.
  • Deletes resources/views/welcome.blade.php, resources/js, resources/css and app/Models/User.php.

That's why it only runs on a new application.

Environment variables it writes

These are always written, even if they already had a value:

KeyValue
APP_LOCALEes
APP_FALLBACK_LOCALEen
APP_FAKER_LOCALEes_MX
SESSION_DRIVERdatabase

The interface ships in Spanish because of APP_LOCALE=es. Change it to en if you want English.

These are only added when missing:

KeyValuePurpose
ADMIN_EMAILSemptyWho administers the app.
LARAVEL_UPLOADS_DISKpublicWhere uploads such as the avatar are stored.
LARAVEL_OPTIONS_EXPORT_DISKlocallaravel-options exports.
LARAVEL_AUDIT_EXPORT_DISKlocallaravel-audit exports.
VITE_APP_NAME${APP_NAME}
VITE_GOOGLE_LOGIN, VITE_FACEBOOK_LOGIN, VITE_MICROSOFT_LOGINfalseNo interface reads them yet: see Common problems.

5. Review and name the administrator

bash
git status
git diff

Then put your email in ADMIN_EMAILS in .env. It takes several, comma-separated, and is case-insensitive:

dotenv
ADMIN_EMAILS=you@example.com,someone@example.com

This is what isAdmin() on the generated user answers: policies let that user through, the admin middleware lets them in, and they can impersonate other users.

6. Install with app:install

bash
php artisan app:install

Each step runs in its own process, because the providers of freshly installed packages only exist for an artisan that boots again. In this order:

  1. composer update --no-interaction. It is update, not install: it changes composer.lock.
  2. php artisan vendor:publish --tag=sanctum-migrations
  3. php artisan notifications:install
  4. php artisan migrate --force
  5. php artisan db:seed --class=Database\Seeders\SiteOptionsSeeder --force
  6. php artisan storage:link
  7. php artisan route:json
  8. npm install
  9. npm run build

If a step fails, it stops and tells you which one.

OptionWhat it does
--pretendPrints the steps without running them.
--without-buildSkips npm install and npm run build.
--composer=composerThe Composer executable. A .phar is run with the same PHP as artisan.
--npm=npmThe npm executable.

On Windows, if the composer on your PATH runs an old PHP:

bash
php artisan app:install --composer=C:/path/to/composer.phar

7. Start it

bash
composer run dev

This is Laravel's own development script: it starts the server on http://127.0.0.1:8000 and Vite, among other processes. If Laragon serves the app, npm run dev is enough, or the npm run build that app:install already ran.

8. Log in as administrator

  1. Open /auth/register and sign up with an email listed in ADMIN_EMAILS. The password needs at least 8 characters.
  2. Go to /admin.

You will see:

  • Home, with one card per menu entry.
  • The Administration group, for administrators only: Users, Site (the public site editor), Logs (/log-viewer) and Environment (/env-editor), the last two in a new tab.
  • The notification bell, dark mode, and the user menu with your profile.

With APP_LOCALE=es, those labels appear in Spanish.

The public site lives at /, with the sample content from SiteOptionsSeeder.

All at once: app:init

If you don't need to review between steps, app:init runs app:setup and app:install back to back:

bash
php artisan app:init
bash
php artisan app:init --react
Argument or optionWhat it does
domain (optional)When done, runs configure:domain with that domain. Read the warning below.
--reactReact interface.
--forceConfigure even if the app doesn't look fresh.
--without-buildDon't install or build the interface.

Set ADMIN_EMAILS first

app:setup only adds ADMIN_EMAILS when it's missing. If you already wrote it in .env before app:init, it's kept, and you can register as administrator as soon as it finishes.

The domain argument only works with Laragon, with caveats

configure:domain is meant for Windows with Laragon installed at C:\laragon, a path written into the code. It adds the domain to the hosts file, asking for administrator rights, and writes an Nginx config that only accepts connections from 127.0.0.1 and allows outdated TLS protocols. It sets APP_URL to https://<domain> and SESSION_DOMAIN to .<domain>, and it does not restart Nginx: it only reminds you to.

If Laragon lives on another drive, or you don't use Laragon, create the domain with your own tooling and set APP_URL by hand.

What ends up in the application

WhereWhatOwner
resources/<ui>/app/Site, auth, admin panel, state and frontend routesYours once installed
resources/<ui>/index.js, resources/<ui>/src/The generated modulesLaraPack's: regenerated
laraimport.jsonThe user declaration and whatever you addYours
database/seeders/SiteOptionsSeeder.phpThe sample siteYours
app/Http/Middleware/EnsureUserIsAdmin.phpThe admin middlewareYours
config/auth.phpadminsWho administers, from ADMIN_EMAILSYours
.larapack/manifest.jsonWhat LaraPack generated, with hashesCommit it

Vue or React

Both interfaces are the same application: same routes, same screens, same site JSON, same backend calls. What differs is where things live:

VueReact
Entry pointresources/vue/app/main.jsresources/react/app/main.jsx
resources/<ui>/app/config.jsOnly adminOnly, with route namesadminOnly with route ids, plus adminBase, adminTools, notificationsInterval, sitePages and userUpdateRoute
StatePiniaZustand

For a generated module, a route's name (Vue) and id (React) are the same string, for example AdminUsers. More in With Vue and With React.

Common problems

Every admin table answers 401 and bounces to login. APP_URL doesn't match the address you browse, by host or by port. If you set SANCTUM_STATEFUL_DOMAINS, check it too.

"You signed in, but the session was not kept. Check the session and Sanctum domains." Login succeeded and the cookie never arrived. It is almost always SESSION_DOMAIN or SANCTUM_STATEFUL_DOMAINS.

Two applications log each other out. They share cookies on 127.0.0.1 even on different ports. Open one on localhost.

I don't see the Administration group. Your email isn't in ADMIN_EMAILS, or the config is cached: php artisan config:clear.

Model names show up untranslated. By design: LaraPack can't know what your model is called in Spanish, so it leaves the translation empty in resources/<ui>/src/locales/es.json and the English key shows. Translate it there or in resources/<ui>/app/lang/es.json.

There are no Google, Facebook or Microsoft buttons. app:setup writes VITE_GOOGLE_LOGIN, VITE_FACEBOOK_LOGIN and VITE_MICROSOFT_LOGIN, but neither interface reads them: social login is not wired into the base app. The backend does support it in laravel-auth.

Some packages are installed with no screen. innoboxrr/laravel-audit, innoboxrr/aws-file-manager, algolia/scout-extended and google/recaptcha are installed, but the base app has no interface or configuration for them.

The .env editor is enabled

The base app enables /env-editor for administrators (ENV_EDITOR_ENABLED, default true). From there you can read and change .env, secrets included. If you don't want it in production:

dotenv
ENV_EDITOR_ENABLED=false

More cases in Troubleshooting.

Next step

Your first model: declare a model, generate it and watch it appear in the menu.