Moanv
ProChart case study
ProChart

Architecture

ProChart

A solution-architecture summary — how the system is designed, and why. Verified from the source code.

Type of system
Multi-tenant SaaS (AI process mapping)
Users
Business analysts and consultants
Hosting
United Kingdom
Main stack
React + TypeScript, Django REST, PostgreSQL
Status
Live
Built for
Client — built by Moanv

The problem

After a discovery workshop, a business analyst reads the transcript line by line and maps it into Visio — days of work nobody sees. The hard part isn't drawing boxes; it's spotting what wasn't said: the rejected path nobody mentioned, the approval authority left undefined, the step only half the room agreed on.

How it fits together

Users

Business analysts & consultants

Front end

React 18 + TypeScript (Vite)

Tenant boundary

Backend / API

Django + DRF (Gunicorn, nginx)

Database

PostgreSQL

One shared database; access scoped by an ownership chain (user → workspace → project), enforced on every endpoint.

External services

  • Anthropic Claude — extraction (Grok optional)
  • Stripe — billing
  • Mailjet — email
  • Google Analytics — consent-gated
Analysts use a React single-page app that talks to a Django REST API backed by PostgreSQL. Access is scoped so you can only touch workspaces you own. The API calls Anthropic Claude to extract a process model from a transcript; Stripe handles billing and Mailjet handles email. Analytics load only after consent.

Tech stack

Front end

  • React 18, TypeScript, Vite
  • jsPDF for client-side PDF/PNG export

Backend

  • Python, Django 5, Django REST Framework
  • Gunicorn behind nginx
  • python-docx for Word export (server-side)

Database

  • PostgreSQL (psycopg 3)

Hosting

  • United Kingdom
  • Self-hosted Ubuntu, deployed via Azure DevOps over SSH

Third-party

  • Anthropic Claude (default), operator-switchable to xAI Grok
  • Stripe (billing)
  • Mailjet (email)
  • Google Analytics (consent-gated)

Key design decisions

A review loop, not an auto-answer

Why: Every node carries a confidence level and every gap becomes an open question; a Draft-vs-Confirmed gate is derived live from the model, so nothing is ‘Confirmed’ until a human resolves it.

Trade-off: The analyst still has to close the loop — the tool won't pretend it's done.

Never store the transcript

Why: The sensitive input is held only in memory for the request and discarded; only the resulting structured model is saved.

Trade-off: No re-processing an old transcript server-side; the user re-supplies it.

Strict schema on AI output

Why: LLM output is validated against a JSON schema and a canonical model before it's trusted — malformed output is rejected.

Trade-off: Stricter prompting and the occasional re-ask.

Ownership-based tenancy

Why: Simple, auditable isolation: you can only reach processes in a workspace you own.

Trade-off: No in-workspace sharing or seats yet.

Security & data protection

  • Hosted in the United Kingdom, over TLS (Let's Encrypt) with HTTP redirected to HTTPS.
  • Session authentication with Django's password hashing; email verification and password reset.
  • Every process endpoint is gated so you can only access workspaces you own.
  • Strong input validation: DRF serializers, Pydantic, a strict JSON-schema on AI output, and email MX + disposable-domain checks at signup.
  • Rate limiting on signup and the contact form.
  • Analytics are consent-gated (loaded only after ‘accept’); fonts are self-hosted.
  • Transcripts are never stored or used to train models; secrets are server-side only.

Built to hold up

Performance
A React single-page app with a Django API; PDFs render in the browser.
Availability
A single UK host, Gunicorn behind nginx.
Scalability
Ownership-scoped tenancy on one shared PostgreSQL; plan limits (3 / 30 extractions per month) enforced server-side.

What we'd do next

  • Add HSTS and a strict Content-Security-Policy.
  • Extend rate limiting to the login and extraction endpoints.
  • Add in-workspace collaboration — shared seats within a workspace.