NextChair
NextChair is a multi-tenant, white-label booking platform for barbershops. The application is being rebuilt as a conventional Laravel web application using PHP, MySQL, Blade, Tailwind CSS, Alpine.js, and Vite.
The audited Next.js implementation is preserved in legacy-nextjs
as the functional and visual migration reference. The Laravel application has
its own deployment-neutral Docker option at the repository root; files inside
legacy-nextjs are not used by it.
Local development
composer install
cp .env.example .env
php artisan key:generate
npm install
npm run build
php artisan serve
Configure the MySQL connection in .env before running migrations. The
application resolves a business only from the request hostname through the
business_domains table; it never guesses a tenant from the first business
in the database. For local multi-tenant work, map each configured hostname to
127.0.0.1 in /etc/hosts.
Platform and tenant setup
Migrations create schema only. They do not create a demo business or a
business owner. After migrating, open /install once and create the platform
administrator. That account can sign in at /manager/sign-in, create
businesses, edit their primary domains, and share the one-time owner setup
link generated during provisioning.
For an existing installation created before this platform/tenant split, the
recorded initialAdminUserId account is allowed to sign in once and is
promoted to the platform administrator. No other business owner can use that
upgrade path.
Business provisioning creates the tenant domain, settings, booking rules, opening hours, system roles, owner staff profile, and seven-day owner invitation in one transaction. The owner chooses a password through that invitation; platform administrators and business owners are separate account types.
If demo data is useful for local development, opt into the existing seeder explicitly:
NEXTCHAIR_SEED_DEMO=true php artisan db:seed
Docker deployment
The root compose.yaml runs Laravel with PHP 8.4 FPM, Nginx, MySQL 8,
the database-backed queue worker, and the scheduler. It does not include or
configure Caddy; an existing reverse proxy can forward traffic to Nginx on
127.0.0.1:8085.
First run:
cp .env.example .env
Set private values in .env, including:
APP_URL=http://localhost:8085
APP_KEY=
DB_HOST=db
DB_DATABASE=nextchair
DB_USERNAME=nextchair
DB_PASSWORD=replace-with-a-private-password
DB_ROOT_PASSWORD=replace-with-a-private-root-password
Then build and start the stack:
docker compose build
docker compose up -d
docker compose exec app php artisan key:generate
docker compose exec app php artisan migrate
Then visit http://localhost:8085/install to create the first platform
administrator. Do not run migrations or create tenants from container startup;
the tenant owner is provisioned manually from Manager.
Migrations are intentionally not run by container startup. To inspect the application logs:
docker compose logs -f app nginx queue scheduler db
The default host binding is 127.0.0.1:8085:80. Override it with
NEXTCHAIR_HTTP_BIND and NEXTCHAIR_HTTP_PORT in .env when needed. MySQL
has no published host port and is reachable only as db:3306 inside Compose.
Verification
php artisan test
npm run build