A collaborative platform for teams
Mobflow is a portfolio-grade SaaS simulation that explores modern collaboration workflows with microservices, event-driven communication, and production-style local orchestration.
Table of Contents
Mobflow is a collaborative platform for teams that combines authentication, workspaces, task execution, social interactions, notifications, and realtime chat in a single product experience. It is built as a monorepo with eight Spring Boot backend services, an Angular frontend, and a Docker-based local platform that mirrors the operational boundaries of a real SaaS system.
The project exists to understand and simulate how a production-oriented SaaS can be structured across multiple bounded contexts. Instead of presenting a simplified CRUD sample, Mobflow focuses on service boundaries, gateway routing, JWT-based security, asynchronous events with Kafka, polyglot persistence, local observability, and a developer workflow that reflects real platform engineering decisions.
Mobflow supports the full core flow from account registration and email confirmation to login, workspace access, task management, comments, and notifications.
The platform includes realtime private messaging with WebSocket delivery, conversation history, and read receipt support through the API Gateway and chat service.
Task comments support collaborative discussion and @mentions, allowing users to trigger targeted notification events during task-related conversations.
Required to run the full platform:
- Docker Engine or Docker Desktop with Docker Compose V2
Optional for local development outside containers:
- Java 21
- Maven 3.9+
- Node.js 24
- npm 11+
- OpenSSL or another secure secret generator
Mobflow uses the root .env file as the shared runtime configuration for Docker Compose and the backend services.
- Copy the reference file:
cp .env.example .env- Generate a Base64 JWT secret and place it in
JWT_SECRET:
openssl rand -base64 32- Generate the shared internal service secret and place it in
INTERNAL_SECRET:
openssl rand -hex 32Key points:
JWT_SECRETis used by all services that validate access tokens.INTERNAL_SECRETsecures synchronous/internal/**calls between services through theX-Internal-Secretheader..env.exampleis the reference template;.envis your local runtime file.
- Verify Docker is available:
docker version- Clone the repository and enter the project directory:
git clone https://github.com/LuizAndradeDev/mobflow.git
cd mobflow-
Create and populate
.envas described above. -
Start PostgreSQL first on a clean setup:
docker compose up -d postgres- Verify that the isolated relational databases were created from
init-db.sql:
docker compose exec postgres sh -lc 'PGPASSWORD="$POSTGRES_PASSWORD" psql -U "$POSTGRES_USER" -d postgres -c "\\l"'Expected databases:
mobflow_authmobflow_usermobflow_workspacemobflow_task
- Start the rest of the platform:
docker compose up --build -d- Validate the main edge and gateway:
docker compose ps
curl http://localhost/health
curl http://localhost:8087/actuator/healthUseful maintenance commands:
docker compose down
docker compose down -v
docker compose logs -f <service-name>Optional frontend development outside Docker:
cd web-app
npm install
npm startThe Angular development proxy targets http://localhost:8080, so this mode assumes the gateway is running locally on that port. If you are using the Dockerized stack through nginx on http://localhost, update web-app/proxy.conf.json or run the frontend against the production edge instead.
The following local tools are exposed by Docker Compose:
| Tool | URL | Purpose |
|---|---|---|
| Application | http://localhost |
Main entry point served by nginx, including the Angular app, /api/**, and chat WebSocket proxying. |
| API Gateway Actuator | http://localhost:8087/actuator/health |
Direct gateway diagnostics without going through the edge Nginx layer. |
| MailHog | http://localhost:8025 |
Email inspection for account confirmation and notification delivery. |
| MinIO API | http://localhost:9000 |
Object storage endpoint used by avatar upload flows. |
| MinIO Console | http://localhost:9001 |
Storage inspection and bucket management. |
| Prometheus | http://localhost:9090 |
Metrics querying and scrape target inspection. |
| Grafana | http://localhost:3000 |
Pre-provisioned dashboards for local observability. |
- Open the application at
http://localhost. - Register with username, email, and password.
- After registration, wait for the confirmation message.
- Open MailHog at
http://localhost:8025. - Open the confirmation email and follow the confirmation link.
- Return to the application and log in with the confirmed account.
Mobflow follows a consistent request path for user-facing operations:
Client -> Nginx -> API Gateway -> Services -> Data Stores / Kafka
In local production-style runs, the browser loads the Angular app from nginx, external API traffic is routed through api-gateway, and each backend service owns its own domain logic and persistence. Kafka is used for side effects that should be decoupled from the request path, especially notification fan-out.
The system has three dominant interaction patterns:
- Browser request flow: the client reaches
nginx,nginxproxies API or WebSocket traffic toapi-gateway, and the gateway routes the request to the service that owns the bounded context. - Internal synchronous flow: services call dedicated internal endpoints when they need request-scoped authorization or enrichment data that must stay owned by another service.
- Event-driven flow: services publish domain events to Kafka, and
notification-serviceconsumes them to create in-app notifications and email deliveries without blocking the original user request.
nginx is the public entry point for the browser. It serves the compiled Angular bundle, handles SPA refreshes, proxies /api/** to the gateway, and upgrades /chat/ws/chat for realtime chat connections. This keeps the frontend deployment model simple while preserving a single browser-facing origin.
api-gateway is the single public backend router. It maps external paths to the correct service, validates JWTs for protected /api/** routes, applies an in-memory rate limit, and propagates request context through headers such as X-Correlation-Id, X-User-Id, and X-User-Roles. It also rewrites routes for services that expose internal context paths, such as /tasks, /social, and /chat.
auth-service, user-service, workspace-service, and task-service cover identity, profiles, workspaces, and task management. These services use PostgreSQL for transactional data and keep ownership boundaries explicit: credentials live only in auth-service, profile data and avatars live only in user-service, workspace membership lives only in workspace-service, and board/list/task state lives only in task-service.
social-service, chat-service, and notification-service cover comments, friendships, messaging, and notification delivery. They use MongoDB because these domains are naturally document-oriented and often evolve around nested or append-heavy interaction records rather than relational joins.
Kafka is used for domain events that should not block the request path, especially notification flows. PostgreSQL, MongoDB, Redis, and MinIO are shared as infrastructure, but state ownership remains service-specific. Services do not reach into another service's database; they communicate through HTTP contracts or events.
| Component | Public Surface | Primary Responsibility | Persistence / State | Role in the System |
|---|---|---|---|---|
web-app |
Browser SPA | User interface for authentication, workspace, task, social, notification, and chat flows | Static frontend bundle | Presents the product experience and calls the gateway over HTTP/WebSocket |
nginx |
http://localhost |
Serves the Angular build and fronts all browser traffic | Stateless | Edge layer and single browser-facing origin |
api-gateway |
http://localhost:8087 and proxied /api/** |
Public routing, JWT enforcement, rate limiting, and header propagation | Stateless | Central backend entry point |
auth-service |
/api/auth/** |
Account registration, login, email confirmation, JWT issuance, trusted identity lookup | PostgreSQL (mobflow_auth) |
Identity and token authority |
user-service |
/api/users/** |
User profiles, avatar uploads, and profile enrichment for other services | PostgreSQL (mobflow_user), Redis, MinIO |
Profile and avatar boundary |
workspace-service |
/api/workspaces/** |
Workspace lifecycle, invites, member roles, and join-code access | PostgreSQL (mobflow_workspace) |
Collaboration boundary and membership authority |
task-service |
/api/tasks/** via gateway rewrite to /tasks/api/** |
Boards, lists, tasks, workspace summaries, and analytics | PostgreSQL (mobflow_task), Redis |
Task execution and reporting domain |
social-service |
/api/social/** via gateway rewrite to /social/api/** |
Friendships, friend requests, task comments, and mention resolution | MongoDB (social) |
Social collaboration domain |
chat-service |
/api/chat/** and /chat/ws/chat via gateway |
Private conversations, message history, realtime delivery, unread counters, and read receipts | MongoDB (chat) |
Realtime messaging domain |
notification-service |
/api/notifications/** |
In-app notification persistence and email delivery triggered by platform events | MongoDB (notifications) |
Event-consumption and user notification delivery edge |
Core services:
auth-service: registration, login, email confirmation, JWT issuance, and trusted user lookup by username.user-service: user profiles, avatar storage, and batch profile lookups for other services.workspace-service: workspace lifecycle, membership, invites, and role checks.task-service: boards, task lists, tasks, workspace summaries, and analytics.
Collaboration services:
social-service: friendships, friend requests, task comments, mentions, and related enrichment.chat-service: conversations, message history, realtime delivery, and friendship validation before direct chat.notification-service: consumes platform events and stores or delivers in-app and email notifications.
Mobflow uses two communication styles:
- Synchronous HTTP: browser requests enter through
nginxandapi-gateway, then reach the target service over REST. Services also call trusted internal endpoints when they need request-scoped authorization or enrichment data. Examples includetask-serviceaskingworkspace-servicefor member roles,workspace-serviceaskinguser-serviceto resolve usernames,social-servicevalidating task context and membership, andchat-servicevalidating friendship status before opening private conversations. - Asynchronous Kafka:
auth-service,workspace-service,task-service,social-service, andchat-servicepublish domain events. Current topics includeauth-events,workspace-events,task-events,social-comment-events,social-friendship-events, andsocial.events.notification-serviceconsumes those events to generate notifications and email side effects without coupling notification delivery to the latency or availability of the original request path.
Kafka is intentionally used for cross-service side effects, not as the primary request transport. User-facing reads and writes still happen over HTTP, while notifications and similar fan-out concerns are pushed into asynchronous processing.
Authentication is stateless and JWT-based. auth-service issues tokens, api-gateway validates them at the edge, and downstream services validate them again with the shared JWT secret. This avoids centralizing all authorization decisions in the gateway and lets each service keep responsibility for its own domain rules.
Trusted backend-to-backend calls use X-Internal-Secret on dedicated internal endpoints such as /internal/** and auth-service's /internal/auth/**. In practice, Mobflow uses this for membership checks, user/profile enrichment, username resolution, task context lookups, workspace summaries, and friendship validation. These internal endpoints are intentionally narrow and are used only when one service must consult another service's source of truth.
This results in a simple defense-in-depth model:
- the gateway blocks unauthenticated external traffic on protected routes;
- each service validates JWTs again for its own public endpoints;
- internal endpoints require the shared secret and are not exposed as part of the browser-facing API surface.
Each backend service exposes Spring Boot Actuator health and Prometheus metrics endpoints. Prometheus scrapes those endpoints, Grafana provides pre-provisioned local dashboards, and X-Correlation-Id is propagated across HTTP calls for request tracing through the gateway and internal service calls.
The CI workflow is intentionally focused on validation rather than deployment. It currently covers:
- backend build and tests per service
- backend quality checks
- frontend tests and production build
- repository security scanning
Docker Compose remains a local runtime tool for bootstrapping the full platform, but it is not part of the CI pipeline.
Useful local validation commands:
(cd api-gateway && ./mvnw --batch-mode --no-transfer-progress verify)
scripts/test-backend.sh
scripts/ci/check-backend-quality.sh- API Gateway
- Auth Service
- User Service
- Workspace Service
- Task Service
- Social Service
- Chat Service
- Notification Service
This project is licensed under the Mobflow Attribution-NonCommercial License 1.0.



