Inspiration
Every mid-size company eventually hits the same wall: leave requests live in one spreadsheet, purchase approvals live in email threads, and IT/HR/finance workflows are duct-taped together with forms nobody can audit. Off-the-shelf SaaS tools solve one of these problems, but not all of them, and almost none of them let a single vendor serve multiple client organizations securely from one codebase. I wanted to build the platform I kept wishing existed: a multi-tenant "operating desk" where any organization can spin up its own branded workflow environment — requests, approvals, leave, documents, and reporting — without touching code.
What it does
FlowDesk is a multi-tenant enterprise workflow automation platform with four cooperating layers:
- End-User Interface — staff submit requests, track status, attach files, comment, and receive notifications.
- Tenant Admin Interface — organization admins configure branding, departments, managers, users, roles, approval chains, and leave rules for their own tenant, fully isolated from every other tenant.
- Super Admin Interface — platform owners onboard new tenant organizations, approve tenant admins, monitor activity, and manage global settings.
- Core Workflow Engine — a shared backend engine that drives request lifecycles (submitted → pending approval → approved/rejected/escalated → implemented → completed), enforces approval modes (any-one, all-required, majority, sequential, parallel), and writes an immutable audit trail for every action.
On top of that sits leave management (entitlements, balances, conflict detection, manager/HR approval), configurable request types, file attachments via object storage, real-time dashboards, and full observability so operators can see the health of the platform itself.
How I built it
- Frontend + BFF: Next.js (App Router) with React, TypeScript, Tailwind CSS, and a glassmorphic component system. The browser never talks to the backend directly — every request goes through a Backend-for-Frontend layer built with Next.js Route Handlers, which owns HTTP-only cookie sessions, CSRF protection, and token refresh, then proxies to the Java API as server-only calls.
- Backend API: Java + Spring Boot (Spring Web, Spring Security with OAuth2 Resource Server, Spring Data MongoDB, Spring Validation, Spring Actuator) split into bounded services — tenant/identity, workflow, and reporting — each independently runnable and independently secured.
- Identity & tenancy: Keycloak issues JWTs per realm; every backend endpoint validates the token and enforces tenant isolation at the query level, so no tenant can ever see another tenant's data.
- Data & messaging: MongoDB for domain documents (tenants, departments, users, requests, workflows, audit logs), Redis for caching/rate-limiting, MinIO for file storage, and Kafka wired in for asynchronous, decoupled event handling.
- Observability: Prometheus scrapes metrics from all three Spring services, visualized through custom Grafana dashboards (API health, JVM, and a platform-wide overview) so I can watch the system I built, not just the product it powers.
- Everything containerized: Docker Compose brings up Mongo, Redis, MinIO, Keycloak, Kafka, Prometheus, and Grafana with one command, so the whole stack runs identically on any machine.
Challenges I ran into
- Strict tenant isolation without duplicating infrastructure — I had to guarantee that a bug in one query could never leak another tenant's departments, users, or requests, which meant building tenant-scoping into the data-access layer itself rather than trusting every controller to remember it.
- Keeping the browser fully decoupled from the backend — routing 100% of traffic through the BFF meant re-implementing concerns like token refresh, CSRF, and error normalization that a direct client-to-API call would get "for free," in exchange for a much smaller attack surface.
- Modeling a workflow engine flexible enough for approvals, leave, and generic requests — I needed one state machine (draft → submitted → approval → hold/escalate → implement → complete) that could express wildly different business processes without hardcoding any of them.
- Making the platform observable from day one — wiring Prometheus/Grafana in early, rather than bolting it on later, forced us to think about metrics and audit logging as first-class features instead of an afterthought.

Log in or sign up for Devpost to join the conversation.