A comprehensive Human Resource Information System (HRIS) built with Laravel, Inertia.js, React, and TypeScript. This open-source project helps businesses streamline their HR operations, and while it is used by BeautyWorld, it is available for anyone to use and contribute to.
A public instance runs so you can try the application without installing anything:
| URL | https://hris.programinglive.com |
admin@beautyhris.com |
|
| Password | password |
Both seeded accounts (admin@beautyhris.com and test@example.com) use the password password and hold the administrator role.
This instance is a demo. It is wiped and reseeded periodically, and the credentials above are intentionally public so anyone can explore the app. Do not enter real personal data. If you deploy your own copy, change the passwords.
The demo exists so people can click through the app. It shares a small server with other sites, 2 vCPU / 8 GB, no scaling, and nothing about it is tuned for load.
- It is not a production service. No SLA, no backups you should rely on, no capacity planning. Pages may return 502 when the shared PHP-FPM pool is busy with another site. That is the expected behaviour of a demo on a shared box, not a bug in this application.
- Do not report 502 as a bug. If a page loads when you retry a few seconds
later, the app is fine and the server was busy. A real regression shows up as
a 500 with a stack trace in
storage/logs/laravel.log. - It is not a benchmark. Load-testing this host will degrade every other site on it.
- Capacity will not be raised for the demo. If you need reliability, run your own instance: see docs/deployment.md.
If you are evaluating whether pages work, the two signals worth trusting are:
| Signal | Meaning |
|---|---|
500 + entry in laravel.log |
a real defect worth reporting |
502 |
the shared pool was busy; retry |
200 / 302 |
working as intended |
HRIS Project is a modern human resource management system designed to help businesses streamline their HR operations. The platform provides tools for managing employees, company structure, attendance, and more, all within a user-friendly interface.
-
Organization Management
- Create and manage companies, branches, departments, divisions, sub-divisions, positions, and position levels
- Import branch data using templates
- Manage multiple brands
- Organize company structure hierarchically
- Company registration for new tenants
-
Employee Management
- Comprehensive employee database with detailed records
- Import employee data in bulk from Excel/CSV
- View and manage employee users
- Support for multiple roles per user
- Associate employees with multiple brands
- Assign work schedules and work shifts
-
User Management
- Role-based access control
- Multiple roles per user
- Multiple brands per user
- Multiple work schedules per user
- One work shift per day
-
Modern Interface
- Built with React and Inertia.js
- Responsive design for desktop and mobile
- Intuitive navigation
| Layer | Technology |
|---|---|
| Backend | Laravel 12, PHP 8.3+ |
| Frontend | React 19, TypeScript, Inertia.js, Vite, Tailwind CSS |
| Database | SQLite (development), PostgreSQL or MySQL (production) |
| Queue & scheduler | Laravel queue (database driver) + schedule:run cron |
- PHP 8.3 or higher, with the usual Laravel extensions
- Composer 2
- Node.js 20+ and npm
- SQLite for development, or MySQL/PostgreSQL for production
- Clone the repository
git clone https://github.com/programinglive/hris.git
cd hris- Install PHP dependencies
composer install- Install JavaScript dependencies
The lockfile carries a React 19 / @tinymce/tinymce-react@6 peer conflict, so npm ci needs the flag:
npm ci --legacy-peer-deps- Environment
cp .env.example .env
php artisan key:generate- Configure the database
Development (SQLite) — database/database.sqlite must exist:
DB_CONNECTION=sqliteProduction (PostgreSQL example):
DB_CONNECTION=pgsql
DB_HOST=127.0.0.1
DB_PORT=5432
DB_DATABASE=pghris_db
DB_USERNAME=pghris_user
DB_PASSWORD=secretFor production also set:
APP_ENV=production
APP_DEBUG=false
APP_URL=https://your-domain.example
SESSION_DRIVER=database
QUEUE_CONNECTION=database
CACHE_STORE=database- Schema and demo data
php artisan migrate
php artisan db:seed # optional: creates the demo accounts belowSeeding creates admin@beautyhris.com and test@example.com, password password, role administrator, plus 8 sample companies and the base organization structure (branches, departments, divisions, positions, levels, roles, working calendars).
- Build the frontend
npm run build- Run it
php artisan serve # http://localhost:8000
npm run dev # only when editing frontend assetsFull instructions live in docs/deployment.md. Two things catch people out:
-
Queue worker. With
QUEUE_CONNECTION=database, nothing happens without a worker. Runphp artisan queue:workunder supervisor or systemd; a sample config is indeploy/supervisor/hris-worker.conf. -
Nginx behind a TLS-terminating proxy. If your load balancer ends TLS and forwards over HTTP, the vhost must pass the original scheme to PHP:
fastcgi_param HTTPS $http_x_forwarded_proto;
Without it Laravel emits
http://asset URLs, the browser blocks them as mixed content, and the page renders blank with no visible error. A ready vhost is indeploy/nginx/hris.programinglive.com.conf.
Schema history and the one irreversible step (a column rename) are documented in docs/migration-notes.md.
Company registration is the multi-tenant entry point: it lets a new company sign up on an existing instance, create its own administrator, and keep its data separate from other tenants.
GET /register/companyrenders the registration formPOST /register/companycreates the company, its administrator, and the firstuser_detailsrow in one transaction
Note that the older multi-step wizard (validate-contact, verify-code, save-company-details) has been removed. Only the single-step form exists in the current code; the tests that covered the wizard are skipped with that reason.
GET /renders the landing pageGET /installation-wizardrenders the first-run setup pageGET /register-companyrenders the standalone registration page
php artisan testThe suite covers feature and unit tests for employees, organization structure, attendance, and imports.
tests/Concerns/SkipsViteWhenUnbuiltkeeps the suite meaningful on a fresh clone: the compiled frontend lives inpublic/build, which is git-ignored, so without it every Inertia response throws "Vite manifest not found". When the manifest is missing the trait swaps in Laravel's null Vite handler; oncenpm run buildhas run, the real instance is used.- A handful of tests are skipped deliberately, each with a reason in the test itself (mostly endpoints that no longer exist).
Issues and pull requests are welcome. Please run php artisan test before opening a PR.
Open-sourced software licensed under the MIT license.