https://github.com/wardvisual/wardsuite.hcm
A mini Human Capital Management time tracking system for attendance operations.
https://github.com/wardvisual/wardsuite.hcm
attendance-tracker firebase firestore hcm monorepo nodejs react
Last synced: 14 days ago
JSON representation
A mini Human Capital Management time tracking system for attendance operations.
- Host: GitHub
- URL: https://github.com/wardvisual/wardsuite.hcm
- Owner: wardvisual
- Created: 2026-05-12T09:35:56.000Z (about 1 month ago)
- Default Branch: main
- Last Pushed: 2026-05-14T04:28:42.000Z (about 1 month ago)
- Last Synced: 2026-05-14T06:36:44.436Z (about 1 month ago)
- Topics: attendance-tracker, firebase, firestore, hcm, monorepo, nodejs, react
- Language: TypeScript
- Homepage: https://hcm.wardvisual.com
- Size: 1.41 MB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# WardSuite HCM
> A mini Human Capital Management time tracking system for attendance operations.
WardSuite HCM helps teams track time-ins/time-outs with a clean punch flow, while automatically computing regular hours, overtime, night differential, lateness, and undertime.
[](https://hcm.wardvisual.com)

---
## Tech Stack
| Layer | Technology |
|---|---|
| Frontend | React 19, Vite, Tailwind CSS 4, React Router 7 |
| Animations | Motion |
| State | Zustand (with persist) |
| Backend | Node.js, Express 5, TypeScript (class-based/OOP) |
| Database | Firebase Firestore |
| Authentication | Firebase Auth + Firebase Admin token verification |
| Monorepo | npm workspaces (`apps/*`) |
---
## Repository Structure
```text
wardsuite.hcm/
├── apps/
│ ├── api/ # Express 5 API (TypeScript)
│ │ ├── main.ts
│ │ ├── scripts/
│ │ │ └── migrate.ts
│ │ └── src/
│ │ ├── app.ts
│ │ ├── core/
│ │ ├── modules/
│ │ │ ├── auth/
│ │ │ └── users/
│ │ └── types/
│ └── web/ # React SPA (Vite + Tailwind)
│ └── src/
│ ├── components/
│ ├── modules/
│ │ ├── auth/
│ │ ├── attendance/
│ │ ├── dashboard/
│ │ └── Landing/
│ └── services/
├── libs/
├── .env.example
├── package.json
└── tsconfig.base.json
```
---
## Core Features
| Area | Included |
|---|---|
| Punch Tracking | Punch in/out flow with real-time attendance updates |
| Time Computation | Regular hours, OT, ND (22:00–06:00), late/undertime summaries |
| Daily Summary | Pre-computed day-level metrics |
| Role Access | RBAC support for ADMIN and MANAGER surfaces |
| Admin Visibility | Attendance reporting and punch management panels |
---
## Getting Started
### Prerequisites
- Node.js 22+
- npm
- Firebase project with Firestore + Auth enabled
- Firebase service account credentials
### 1. Install dependencies
```bash
npm install
```
### 2. Configure environment
Copy values from `.env.example` into your local `.env`:
```env
API_PORT=3000
NODE_ENV=development
FIREBASE_PROJECT_ID=
FIREBASE_CLIENT_EMAIL=
FIREBASE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n"
FIREBASE_DATABASE_ID=
VITE_FIREBASE_API_KEY=
VITE_FIREBASE_AUTH_DOMAIN=
VITE_FIREBASE_PROJECT_ID=
VITE_FIREBASE_STORAGE_BUCKET=
VITE_FIREBASE_MESSAGING_SENDER_ID=
VITE_FIREBASE_APP_ID=
VITE_FIREBASE_DATABASE_ID=
JWT_SECRET=
```
### 3. Run in development
```bash
npm run dev
```
- API: `http://localhost:3000`
- Web: `http://localhost:5173`
---
## Scripts
| Script | Description |
|---|---|
| `npm run dev` | Run API + Web concurrently |
| `npm run dev:api` | Run API only |
| `npm run dev:web` | Run Web only |
| `npm run build` | Build API + Web |
| `npm run build:api` | Build API only |
| `npm run build:web` | Build Web only |
| `npm run check` | Typecheck + lint + format check (full CI gate) |
| `npm run typecheck` | Typecheck API + Web |
| `npm run typecheck:api` | Typecheck API only |
| `npm run typecheck:web` | Typecheck Web only |
| `npm run lint` | Lint TypeScript/TSX source files |
| `npm run lint:fix` | Auto-fix lint issues where possible |
| `npm run format` | Format app files with Prettier |
| `npm run format:check` | Check formatting with Prettier |
| `npm run migrate` | Apply Firestore migrations |
| `npm run migrate:status` | Show migration status |
| `npm run seed` | Seed API demo data |
| `npm run emulate` | Run Firebase emulators |
| `npm run firebase:deploy:rules` | Deploy Firestore security rules |
| `npm run firebase:deploy:indexes` | Deploy Firestore indexes |
| `npm run firebase:deploy:hosting` | Deploy Firebase hosting |
| `npm run clean` | Remove build output directories |
---
## Deployment
The system runs as two independently deployed units:
| Service | Host | URL |
|---|---|---|
| Frontend (SPA) | Firebase Hosting | `https://hcm.wardvisual.com` |
| API | Docker · DigitalOcean VPS | `https://hcmapi.wardvisual.com` |
---
### Frontend — Firebase Hosting
The React SPA is built with the production API base URL injected at build time, then deployed to Firebase Hosting.
**1. Set production env vars**
Create `.env.production` (or export inline):
```env
VITE_API_BASE_URL=https://hcmapi.wardvisual.com/api
VITE_FIREBASE_API_KEY=...
VITE_FIREBASE_AUTH_DOMAIN=...
VITE_FIREBASE_PROJECT_ID=...
VITE_FIREBASE_STORAGE_BUCKET=...
VITE_FIREBASE_MESSAGING_SENDER_ID=...
VITE_FIREBASE_APP_ID=...
VITE_FIREBASE_DATABASE_ID=...
```
**2. Build and deploy**
```bash
# Build + deploy to Firebase Hosting in one step
npm run deploy:web
```
This runs `cross-env VITE_API_BASE_URL=https://hcmapi.wardvisual.com/api npm run build:web`, outputs to `dist/web/`, then runs `firebase deploy --only hosting`.
**3. Deploy Firestore rules and indexes (when changed)**
```bash
npm run firebase:deploy:rules
npm run firebase:deploy:indexes
```
**Hosting config** (`firebase.json`):
- Public folder: `dist/web`
- SPA fallback: all routes → `/index.html`
---
### API — Docker on DigitalOcean VPS
The Express API runs inside a Docker container, fronted by a **Caddy** reverse proxy that handles TLS automatically via Let's Encrypt.
#### Infrastructure
```
Internet
│
▼
Caddy (hcmapi.wardvisual.com) ← TLS termination, gzip, security headers
│
▼
wardsuite-hcm-api:3000 ← Docker container (internal)
│
▼
Firebase Admin SDK → Firestore
```
## API Response Contract
```json
// success
{ "success": true, "message": "...", "data": {}, "meta": {} }
// error
{ "success": false, "message": "...", "error": "...", "statusCode": 400 }
```
---
## Firestore Collections
| Collection | Doc ID format | Purpose |
|---|---|---|
| `users` | Firebase UID (`_schema` sentinel also exists) | User profiles and schedule metadata |
| `attendance` | auto-id (`_schema` sentinel also exists) | Punch in/out records (one doc per IN/OUT event) |
| `dailySummary` | `{userId}_{YYYY-MM-DD}` (`_schema` sentinel also exists) | Computed daily totals |
| `attendanceHistory` | auto-id (`_schema` sentinel also exists) | Immutable audit log for punch edits/adjustments |
| `weeklySummary` | `{userId}_{YYYY-WNN}` (`_schema` sentinel also exists) | Aggregated weekly totals for reporting |
| `_migrations` | migration version | Migration tracking |
---
## Author
**Eduardo** — [@wardvisual](https://github.com/wardvisual)