Folio Office Management
Complete reference for installing, configuring and running Folio β the self-hosted HR, payroll and office management system built for multi-company organisations.
Live Demo
Try Folio before you buy at folio.cwfms.com. The demo resets automatically β feel free to explore.
| Role | Username | Password | Access |
|---|---|---|---|
| π Admin | admin | password123 | Full system |
| π Accountant | marcus.levy | accountant123 | Finance & reports |
| π₯ HR Office | derek.washington | hroffice123 | Payroll & employees |
| π§βπΌ Employee | kezia.campbell | employee123 | Personal finance |
Requirements
| Component | Requirement |
|---|---|
| PHP | 7.4 or higher (8.x recommended) |
| Extensions | pdo_sqlite, json, zip, mbstring |
| Database | SQLite via PDO β no MySQL or PostgreSQL required |
| Web Server | Apache / LiteSpeed / Nginx with PHP. Standard shared hosting supported. |
| Install Path | Must install at the domain root (e.g. office.yourdomain.com/). Subdirectory installs not supported. |
| Writable dirs | data/, uploads/, backups/, logs/ β set to 775 |
Installation
- Purchase and download
folio-system.zipfrom your customer account. - Upload and extract to the root of your domain β all files at
public_html/or equivalent, not in a subdirectory. - Set directory permissions:
chmod 775 data/ chmod 775 uploads/ chmod 775 backups/ chmod 775 logs/
- Visit
yourdomain.com/setup/install.phpβ the First-Run Setup wizard will appear. - Complete setup, then activate your license. See sections below.
Database initialisation error? Delete the entire data/ folder and try again. A partially-created database from a previous failed run will repeat the error on every visit.
cPanel: Use File Manager β right-click data/ β Change Permissions β set to 775.
First-Run Setup
On the first visit, Folio redirects to /setup/install.php. This screen appears once only.
- Organisation Name β appears in the header, reports, and exported documents.
- Default Theme β Dark or Light. Users can switch individually.
- Administrator Account β full name, email and password (min. 8 characters). Store securely.
- First Company β at least one required. More can be added after login.
- Click Complete Setup β schema migrations run and you are redirected to login.
The setup wizard permanently locks once an admin exists. To reset: delete data/app.db β this erases all data.
After setup, go to Admin β Settings β License to activate your license key.
Roles & Access Control
Folio has four fixed roles. Each user holds exactly one role assigned by the Administrator.
| Role | Access | Key Capabilities |
|---|---|---|
| Administrator | Full | All modules, user management, settings, backups, migrations |
| Accountant | Financial | Transactions, payroll, reports β scoped to assigned companies |
| HR | People ops | Employees, leave management, letters, payroll view β no financial access |
| Guest | View only | Read-only dashboard and transaction list |
Accountants are assigned to specific companies via Admin β Users β Assign Companies. They only see data for their assigned companies.
Dashboard
Each role lands on its default dashboard after login. The currency toggle in the header converts all amounts on the fly.
| Dashboard | Path | Default for |
|---|---|---|
| Main | /dashboard.php | Administrator |
| Accountant | /dashboards/accountant_dashboard.php | Accountant |
| Guest | /dashboards/guest_dashboard.php | Guest |
| HR | /hr/hr_main.php | HR |
Transactions
The core financial ledger at /transactions.php. Every income or expense movement is recorded here with a full audit trail.
| Field | Description |
|---|---|
| Date | When the transaction occurred |
| Company | Which entity this belongs to |
| Amount | Positive = income, negative = expense |
| Description | Free-text summary |
| Category | Revenue, OPEX, COGS, etc. with sub-category |
| Audit Trail | Every change logged with user ID, IP, timestamp |
The transaction list supports filtering by company, date range, amount, category and payment method. A running total displays in the selected currency at the bottom.
Companies
Manage legal entities at /admin/companies.php. Supports parentβchild structures (holding company β subsidiaries). Inactive companies preserve all data but are hidden from dropdowns and reports.
| Field | Description |
|---|---|
| Name | Full legal name of the entity |
| Code | Short identifier (e.g. ACME). Appears in exports and reports. |
| Short Code | Optional abbreviated code for tight layouts |
| Parent | Set for subsidiary relationships. Leave blank for top-level entities. |
| Active | Toggle visibility β inactive companies preserve all data |
Employees & HR
Employee Profiles
Full records at /admin/employees.php β name, position, department, salary, hire date, tax ID, and document uploads (IDs, contracts, certificates with category tags and expiry reminders).
Leave Management
- Leave Types β Configurable categories with default allocation days at
/hr/leave_types.php - Leave Requests β Submit and approve at
/hr/leave_requests.php. Approval auto-decrements balance. - Leave Balances β Per-employee, per-type, per-year with carry-over at
/hr/leave_balances.php - Leave Calendar β Visual calendar of all approved leave at
/hr/leave_calendar.php
HR Policies
Internal policy documents at /hr/policies.php. Default policies (Code of Conduct, Leave Policy, Remote Work) seeded at install time. Administrators and HR managers can add, edit, or delete policies.
Payroll
Process payroll at /payroll/payroll.php. Each entry covers one employee for one pay period.
| Field | Description |
|---|---|
| Gross Pay | Total before deductions |
| Deductions | Tax, NIS, pension β with optional line-item breakdown |
| Net Pay | Calculated automatically (gross β deductions) |
| Status | Unpaid / Paid β marking Paid creates an expense transaction automatically |
Exports
- PDF payslips at
/payroll/payslip_pdf.php?id=N - Payroll Report by company/year β
/payroll/payroll_report.php - Monthly summary and top earners β
/payroll/summary.php - Overview by pay period β
/payroll/overview.php
If you also use CWFMS, marking a payroll run as Paid can automatically post the expense there β no double entry. See CWFMS Integration.
Reports
The Reports Hub at /reports/hub.php consolidates all exports: payroll reports, employee lists (CSV + PDF), and financial summaries β all filterable by company.
Guest Export: Enable in Admin β Settings β Allow Guest Export to permit guest-role users to download CSV exports. Disabled by default.
Admin Panel
Accessible only to Administrators at /admin/settings.php.
| Setting | Description |
|---|---|
| Organisation Name | Appears in header, all reports, exports and letters |
| Logos | Light/dark, desktop/mobile variants (PNG, JPG, SVG) |
| Base Currency | Storage currency β change with care, existing values are not converted |
| Exchange Rates | Manual or auto-refreshed from exchangerate.host |
| Letter Footer | Default footer for generated letters β supports {COMPANY}, {DATE}, {USER} |
| Backups | Rolling backups at /admin/backup_logs.php with SHA-256 integrity checks |
| User Management | Create, edit, deactivate, assign companies β at /admin/users.php |
License Activation
Folio requires a license key purchased from cwfms.com. The key is validated against the license API and the result cached locally for 48 hours β no call is made on every page load.
First-Time Activation
- After setup, navigate to any page β the License Required screen appears if no key is cached.
- Enter your key in format
CWFMS-XXXX-XXXX-XXXX-XXXXfrom your purchase email or customer account. - Click Activate License. Folio contacts the license server and caches the result for 48 hours.
Managing via Admin
Go to Admin β Settings β License to view status, force re-validation, or clear the cache.
Firewall note: Folio must reach cwfms.com over HTTPS (port 443) for validation. The 48-hour cache means only one outbound request every two days.
CWFMS Integration
Folio can optionally push payroll expenses to CWFMS automatically when a payroll run is marked as paid β eliminating double entry between the two systems.
Completely optional. Both systems work independently. Nothing is sent unless explicitly configured. If CWFMS is unreachable, payroll mark-paid completes normally.
Setup
- In CWFMS: Settings β Integrations β enable API and copy the API key.
- In Folio: Admin β Settings β CWFMS Integration β enter the CWFMS base URL and API key.
- Click Test Connection to confirm.
- In the Company Mapping table, set the CWFMS Company ID for each Folio company (visible in the CWFMS URL when viewing a company).
The push log (last 10 attempts) is visible in Admin β Settings β CWFMS Integration so you can confirm pushes are landing correctly.
For CWFMS documentation see the CWFMS Docs β
Currency Conversion
All amounts are stored in their original currency. The header toggle cycles through USD β JMD β KYD β CAD β EUR β GBP and converts all displayed values on the fly β stored values are never modified.
Add currencies via Admin β Settings β Exchange Rates. To add a currency to the toggle cycle, edit the currencies array in includes/header.php.
Changing the base currency after data has been entered does not retroactively convert stored amounts β it only affects new entries.
Security & Best Practices
- Passwords hashed with
password_hash()/ bcrypt β never stored in plaintext - Sessions regenerate on login β prevents session fixation attacks
- CSRF tokens validated on every POST request
.htaccessblocksdata/,migrations/,logs/,backups/,setup/from web accessuploads/blocks PHP execution β uploaded files cannot run as scripts- All SQL via prepared statements β no string interpolation
- File uploads enforce an extension whitelist (PDF, DOC, XLS, JPG, PNG, CSV, ZIP)
Recommended Hardening
- Enable HTTPS β uncomment the redirect rule in
.htaccess - Restrict
/adminby IP on public servers - Use a strong admin password β 16+ characters, mixed case and symbols
- Run daily backups and store a copy off-server
Troubleshooting
| Issue | Resolution |
|---|---|
| Database initialisation error | Delete entire data/ folder, re-upload fresh. Set chmod 775 data/. Stale DB from a previous failed run is the most common cause. |
| Blank page after login | Check data/ is writable. Set APP_ENV=development temporarily to see PHP errors on screen. |
| License Required screen keeps appearing | Ensure server can reach cwfms.com on port 443. Verify the key has no extra spaces. Regenerate from your customer account if needed. |
| CWFMS push not working | Use Test Connection in Admin β CWFMS Integration. Check the push log for the error. Confirm CWFMS API is enabled in CWFMS Settings β Integrations. |
| CWFMS company not receiving payroll | Set the CWFMS Company ID in the Company Mapping table. The ID must match the folder name in the CWFMS URL. |
| Payroll auto-expense not created | Trigger trg_payroll_mark_paid is case-sensitive β value must be paid not Paid. Re-apply the master schema if the trigger is missing. |
| File uploads failing | Set chmod 775 uploads/. Check upload_max_filesize and post_max_size in PHP INI. |
| DB connection failed | pdo_sqlite extension not enabled. Check phpinfo() and enable in php.ini, then restart PHP-FPM. |
| Currency toggle does nothing | Check browser console (F12) for JS errors. Confirm exchange_rates in Admin β Settings is valid JSON. |
| 403 on /setup/install.php | Confirm .htaccess has the allow rule for install.php before the block rule for setup/. |
Changelog
v1.0.0 β Initial Release
- First standalone release β fully de-branded
- Single consolidated schema (
migrate_master_schema.php) - First-run setup wizard
- License gate with 48-hour local cache β SQLite 3.x compatible
- Optional CWFMS payroll push integration
- Upload extension whitelist and PHP execution block in
uploads/ - Self-healing download fallback in CWShop
Also See
Folio and CWFMS are complementary systems β Folio manages your people, CWFMS manages your money.