StaffOS is a full-stack staff management platform for small and medium sized teams. It is built with Next.js 16, Prisma ORM, and PostgreSQL, and is designed to be deployed with a cloud hosted database. The application covers the full employee lifecycle from registration and onboarding through daily attendance and task tracking, leave management, payroll configuration, and performance reporting.
All features are gated behind a role based access system with three roles: Admin, Manager, and Staff. Each role sees a tailored interface and can only reach the API endpoints appropriate to their level of access.
Employee Management handles the full lifecycle of a staff member's account. New users register and go through an email verification step before an admin approves their account. Admins and managers can view and edit employee profiles, assign departments and supervisors, upload documents, record work history entries such as promotions and role changes, and generate performance reports by period.
Task Management lets admins and managers create tasks with a title, description, priority level, deadline, and assignee. Staff see only their own assigned tasks. Any user with access to a task can leave comments and attach files. Tasks move through Pending, In Progress, Completed, and Cancelled statuses.
Attendance Tracking gives admins and managers a daily log for each employee with five status options: Present, Remote, Late, Half Day, and Absent. Clock in and clock out times are optional and the system calculates hours worked automatically. Staff can view their own monthly history but cannot create or edit records.
Leave Management allows any user to submit a leave request with a type, date range, and optional reason. The system calculates working days automatically, excluding weekends. Admins and managers review pending requests and approve or reject them with an optional note. Approving a request that covers today automatically sets the employee status to On Leave.
Payroll is one of five optional modules that admins can enable or disable per-feature from the Settings page (the others are Attendance, Leave, Messages, and Reports - Payroll is just the one that ships disabled by default). When enabled it appears in the navigation for all users. It stores a provider name, currency, and pay day, and calculates the next upcoming pay date. It is designed as the configuration layer for a future connection to an external payroll service.
Messaging provides direct conversations between any two users, with a live-filtering search box and relative, calendar-aware timestamps ("Just now", "2h ago", "Yesterday"). Receiving a message triggers an email notification if the recipient has that preference enabled, plus an in-app toast and sound if they're active elsewhere in StaffOS at the time (unless they've set Do Not Disturb).
Presence and Status shows a live colored dot on every user's avatar throughout the app: green for online, amber for away (auto-detected after 10 minutes of inactivity, or set manually), red for Do Not Disturb (mutes in-app notifications), gray for offline. Clicking your own avatar in the sidebar opens a status picker to set Away or Do Not Disturb manually - picking either locks it in place regardless of activity, the same way Discord's status picker works, until you pick something else.
Profile Pictures let every user upload a photo from Settings, automatically resized and cropped in the browser before upload. Falls back to colored initials when no photo is set, consistently across the whole app.
Quick Search in the top bar searches staff and tasks live as you type, with results grouped by type and a click straight through to the relevant page.
Reporting and Exports let admins and managers export staff lists and task summaries as Excel or PDF files, with filters for department and date range.
Announcements allow admins and managers to send a broadcast email to all active staff who have the announcements preference enabled. Each send is recorded in the audit log with a recipient count.
Weekly Digest is a scheduled email sent every Monday morning containing each user's task summary for the week: completed, in progress, pending, overdue, and unread message count.
Audit Logs record every significant action in the system including approvals, role changes, task operations, setting changes, and exports. Admins and managers can browse the full log with timestamps and before-and-after data.
Two-Factor Authentication is available to all users via any TOTP app such as Google Authenticator or Authy. Enabling it requires scanning a QR code and confirming with a six-digit code. Disabling it requires the current code to confirm.
| Layer | Choice |
|---|---|
| Framework | Next.js 16 with the App Router |
| Language | TypeScript |
| Styling | Tailwind CSS with CSS custom properties |
| ORM | Prisma v5 |
| Database | PostgreSQL |
| Authentication | JWT tokens stored in HTTP-only cookies |
| Gmail via Nodemailer SMTP | |
| Two-factor auth | TOTP via otplib with QR code generation |
| Deployment | Vercel with Vercel Cron for scheduled jobs |
| Role | What They Can Do |
|---|---|
| Admin | Everything. Manages users, approves registrations, controls system settings, views audit logs, runs backups, and can perform any action available to lower roles. |
| Manager | Creates and assigns tasks, views and edits staff profiles, approves leave requests, logs attendance, sends announcements, and views reports. Cannot access system settings, audit logs, or backup tools. |
| Staff | Views and updates their own assigned tasks, submits leave requests, views their own attendance records, sends and receives direct messages, and manages their own profile and notification preferences. |
Five pages are a special case: Payroll, Attendance, Leave, Messages, and Reports can each be hidden for everyone by an Admin from the System tab in Settings. Payroll is hidden by default; the other four are visible by default. See docs/roles-and-permissions.md for the full mechanism, including that an Admin can still reach a disabled page directly even when it's hidden for everyone else.
# Install dependencies
npm install
# Copy the example environment file and fill in your values
cp .env.example .env
# Apply the database schema
npx prisma db push
# Populate sample data
node prisma/seed.js
# Start the development server
npm run devThe app will be available at http://localhost:3000.
After seeding, log in with the default admin account:
Email: admin@staffos.com
Password: Admin@123
All other seeded staff accounts use the password Staff@123. See docs/seed-data.md for the full list of seeded accounts and sample records.
Six environment variables are required. The application will not start correctly without all of them.
| Variable | Description |
|---|---|
| DATABASE_URL | Full PostgreSQL connection string including host, port, credentials, and database name |
| JWT_SECRET | Long random string used to sign and verify all JWT tokens |
| NEXT_PUBLIC_APP_URL | The public URL of the deployed application, used in email links |
| GMAIL_USER | The Gmail address used as the sender for all outgoing emails |
| GMAIL_APP_PASSWORD | A 16-character Gmail App Password generated under Google Account security settings |
| CRON_SECRET | A random string used to authenticate the weekly digest cron endpoint |
Generate a secret with:
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"Full details and instructions for configuring these in Vercel are in docs/environment-variables.md.
StaffOS is designed to run on Vercel connected to a cloud PostgreSQL database. The simplest setup provisions Postgres directly from the Storage tab in your Vercel project (Prisma Postgres), so it's already linked with no separate account needed - any other Postgres provider works too if you'd rather bring your own.
The high-level steps are:
- Provision a Postgres database from the Storage tab of your Vercel project (or use another Postgres provider) and note the connection string
- Run
npx prisma db pushwith that connection string to apply the schema - Import the repository into Vercel
- Add all six environment variables to the Vercel project settings
- Deploy
For the complete step by step guide including local setup on Arch Linux, schema update procedures, and cron job configuration, see docs/deployment.md.
StaffOS uses a RESTful API built on Next.js API Routes. Resources are nouns, HTTP methods define the action, and every response follows the same envelope:
{ "success": true, "data": { } }
{ "success": false, "error": "Human readable message" }All protected routes verify a JWT access token from an HTTP-only cookie. Role checks are performed independently inside each handler, not in middleware.
The full list of every route, its method, required role, and expected request body is in docs/api-reference.md.
The docs folder contains a full wiki covering every part of the system.
| Document | What It Covers |
|---|---|
| Architecture | Stack, folder structure, request lifecycle, deployment topology, design system |
| Authentication | Registration, login, JWT strategy, 2FA, email verification, email change, sessions |
| Roles and Permissions | Full access matrix, route protection, how the toggleable-feature system affects visibility |
| Database | Every model, every field, all enums, schema management commands |
| API Reference | Every endpoint with method, auth requirements, and request body |
| Features | Detailed description of every page and feature in the application |
| Email System | Transport setup, every email template, notification preferences |
| Attendance | Statuses, clock times, upsert behaviour, admin vs staff view |
| Leave Management | Leave types, working days calculation, approval flow, cancellation |
| Payroll | Enabling and disabling, configuration options, next pay date calculation |
| Environment Variables | Every variable, how to generate secrets, local and Vercel configuration |
| Deployment | Database setup, Vercel setup, local setup, updating the schema |
| Seed Data | All seeded accounts with credentials, departments, tasks, and sample records |
| Cron Jobs | Weekly digest schedule, authentication, manual triggering, changing the schedule |