WageFlow - Healthcare Staffing & Invoicing Platform
Overview
WageFlow is a healthcare-focused staffing and invoicing platform inspired by Instawork, built to connect healthcare providers with qualified workers.
The system is designed for shift management, job matching, invoicing, compliance, and real-time collaboration between workers and providers.
Currently, WageFlow is in active development, with the backend modular monolith in place and REST API endpoints being refined for jobs, applications, shifts, users, and invoices.
Key Features (In Development)
- Shift Management: Post, assign, and track healthcare shifts
- Worker Applications: Apply for shifts, track status, and receive real-time updates
- Invoicing: Workers generate invoices, providers manage client billing
- AI Matching (Planned): Smart matching of shifts with available workers
- Geo-Tracking (Planned): Clock-in/out with geofencing for attendance verification
- Compliance (Planned): Built-in Canadian healthcare compliance features
Technologies Used
- Backend: NestJS (modular monolith, REST API)
- Database: PostgreSQL with Prisma ORM
- Caching & Queueing: Redis for performance and async tasks
- Authentication: Custom + Supabase Auth integration
- File Storage: Cloudinary for worker/provider documents
- Containerization: Docker & Docker Compose (Kubernetes planned)
- CI/CD: GitHub Actions with Docker deployment pipelines
Architecture
WageFlow follows a modular monolith architecture with future readiness for microservices.
The system includes:
- Job & Application Services (clean, RESTful APIs)
- Invoicing Module for worker payments and client billing
- Provider & Worker Management Services
- Real-time updates via WebSockets/SSE
- AI Matching Module (planned)
Event-Driven Architecture
To keep services decoupled and scalable, WageFlow uses an event-driven approach.
For example, when a new job is created, an event is emitted and other services (like notifications or invoicing) can react without changing the core logic.
// jobs.service.ts
import { Injectable } from '@nestjs/common';
import { EventEmitter2 } from '@nestjs/event-emitter';
import { PrismaService } from '../prisma/prisma.service';
@Injectable()
export class JobsService {
constructor(
private readonly prisma: PrismaService,
private readonly eventEmitter: EventEmitter2,
) {}
async createJob(data: any) {
const job = await this.prisma.job.create({ data });
// Emit event when a job is created
this.eventEmitter.emit('job.created', { jobId: job.id, job });
return job;
}
}