Five acceptance gates
Discovery, direction, design, development and launch each carry their own state, deadline and unambiguous acceptance history.
A self-hosted client portal for project stages, acceptance, consolidated feedback rounds, scope changes and decision history.
N3X Flow turns scattered email and chat threads into a premium Project Room: the client always sees the next action, the team controls scope, and every comment, acceptance and commercial decision stays with the right stage.
Data on your server · single-use email links · encrypted SMTP · no application telemetry
Managed hosting by N3X
N3X can deploy and maintain this application, from initial setup and SSL to updates, monitoring and backups.
Discovery, direction, design, development and launch each carry their own state, deadline and unambiguous acceptance history.
Up to three shared responses per stage instead of an endless stream of conflicting messages.
Reviewers may add items, but only the designated decision maker accepts stages and additional cost.
Defects, questions and scope changes stay distinct, while each change order includes price, timing, validity and a decision.
The worker tracks review windows and records precisely whether a stage was accepted explicitly or deemed accepted after the deadline.
Clients do not create passwords. Tokens are hashed, single-use, valid for 15 minutes and consumed only after confirmation.
The audit trail records actor, time, project, event and context for material decisions.
Install with a dedicated icon, iOS support, bottom navigation and a safe offline screen that never stores project content.
DOCKER COMPOSE
One configuration starts the portal, worker and PostgreSQL. The owner configures agency branding and SMTP in the authenticated panel, keeping secrets out of Compose.
DOCKER CONFIGURATOR
Set the domain, bind address, port and image version. The configurator prepares a ready-to-use Docker Compose file and startup commands without manually managing secrets.
The domain must point to your reverse proxy. Do not include https:// or a path.
0.0.0.0 provides LAN and proxy access. Use 127.0.0.1 when the reverse proxy runs on the same host.
The application port available to your reverse proxy. The default is 8792.
Keep latest for the newest release or pin a specific version.
name: n3xflow
x-app-environment: &app-environment
N3XFLOW_DATABASE_PASSWORD_FILE: /run/n3xflow/database_password
N3XFLOW_TRUST_PROXY_HOPS: ${N3XFLOW_TRUST_PROXY_HOPS:-0}
N3XFLOW_DEV_MAGIC_LINKS: ${N3XFLOW_DEV_MAGIC_LINKS:-0}
N3XFLOW_UPLOADS_DIR: /var/lib/n3xflow/uploads
TZ: Europe/Warsaw
x-app-security: &app-security
read_only: true
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
tmpfs:
- /tmp:size=64m,mode=1777
- /app/.next/cache:size=128m,mode=0700,uid=1001,gid=1001
services:
bootstrap:
image: alpine:3.22
restart: "no"
command:
- /bin/sh
- -ec
- |
umask 077
if [ ! -s /run/n3xflow/database_password ]; then
od -An -N32 -tx1 /dev/urandom | tr -d ' \n' > /run/n3xflow/database_password
fi
if [ ! -s /run/n3xflow/settings_key ]; then
od -An -N32 -tx1 /dev/urandom | tr -d ' \n' > /run/n3xflow/settings_key
fi
chmod 0444 /run/n3xflow/database_password /run/n3xflow/settings_key
volumes:
- runtime_secrets:/run/n3xflow
networks:
- backend
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
web:
image: ghcr.io/nexitpl/n3xflow:latest
pull_policy: always
restart: unless-stopped
depends_on:
bootstrap:
condition: service_completed_successfully
postgres:
condition: service_healthy
environment: *app-environment
volumes:
- runtime_secrets:/run/n3xflow:ro
- uploads_data:/var/lib/n3xflow/uploads
ports:
# Keep behind a firewall until the owner account exists; publish through HTTPS.
- "0.0.0.0:8792:3000"
healthcheck:
test: ["CMD", "wget", "-q", "--spider", "http://127.0.0.1:3000/api/health"]
interval: 30s
timeout: 5s
retries: 5
start_period: 30s
networks:
- frontend
- backend
<<: *app-security
worker:
image: ghcr.io/nexitpl/n3xflow:latest
pull_policy: always
restart: unless-stopped
depends_on:
bootstrap:
condition: service_completed_successfully
postgres:
condition: service_healthy
web:
condition: service_healthy
environment: *app-environment
volumes:
- runtime_secrets:/run/n3xflow:ro
command: ["node", "dist/worker.cjs"]
networks:
- backend
<<: *app-security
postgres:
image: postgres:17-alpine
restart: unless-stopped
depends_on:
bootstrap:
condition: service_completed_successfully
environment:
POSTGRES_DB: n3xflow
POSTGRES_USER: n3xflow
POSTGRES_PASSWORD_FILE: /run/n3xflow/database_password
volumes:
- postgres_data:/var/lib/postgresql/data
- runtime_secrets:/run/n3xflow:ro
healthcheck:
test: ["CMD-SHELL", "pg_isready -U n3xflow -d n3xflow"]
interval: 5s
timeout: 5s
retries: 12
networks:
- backend
networks:
frontend:
backend:
internal: true
volumes:
postgres_data:
runtime_secrets:
uploads_data:
mkdir -p n3xflow
cd n3xflow
# Save the copied configuration as docker-compose.yml
docker compose up -d
docker compose ps
curl -fsS http://127.0.0.1:8792/api/healthUSER GUIDE
Installation, getting started, settings and troubleshooting.
N3XFlow is a client collaboration portal for project stages, feedback, approvals, scope changes and decision history.
You need a server with Docker Compose, a browser, an HTTPS domain and SMTP for messages and sign-in links. PostgreSQL is included.
docker compose up -d
docker compose ps
http://SERVER_IP:8792 from a trusted network and create the owner account.Host and X-Forwarded-Proto.Restrict access with a firewall until the owner exists. With one trusted proxy, you can set N3XFLOW_TRUST_PROXY_HOPS=1; the application should not be accessible by bypassing that proxy.
Create a project and assign the team, client decision maker and reviewers. Work through its stages, collect consolidated feedback, agree on scope changes and record decisions.
The built-in Guide explains responsibilities, deadlines, feedback rounds, attachments and approval rules in Polish and English. Use it alongside the project's agreements.
Email notifications go to the opposite project side. Client messages include a single-use sign-in link valid for 15 minutes.
Images and short videos are available to authenticated project participants. Uploads are limited to 30 MB per form; the reverse proxy should allow at least 32 MB.
Install the portal on your home screen as a PWA. Project content requires a server connection and is not cached for offline work.
Take consistent backups of postgres_data, uploads_data and runtime_secrets. Losing the settings key makes saved SMTP credentials unrecoverable.
Before updating, review release notes and Compose changes. After backing up:
docker compose pull
docker compose up -d
docker compose ps
When upgrading an older installation without attachment support, update Compose too and retain the named uploads_data volume.
For missing email, check SMTP settings and docker compose logs --tail=100 worker. Expired links require a fresh sign-in link. For failed uploads, check file size and the proxy limit. Approval records do not replace a special signature form required by a contract.