ProjectFlow is a collaborative project and task management application built as a full-stack engineering sample. Rails owns business rules and data, Vue consumes its REST API, and a dedicated Node.js/Socket.io service delivers authorized realtime events.
- JWT login with active-account checks.
- Admin and Member roles with server-side authorization.
- User administration, including role and account-status management.
- Project creation, editing, and membership management.
- Project-scoped tasks with status, priority, due date, and assignment workflows.
- Task comments and a persisted project Activity Feed.
- Realtime task, comment, and membership updates, plus personal assignment notifications.
| Layer | Technology |
|---|---|
| Backend API | Ruby 3.4.10, Rails 8.1.3.1, Puma |
| Frontend | Vue 3, Vite, Pinia, Vue Router, Axios |
| UI | PrimeVue, Tailwind CSS |
| Database | PostgreSQL |
| Realtime | Node.js, Express, Socket.io |
| Authentication | JWT, bcrypt |
| Backend testing | RSpec request specs |
| Local orchestration | Docker, Docker Compose |
The repository contains three application services:
api/: authoritative domain layer for authentication, authorization, persistence, users, projects, memberships, tasks, comments, and activities.frontend/: Vue interface for authentication state, project/task workflows, REST communication, and realtime UI refreshes.event-service/: Socket.io delivery layer that validates Rails webhooks and authorizes socket access against Rails. It does not store business data.
A realtime change follows this path:
- Rails validates and persists the change.
- Rails records an
Activitywhere applicable. - Rails sends the activity to Node through a shared-secret webhook.
- Node broadcasts it to an authorized Socket.io room.
- Vue reloads the affected resource from Rails.
flowchart LR
B[Browser / Vue]
R[Rails API]
D[(PostgreSQL)]
N[Node / Socket.io]
B -->|REST + JWT| R
R -->|SQL| D
R -->|Activity webhook| N
B <-->|Socket.io + JWT| N
N -->|User and project authorization| R
- Admins can access all projects, manage users and account status, create or edit projects, and manage memberships.
- Members can access only their projects, where they can work with project tasks, assignments, comments, members, and activities.
- Project, task, comment, membership, and activity lookups resolve through authorized project scopes. Cross-project resource requests return
404. - Task assignees are validated server-side and must be active members of the task's project.
- Admins must be explicit project members before they can be selected as assignees.
- Membership removal is blocked while the user has assigned tasks in that project.
- The users API rejects self-deactivation and checks that another active admin remains before deactivating or demoting an admin.
- Inactive users cannot log in or continue using protected Rails endpoints.
- Frontend route guards and controls support the UX, but Rails remains the security boundary.
Vue sends its Rails JWT during the Socket.io handshake. Node validates the user against Rails, derives the personal user:<id> room from that response, and checks each project:<id> room join through the scoped Rails project endpoint. Vue rejoins the active project room after Socket.io reconnects.
project:eventsignals task, comment, and membership changes. Vue then refreshes authoritative REST data.notificationdelivers assignment and reassignment messages to the affected user's room.
Rails-to-Node webhooks use a separate server-side secret. Webhook transport errors are logged after persistence and do not undo the completed Rails operation. Delivery is currently best-effort, without retry or replay.
Docker Compose is the recommended local setup.
docker compose up --build| Service | URL |
|---|---|
| Frontend | http://localhost:5173 |
| Rails API | http://localhost:3000 |
| Event service | http://localhost:3001 |
| Event health check | http://localhost:3001/health |
Stop the services without deleting PostgreSQL data:
docker compose downPostgreSQL uses the persistent projectflow_postgres_data volume and is not exposed to the host. Compose keeps server-side secrets out of the frontend environment.
After loading the development seeds:
| Role | Password | |
|---|---|---|
| Admin | admin@projectflow.test |
password123 |
| Member | member@projectflow.test |
password123 |
These credentials are for local development only.
Run the Rails request specs:
cd api
bin/rspecThe suite covers authentication, inactive users, endpoint authorization, project scoping, task authorization, assignment validation, and reassignment activity metadata.
Frontend quality checks:
cd frontend
npm run lint
npm run build- Realtime delivery has no persistence, retry, replay, or reconnect catch-up.
- Personal assignment notifications are not persisted.
- Frontend and event-service automated tests are not configured.
- Self-service registration and password-reset endpoints are not implemented.