Back to tools

N3XFlow

A self-hosted client portal for project stages, acceptance, consolidated feedback rounds, scope changes and decision history.

SELF-HOSTED PROJECT OPSv0.1.0

Delivery completed. Decisions documented.

N3XFlow 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

Want to use it without maintaining the server?

N3X can deploy and maintain this application, from initial setup and SSL to updates, monitoring and backups.

Ask about N3X hosting

A process that protects the relationship and margin

Five acceptance gates

Discovery, direction, design, development and launch each carry their own state, deadline and unambiguous acceptance history.

Consolidated feedback rounds

Up to three shared responses per stage instead of an endless stream of conflicting messages.

One decision maker

Reviewers may add items, but only the designated decision maker accepts stages and additional cost.

Scope-change control

Defects, questions and scope changes stay distinct, while each change order includes price, timing, validity and a decision.

Five-business-day reviews

The worker tracks review windows and records precisely whether a stage was accepted explicitly or deemed accepted after the deadline.

Email-link sign-in

Clients do not create passwords. Tokens are hashed, single-use, valid for 15 minutes and consumed only after confirmation.

Append-only history

The audit trail records actor, time, project, event and context for material decisions.

Phone-ready PWA

Install with a dedicated icon, iOS support, bottom navigation and a safe offline screen that never stores project content.

DOCKER COMPOSE

A private, white-label-ready stack

One configuration starts the portal, worker and PostgreSQL. The owner configures agency branding and SMTP in the authenticated panel, keeping secrets out of Compose.

N3XFlow Web — Project Rooms, roles, acceptance, feedback and settings
N3XFlow Worker — deadlines, offer expiry and email delivery
PostgreSQL 17 — projects, decisions and append-only audit history
Your reverse proxy — HTTPS and a custom domain such as portal.example.com

DOCKER CONFIGURATOR

Compose tailored to your agency

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.

Configure branding and SMTP after sign-in. After startup, open http://SERVER_IP:8792 and create the owner account immediately. Then configure the public HTTPS URL and SMTP. Create consistent backups of postgres_data and runtime_secrets.
Public address
https://flow.example.com
First-run address
http://DOCKER_SERVER_IP:8792
Reverse proxy target
http://DOCKER_SERVER_IP:8792
Health check
http://127.0.0.1:8792/api/health

Ready-to-use docker-compose.yml

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}
  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
    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:

Start and health check

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/health

Changelog

    • ReleaseFirst self-hosted release: a web panel, deadline and notification worker, and PostgreSQL deployed with Docker Compose.
    • NewFive-stage Project Rooms with a designated decision maker, five-business-day reviews and up to three consolidated feedback rounds.
    • NewFeedback classification as defect, scope change or question, plus change-order cards with price, timing and an explicit client decision.
    • NewSingle-use email links, encrypted SMTP settings, project roles and an append-only log of material events.
    • NewAn installable PWA with a dedicated icon, iOS support, mobile bottom navigation and a safe offline screen that never stores project content.
A decision trail, not a signature substitute. N3XFlow supports documentary-form records and project coordination. It does not replace a handwritten or qualified electronic signature when a specific act, such as many copyright assignments, requires that form.