Installation
Overview
WebBlocks CMS is distributed as a Composer package installed into a Laravel host application. The host application remains responsible for its bootstrap, environment, database, queues, mail, scheduler, deployment, backups, and public document root. Batched/daily email notifications and daily email summaries require the scheduler every minute; new sites enable these policies by default. Viewing saved messages and panel notifications does not require scheduling or outgoing mail.
Before provisioning a production server, review Hosting Requirements, qualify the intended workload using Hosting Capacity Validation, compare it with the explicitly provisional Hosting Capacity Results, and complete the Hosting Readiness Checklist. Those pages separate the base install contract from optional image, mail, scheduler, backup, and package-native update dependencies; the current partial measurements are not a production certification.
For a normal installation, start in a fresh or existing Laravel 12.55+ or Laravel 13 application with its application key and database configured. Install the package with Composer, then run the CMS installer.
An install is considered complete when the application has a working CMS baseline:
- an app key exists
- the database is reachable
- required tables exist
- core seed data exists
- the first active
super_adminexists - an install completion marker is stored in
system_settings
Install into a Laravel application
From the root of the Laravel host application, run:
composer require fklavyenet/webblocks-cms
php artisan webblocks:install --name="Admin User" --email="admin@example.com" --password="secret-password"
Then open /webadmin/login. This is the primary and supported installation path for CMS users. Cloning this repository does not create a standalone Laravel application.
Supported options:
--name=first super admin display name--email=first super admin email address--password=first super admin password--site-name=first site name; when omitted,WEBBLOCKS_CMS_DEFAULT_SITE_NAMEis used if configured, otherwise the normalizedAPP_URLhost is used--site-handle=default site handle--repair-partialrename empty partial CMS tables before fresh-install migrations--skip-starter-contentpublish an empty home page instead of the shipped starter page--forceoverwrite package-owned CMS assets or published config files when needed
What webblocks:install does:
- names the first site after the normalized
APP_URLhost while keeping its internal handledefault;www.is omitted from the name, meaningful subdomains are retained, and local or IP hosts fall back toDefault Site - publishes
config/webblocks-cms.phpwhen the host app does not already have it - removes the untouched fresh Laravel welcome route from
routes/web.phpwhen it is safe, with a timestamped backup first, so CMS public routes can serve/ - patches
app/Models/User.phpwithWebBlocks\Cms\Auth\Concerns\HasWebBlocksCmsAccess - creates a timestamped backup before modifying
User.php - skips patching when the trait is already present
- fails clearly if
User.phpis not a recognizableApp\Models\User extends Authenticatableclass - runs the package fresh-install migration path for clean consumer installs
- detects partial CMS schemas before running fresh-install migrations and reports existing CMS tables, row counts, related migration rows, and known foreign key conflicts
- repairs empty partial CMS schemas only when
--repair-partialis provided, by renaming empty CMS tables with a timestamped_before_cms_install_...suffix before continuing - refuses automatic repair when any partial CMS table contains rows
- skips rerunning that fresh schema when CMS tables already exist
- creates Laravel support tables without running host application migrations, currently covering CMS password reset tokens plus
sessions,cache, andcache_lockswhen those database-backed drivers are configured - does not run the host application's normal Laravel migration set as part of package install, so it avoids conflicts with the already-created CMS-compatible
userstable - prepares the
backupsfilesystem disk root used by Backup / Restore - installs package-owned CMS assets into
public/cms - creates
public/storagewhen it is missing and the environment allows it - seeds locales, sites, slot types, page layouts, and core block types idempotently
- seeds the complete WebBlocks UI icon catalog from the manifest shipped with the package, so icon fields work with no outbound network and no manual sync
- provisions the published home page served at
/, including its layout slots - fills that home page with the shipped starter content, unless it is turned off
- records the installed version and install completion marker in
system_settings - creates the first active
super_adminonly when one does not already exist
Package auth is Laravel-native and does not require Breeze, Jetstream, Laravel UI, or Fortify. After install, sign in at /webadmin/login when CMS package auth routes are active. CMS-owned auth views and admin guest redirects use package route names such as webblocks.auth.login and webblocks.auth.logout, so a host product can keep its own global login route, for example /quiztem/login, without stealing CMS form actions or /webadmin redirects.
For the current package-consumer installation model, the host application's App\Models\User remains the auth model and install-time patch target.
Partial Install Recovery
If webblocks:install stops after a failed or interrupted prior run, rerun it without repair first and read the partial-install diagnostic. Empty CMS tables can be moved aside explicitly:
php artisan webblocks:install --repair-partial --name="Admin User" --email="admin@example.com" --password="secret-password"
The repair mode only renames empty CMS-owned candidate tables. It does not drop tables, does not alter non-empty tables automatically, and does not assume CMS owns the host application.
Panel Notifications Without A Scheduler (CMS 1.96.0)
For site-operation managers, the admin header notification bell links to Dashboard → Panel notifications. The panel reads saved contact messages each time a panel page loads, even when email is disabled or the scheduler has never run. It shows unread messages and messages awaiting reply per accessible site, with links to the filtered contact inbox. Unread messages are included in the awaiting-reply count. The bell badge counts unread contact messages only; read messages awaiting reply and system warnings remain separate on the Dashboard. With no unread messages, the bell is hidden; the Dashboard notification panel remains available. The Actions icon opens the selected site’s inbox to review messages awaiting reply, which can include messages already read. Counts and links never include inaccessible sites, and the summary does not display visitor details.
Opening the panel does not mark messages read, send pending email, retry failed delivery or manufacture scheduler health. Reading a contact message reduces unread work but leaves it awaiting reply; marking it replied or archived removes it from this summary. Spam and quarantined messages remain in the moderation inbox rather than the pending-work count. This is shared inbox state, refreshed on page loads, not a personal notification history. Live Chat retains its own authorized panel indicator, independent of scheduled email.
Immediate-only email with daily summaries disabled also works without a scheduler, provided outbound mail is configured. Batched/daily email and daily email reminders still require background scheduling: logging into the CMS cannot guarantee delivery at the selected time when nobody visits the panel.
Scheduled Notifications And Scheduler Health
New sites from CMS 1.95.0 use ten-minute message batches and a daily pending-message summary by default. Before enabling these features in production, the server administrator or hosting provider must configure Laravel’s scheduler to run every minute. Updates register CMS jobs without silently installing a server cron entry. CMS 1.105.25 also offers the optional, explicitly confirmed CLI setup below. The person operating the CMS selects notification policy; the server administrator owns the background runtime.
Add one entry to the application user’s crontab or the equivalent hosting scheduled-task service:
* * * * * cd /path/to/laravel-app && /path/to/php artisan schedule:run >> /dev/null 2>&1
Replace both example paths with the actual Laravel host directory containing artisan and the appropriate CLI PHP executable. Web and CLI PHP must satisfy the CMS requirements. If this application already has a working Laravel scheduler, keep that entry; the new job joins the existing schedule. A permanent queue worker is not required by this synchronous notification implementation.
From CMS 1.105.25, open Cleanup → Retention and automation → Scheduler setup and verification, or the setup link in System Health. The read-only screen shows commands for this installation, actual heartbeat status and a refresh link. Verify the displayed CLI PHP path with your provider; if necessary configure WEBBLOCKS_CMS_SCHEDULER_PHP_BINARY and refresh application configuration. Herne is not required. Any hosting panel that supports an every-minute command can use the standard cron command above.
On a supported Unix host with CLI access, run as the operating-system account that owns artisan and can read the application and write its runtime directories, never root:
php artisan webblocks:scheduler:setup
php artisan webblocks:scheduler:setup --install
The first command only inspects. The second requires confirmation after reviewing cron, systemd and hosting-panel tasks; for a reviewed noninteractive installation use --install --yes. --json emits a sanitized result without prompting. The installer preserves existing crontab content, adds one marked every-minute entry, and reads it back. Existing/ambiguous scheduler entries, recent real activity, readable external definitions, unsupported shells, wrong accounts and access failures prevent installation. It cannot discover every provider-owned or unreadable scheduler definition: review these before confirming. If CLI/crontab access is unavailable, use the hosting panel or ask the provider to add the command. A CMS update cannot guarantee OS permissions on every hosting environment.
An installed cron entry remains unverified until the actual scheduled callback runs. Wait 1–2 minutes, refresh recorded activity and check the status command below. The setup screen reports heartbeat activity; the full health/status command also checks notification execution. Do not add another scheduler just because cleanup is waiting for its daily time. Updates preserve each installation’s saved cleanup policy and opt-in categories; review and save them separately.
Also configure a real outbound mail transport, the canonical HTTPS APP_URL, and a shared cache supporting atomic locks when multiple workers can process notifications. The existing-site upgrade preserves full/immediate notifications with daily reminders disabled; those notification settings do not require scheduling until changed.
CMS 1.95.1 adds recorded health to the Dashboard and Sites → Edit → Contact, and Live Chat 0.7.1 exposes it in its settings and plugin health. The site notification API includes scheduler_health. Check the registered tasks and then the recorded runtime evidence:
php artisan schedule:list
php artisan webblocks:scheduler:status --json
Users with System Health access review the full scheduler notice in Maintenance → System Health → Scheduled notifications; their Dashboard shows a compact health summary. Site-operation managers without that access retain the detailed Scheduler card on their Dashboard, even when all accessible sites use immediate-only notifications with daily summaries disabled. In that case the card is informational and explains that those notifications do not require scheduling. If any accessible site enables batching, daily delivery or daily summaries, unverified or delayed health raises the warning; inaccessible sites never influence the notice.
The job list confirms registration only. Running requires a recent scheduled heartbeat and a recent completed notification run. Not yet verified means no reliable execution evidence has been recorded. Delayed means a heartbeat or completed run is more than five minutes old. A processing failure or missing notification schema is shown separately. A current execution may briefly show In progress. The status command exits successfully only for verified running health; other states return a nonzero status.
The heartbeat is produced by an actual scheduled callback. Manually running php artisan webblocks:notifications:dispatch can process due mail but does not establish scheduler health. Health reads do not create a heartbeat. Evidence is stored in the CMS database and remains visible across web and CLI processes. Timestamps are returned in UTC; daily summary hours still follow each site’s timezone. No customer content, secrets or raw exception text enter this health record.
If scheduling is unverified or delayed while batches or daily summaries are enabled, the panel warns that notifications may remain pending and identifies the server administrator/provider as the setup owner. Ask that owner to inspect cron or the hosting scheduler, the application path, CLI PHP, process permissions and runtime errors. Then confirm a fresh heartbeat and completed notification run. These checks confirm recorded execution on this installation; they do not guarantee recipient inbox delivery or independently certify every server node.
Updating Existing Installations
Use Updates for the System Updates workflow, backups, and
compatibility requirements. Publisher installations older than 1.89.1
must first apply the 1.89.1 license-layout bridge before installing 1.89.2
or later. Check again after the bridge; newer clients perform a follow-up
check automatically. Composer installations can update directly through
Composer without this Publisher artifact bridge.
User documentation is maintained separately in the webblocks-cms-docs
repository under docs/; it is not installed with the CMS package. The
package retains resources/contracts/inventory.md as the runtime authoring
contract, also available through GET /webadmin/api/inventory. Public docs
and guides are publication targets, and no documentation synchronization
engine was introduced by the repository split.
Relational runtime migration in CMS 1.98.5
The package update adds relational storage for page layout and shared-slot references, staged-update and restore markers, source-sync metadata and managed slots, block application references, API token access lists, site notification policies and scheduler health. Existing values are copied in bounded batches; API payloads and export/import fields keep their existing structure.
Mapped values are read from SQL. Existing JSON fields remain temporary rollback compatibility copies and are synchronized on supported writes. Unmapped settings and full revision snapshots retain their existing storage format in this phase. Unknown historical fields, malformed values and unresolved references are preserved. The update migration is repeatable and its rollback does not delete the new data. If an older package writes those copies after a rollback, reconcile that drift before returning to the SQL-authoritative version.
Block and application settings migration in CMS 1.98.6
The next package update moves remaining Block settings and Embedded Application asset/support/schema lists into relational records. Core block fields have typed appearance, media, navigation and content schemas. Bindings, collection settings and application instance values have separate records; typed nodes preserve nested structure and historical/plugin extensions. Asset and enum lists keep order and duplicates, and setting definitions retain their types and defaults.
The migration reads one legacy payload at a time in bounded ID batches and is repeatable. Existing API, renderer, locale, export/import and full revision fields keep their compatible structures. SQL is authoritative; existing JSON columns remain synchronized rollback copies. An update rollback retains SQL data, so review any writes made by an older package before reapplying the new version. Full snapshot and other legacy content/runtime JSON are later migration work.
Remaining relational preparation in CMS 1.98.7
The package-native migration prepares page, slot and layout settings, block metadata, complete historical snapshots, transfer records, import continuation maps, recovery data, update receipts, icon lists and moderation reasons in SQL. Existing API names and structures remain compatible. Plugin lifecycle state and promotion plans now write SQL; old mutable files are retained until cutover. Preparation is idempotent and does not replace newer SQL plugin state on reruns.
The bridge retains old columns for an updater already executing the previous package. Keep the automatic full backup when installing the subsequent cutover: restoring older code alone cannot restore removed columns or data files. CMS full backups contain the database, public uploads and site-public files; retain the matching package and any required private plugin/local storage separately.
Final SQL cutover in CMS 1.98.8
The cutover removes the temporary fields and imported mutable state files after preparation/readback. SQL is the source for all CMS-owned persistent structures, including independent full snapshots. The existing API, signed package, immutable backup and export formats continue to use their established serialization. Publisher offers 1.98.7 first to earlier in-app clients; check again after that bridge to apply 1.98.8. Keep the full backup for a return to older code.
Legacy source-maintained installations
The browser wizard and manual CLI flows below apply only to historical source-maintained or maintenance-repository installations that already contain a complete Laravel host application. They are not alternatives for installing the current package repository by itself. New installations should use the Composer package flow above.
Browser Install Wizard
Use the browser wizard for a fresh install.
After the source code is present locally, start with:
composer install
cp .env.example .env
php artisan serve
Then open http://127.0.0.1:8000/install.
The wizard covers:
- environment readiness checks
- database configuration and connection validation
- core CMS installation
- first
super_admincreation - install locking after completion
Notes:
- the installer is for fresh installs
- if setup is incomplete, the wizard can be reopened and resumed safely
- after completion, install routes are locked and normal auth/admin flow takes over
- the installer writes the selected database configuration into
.env
Manual CLI Installation
Use the CLI flow when you prefer a standard Laravel setup path for a fresh install.
composer install
cp .env.example .env
php artisan key:generate
php artisan migrate
php artisan db:seed
php artisan storage:link
php artisan serve
Notes:
php artisan db:seedinstalls the core CMS catalogs, provisions the home page with its starter content, and records the current app version as the installed version for a fresh installphp artisan storage:linkis required if public file serving should usestorage/app/public- runtime directories under
storage/framework,storage/logs, andbootstrap/cacheare created automatically on first run - Backup / Restore stores archives on the
backupsfilesystem disk, defaulting tostorage/app/backups. The PHP runtime user should own that directory or share a deployment group with read/write access; avoid broad777modes.
Native Local Install
For a fresh Laravel project running with locally installed PHP and Composer:
composer require fklavyenet/webblocks-cms
php artisan webblocks:install --name="Admin User" --email="admin@example.com" --password="secret-password"
Then open:
- public site:
/ - admin login:
/webadmin/login - admin:
/webadmin
For development of an existing source-maintained Laravel installation:
composer install
cp .env.example .env
php artisan key:generate
Notes:
- trusted local development should use
.testdomains and HTTPS, withhttps://webblocks-cms.testas the canonical CMS development URL php artisan serveremains useful for quick CLI-only checks, but trusted browser workflows should use the native Nginx/PHP-FPM setup documented indocs/native-local-development.md- local contact form email notifications should use a local SMTP catcher or trusted SMTP test account; the usual local SMTP values depend on the installed tool
- Contact Form notification recipients resolve in this order: block-level
recipient_email, current site's default contact recipient,CONTACT_RECIPIENT_EMAIL, thenMAIL_FROM_ADDRESSas the last safe fallback - contact submissions are stored independently from notification delivery, so a public
Message sentresponse confirms storage success even if admin later shows notificationFailed,Skipped, orNot configured MAIL_MAILER=log,MAIL_MAILER=array, andMAIL_MAILER=nullare not real outbound delivery and are shown as not configured for Contact Message notification- Contact Form blocks render a hidden wrapper (shipped
wb-sr-onlyclass) withinert,aria-hidden="true", a renderer-generatedform_check_{token}field,tabindex="-1",autocomplete="off", and a form-bound signed timestamp; invalid proof or a filled check field produces the same generic success redirect without storing a Contact Message or attempting notification - submissions that pass signed proof and the generated check field are scored locally with content, exact and near-duplicate repetition, exact-IP, sender-address,
/24or/64network, form-burst, and learned site-reputation signals; allowed, quarantined, and spam remain durable admin classifications separate from notification state - protection requires no CAPTCHA or external service; cache keys use keyed hashes and the 30-day admin metrics contain aggregate decisions rather than submitted content
- when notification delivery fails, admins can inspect the saved message under
Admin -> Contact Messagesto see the compact failure state in the list and the stored failure detail on the message detail screen
Then open:
- public site:
https://webblocks-cms.test - admin:
https://webblocks-cms.test/webadmin - installer on a fresh install:
https://webblocks-cms.test/install
Complete the fresh install in the browser wizard after those setup steps are done.
Package development and contributing
Cloning the repository is not the normal installation path for application users.
Clone the repository only when developing or contributing to WebBlocks CMS itself:
git clone https://github.com/fklavyenet/webblocks-cms.git
cd webblocks-cms
composer install --no-interaction --prefer-dist
composer validate --strict
composer format:test
composer test
The repository is package source, not a deployable Laravel application. See the product contributing instructions and the package testing strategy for the development workflow.
Accessing the Install Wizard
- fresh installs automatically redirect to
/install - you can also open the wizard manually at
/install - you can open
/install/coreto jump directly to the core install step when earlier requirements are already satisfied - the wizard may advance steps automatically as requirements are completed
- opening
/and/installin multiple browser tabs can show different wizard steps; this is expected because the installer tracks progress and routes accordingly
First Super Admin Creation
The first super_admin is required for a completed install.
- in the browser wizard, create the first admin during the final setup step
- in the package-consumer CLI flow, provide
--name,--email, and--passwordtowebblocks:install - in a manual install, ensure at least one active
super_adminaccount exists before considering the CMS fully installed
super_admin is the install-level role that can access Users, sites, locales, settings, updates, backups, export/import, and all site content.
Starter Content
A fresh install publishes a home page at / and fills it with starter content: a brand lockup with the product mark beside the heading, a short feature grid, and a closing call to action. These are ordinary blocks, not a hard-coded welcome screen, so the first page a new admin opens in the editor is a working page they can rewrite, reorder, or delete.
The logo is imported into the site's own Media Library at install time and bound to the block like any other image, so it is served from the site's own origin and the operator can replace or delete it in the admin. It is never hot-linked from a remote host: that would make every public visitor issue a third-party request and tie the customer's home page to another host's uptime. An image that cannot be imported — read-only disk, missing file — leaves the block without media instead of failing the install.
Rules that make this safe to ship on every install path:
- starter content is written only into a page that has no blocks at all, so it can never overwrite existing content
- it is install-time only; System Update never adds or restores it
- a missing or unreadable blueprint is reported and skipped, never fatal to an install
- an unknown block type skips that block and its children instead of failing
Controls:
WEBBLOCKS_CMS_STARTER_CONTENT=true
WEBBLOCKS_CMS_STARTER_CONTENT_PATH=
WEBBLOCKS_CMS_SEND_POWERED_BY_HEADER=true
WEBBLOCKS_CMS_STARTER_CONTENT=falseinstalls an empty published home page.php artisan webblocks:install --skip-starter-contentdoes the same for a single run.WEBBLOCKS_CMS_STARTER_CONTENT_PATHpoints at a directory of your own blueprints when a product should ship its own starter page.WEBBLOCKS_CMS_SEND_POWERED_BY_HEADER=trueaddsX-Powered-By: WebBlocks CMSto CMS public page responses so technology catalogues can identify the product without learning its installed version. Set it tofalsewhen an installation policy requires suppressing product identification.
Adding Starter Content To An Existing Install
An install created before this feature keeps its empty home page: System Update never adds content. To fill it once:
php artisan webblocks:starter-content
On a multisite install, --site=handle picks the site; without it the primary site is used.
It provisions the site's page at / if it is missing, then writes the starter blocks only if that page has no blocks. On a site whose home page already has content it does nothing and reports why, and it never touches any other page. Running it twice is safe.
The command takes no class name and does not ask for production confirmation, because both of those break the runners this is for. A hosting panel's Artisan screen cannot answer db:seed's production prompt, and one has been seen to strip the backslashes out of a namespaced --class value, leaving Laravel to resolve Database\Seeders\WebBlocksCmsDatabaseSeedersStarterContentSeeder. The guarantee that would justify a confirmation prompt is structural here instead: starter content is only ever written into a page with no blocks.
The same work is reachable as a seeder, which is what db:seed runs on a fresh install:
php artisan db:seed --class="WebBlocks\Cms\Database\Seeders\StarterContentSeeder" --force
Blueprints are JSON files under the package's database/content/starter directory, using the webblocks.cms.starter-content.v1 schema and the same block vocabulary as the AI Page Building Guide. home.json is the shipped default; a locale-specific home.{locale}.json beside it wins for an install whose default locale matches. The directory's README.md documents the file format.
Common Setup Notes
- the installer is locked after completion
/webadminis the canonical CMS admin entry point- package-consumer installs may sign in through
/webadmin/login; co-installed apps may keep host-owned/login /webadmin/dashboardredirects to/webadmin- CMS assets stay under
/cms, for example/cms/css,/cms/js, and/cms/brand - package-owned
/webadmin/loginuses package Blade views, the WebBlocks UI guest auth shell, pinned WebBlocks UI assets,/cms/css/guest.css, and CMS product brand assets from/cms/brand, including normal, dark-surface, on-accent/inverse, and high-contrast favicon/browser-tab variants /cmsis reserved for CMS-owned static public assets and must not be used as a CMS admin route prefix, alias, or redirect/adminis not CMS-owned and must not be restored as a CMS admin route- new pages start in
draft - if install-level features such as revisions, backups, or updates report missing tables, run
php artisan migrate
The /webadmin and /cms split avoids the Nginx try_files collision where /cms/ can be resolved as the physical public/cms/ asset directory before Laravel handles a route. Do not solve admin access by adding a public/cms/index.php handoff; that front-controller bridge must stay absent from root and package public assets.
Email And Contact Form Readiness
Configure Laravel mail delivery before publishing a public contact page. A typical SMTP .env setup looks like:
MAIL_MAILER=smtp
MAIL_HOST=smtp.example.com
MAIL_PORT=587
MAIL_USERNAME=
MAIL_PASSWORD=
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=no-reply@example.com
MAIL_FROM_NAME="Site Name"
CONTACT_RECIPIENT_EMAIL=contact@example.com
MAIL_* controls Laravel mail delivery for Contact Form notification attempts. MAIL_FROM_ADDRESS is the safe fallback sender/from address and is also the last safe Contact Form recipient fallback when no more specific recipient is configured. CONTACT_RECIPIENT_EMAIL is optional and acts as an environment-level fallback recipient. Prefer configuring the site-level Contact recipient in Site -> Edit -> Contact when available, so contact routing lives with the site instead of only in .env.
After changing production or package-install .env mail settings, clear cached configuration if the install uses config caching:
php artisan optimize:clear
Contact Form notifications resolve recipients in this order:
- Contact Form block
recipient_email - Site default contact recipient from
Site -> Edit -> Contact .envCONTACT_RECIPIENT_EMAIL- safe
MAIL_FROM_ADDRESSfallback
Accepted real Contact Form submissions are stored before email notification is attempted. Notification failure does not mean the public form submission failed. Admins should check /webadmin/contact-messages for stored messages, notification status, and safe failure details. Public visitors should only see normal success or validation feedback, not mail diagnostics.
Sent means the CMS handed the notification to the configured mail transport without an exception; it does not guarantee inbox delivery. Skipped or Not configured means no real notification send was attempted.
Use the native contact_form block for contact pages. Do not replace it with Trusted HTML, raw <form> markup, or mailto: fallbacks. The CMS renderer generates the hidden anti-spam check field automatically; do not create it manually. The old website honeypot field is no longer the public contract.
Practical Contact Form smoke test:
- Publish or preview a page containing the native
contact_formblock. - Submit a test message with name, email, subject, and message.
- Open
/webadmin/contact-messages. - Confirm the message was stored.
- Review notification status.
- If email did not arrive, inspect the safe failure details and run mail diagnostics.
Diagnostic commands:
php artisan contact:mail-diagnose
php artisan contact:mail-diagnose --block=ID
php artisan contact:mail-diagnose --send-test=you@example.com
The diagnostic command must not print passwords, tokens, or mail secrets. Use --block=ID to inspect the recipient fallback chain for one Contact Form block. Use --send-test= only for a controlled SMTP send check to an intentional test address.
Post-Install Next Steps
- Sign in to
/webadmin. - Review your site and locale configuration.
- Configure site identity and domains.
- Configure Laravel mail settings or approved system mail settings.
- Configure a Contact Form recipient, preferably on
Site -> Edit -> Contact. - Run
php artisan contact:mail-diagnose. - Submit a test native Contact Form and confirm it stores a Contact Message.
- Review email notification status for that test message.
- Open the starter home page in the editor and make it your own.
- Create your first page.
- Add media, navigation, and blocks.
- Publish content through the editorial workflow.
Public Content Mount
The default integrated mode preserves root public URLs. To run beside a Laravel product, configure WEBBLOCKS_CMS_PUBLIC_MOUNT=wb before installation/deployment; public content, search, and sitemap then use /wb, while admin/API/assets/form endpoints retain their dedicated areas. Mounted installation keeps the host welcome route. This is an instance-wide config setting, not a panel or Site setting. Read Public Routing before enabling or changing it, especially for cache rebuilding, host catch-alls, robots ownership, and URL migration.