AI-Powered Legal Document Auditor built with Django, Django REST Framework, Django Channels, React, Vite, Redis, PostgreSQL, and Docker Compose.
LawPulse is a LegalTech web application for uploading PDF contracts, extracting risky clauses, and reviewing them in a side-by-side interface. The backend parses uploaded PDF files, stores page-level text, extracts potentially risky clauses using a LangChain-backed service with a heuristic fallback, and streams live progress updates over WebSockets. The frontend provides a contract viewer, extracted text panel, clause list, and review form.
This repository follows a strict Windows-first execution path for local development at:
D:\Projects\LawPulse
Use these versions as the project baseline:
- Python 3.13.12
- Django 5.2
- Node.js 24 LTS
- Redis 7
- PostgreSQL 17
This project includes three critical execution corrections:
-
Python version is fixed to 3.13.12
- Do not use Python 3.12 for this project.
-
Frontend PDF loading uses absolute backend media URLs
- The frontend converts Django media URLs into absolute backend URLs so
react-pdfloads from: http://127.0.0.1:8000/...- instead of incorrectly attempting:
http://127.0.0.1:5173/...
- The frontend converts Django media URLs into absolute backend URLs so
-
A root health endpoint exists at
/http://127.0.0.1:8000/loads successfully and returns a backend health response.
- Django 5.2
- Django REST Framework
- drf-spectacular Swagger / OpenAPI
- Django Channels
- Redis
- React
- Vite
- TypeScript (strict mode)
- PostgreSQL
- LangChain
react-pdf- Docker Compose
- Upload PDF contracts
- Parse contract pages into stored page text
- Extract risky clauses with LangChain-backed logic and heuristic fallback
- Stream live processing updates via WebSockets
- Side-by-side contract viewer and clause review interface
- Review extracted clauses with a structured form
- Custom request latency middleware with
X-Request-Latency-Ms - Swagger / OpenAPI documentation
- Django admin for jobs, pages, and clauses
- Local Windows development workflow
- Full Dockerized stack for frontend, backend, PostgreSQL, and Redis
D:\Projects\LawPulse
├── .gitignore
├── README.md
├── docker-compose.yml
├── docs
│ └── screenshots
│ ├── backend-admin.png
│ ├── backend-response-headers.png
│ ├── backend-swagger-ui.png
│ ├── frontend-completed-view.png
│ ├── frontend-empty-state.png
│ ├── frontend-processing.png
│ └── frontend-selected-clause.png
├── backend
│ ├── .env
│ ├── .env.example
│ ├── Dockerfile
│ ├── manage.py
│ ├── requirements.txt
│ ├── auditor
│ │ ├── admin.py
│ │ ├── apps.py
│ │ ├── consumers.py
│ │ ├── models.py
│ │ ├── routing.py
│ │ ├── serializers.py
│ │ ├── urls.py
│ │ ├── views.py
│ │ └── services
│ │ ├── __init__.py
│ │ ├── llm.py
│ │ └── pdf_audit.py
│ └── config
│ ├── asgi.py
│ ├── middleware.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
└── frontend
├── .env
├── Dockerfile
├── package.json
├── tsconfig.app.json
├── vite.config.ts
└── src
├── api.ts
├── App.css
├── App.tsx
├── index.css
├── main.tsx
├── types.ts
└── components
├── PdfViewerPane.tsx
├── RiskForm.tsx
└── RiskList.tsx
Install the following on Windows before starting:
- Python 3.13.12 (64-bit)
- Node.js 24 LTS
- Git for Windows
- Docker Desktop
- Visual Studio Code
Verify tools in PowerShell:
where.exe python
python --version
py -3.13 --version
py --list
node --version
npm --version
git --version
docker --version
docker compose versionSuccess means:
- every command prints a version
py -3.13 --versionworks- Docker Desktop is running
- Python 3.13.12 is visible and usable
- Python 3.12 is not used for this project
Create the project folders:
cd D:\Projects
mkdir LawPulse
cd D:\Projects\LawPulse
mkdir backend
mkdir frontend
mkdir docs
mkdir docs\screenshotsExpected structure:
D:\Projects\LawPulse
├── backend
├── frontend
└── docs
└── screenshots
Initialize the repository:
cd D:\Projects\LawPulse
git init
git branch -M mainCreate root .gitignore:
# OS
.DS_Store
Thumbs.db
# Python
backend/.venv/
backend/__pycache__/
backend/**/__pycache__/
backend/*.sqlite3
backend/db.sqlite3
backend/.pytest_cache/
backend/.mypy_cache/
backend/.ruff_cache/
backend/media/
backend/staticfiles/
# Python env files
backend/.env
# Node
frontend/node_modules/
frontend/dist/
# Frontend env
frontend/.env.local
frontend/.env.*.local
# Root / generic env
.env
.env.*
# VS Code
.vscode/
# Logs
*.log
# Screenshots temp exports
*.tmp.pngFirst commit:
cd D:\Projects\LawPulse
git status
git add .gitignore
git commit -m "chore: initialize repository and root gitignore"
git log --onelinecd D:\Projects\LawPulse\backend
py -3.13 -m venv .venv
.\.venv\Scripts\Activate.ps1If PowerShell blocks activation:
Set-ExecutionPolicy -Scope CurrentUser RemoteSigned
.\.venv\Scripts\Activate.ps1Successful activation shows the prompt prefixed with:
(.venv)
Create D:\Projects\LawPulse\backend\requirements.txt:
Django>=5.2,<5.3
djangorestframework>=3.16,<3.17
drf-spectacular>=0.28,<0.29
channels>=4.3,<4.4
channels_redis>=4.3,<4.4
daphne>=4.2,<4.3
django-cors-headers>=4.7,<4.8
dj-database-url>=3.0,<3.1
psycopg[binary]>=3.2,<3.3
python-dotenv>=1.1,<1.2
pypdf>=5.4,<5.6
langchain>=0.3,<0.4
langchain-openai>=0.3,<0.4
pydantic>=2.11,<2.12
Install dependencies:
cd D:\Projects\LawPulse\backend
.\.venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
pip install -r requirements.txtcd D:\Projects\LawPulse\backend
.\.venv\Scripts\Activate.ps1
django-admin startproject config .
python manage.py startapp auditor
mkdir auditor\services
New-Item auditor\services\__init__.py -ItemType FileSecond commit:
cd D:\Projects\LawPulse
git add backend
git commit -m "feat: bootstrap Django backend and dependencies"cd D:\Projects\LawPulse\frontend
npm create vite@latest . -- --template react-ts
npm install
npm install react-pdf pdfjs-dist react-hook-form zod @hookform/resolversConfirm strict TypeScript in frontend\tsconfig.app.json:
"strict": trueThird commit:
cd D:\Projects\LawPulse
git add frontend
git commit -m "feat: scaffold React frontend with Vite and strict TypeScript"Create backend\.env.example:
DEBUG=True
SECRET_KEY=django-insecure-change-me
ALLOWED_HOSTS=127.0.0.1,localhost
CORS_ALLOWED_ORIGINS=http://127.0.0.1:5173,http://localhost:5173
DATABASE_URL=sqlite:///D:/Projects/LawPulse/backend/db.sqlite3
REDIS_URL=redis://127.0.0.1:6379/0
LLM_MODEL=gpt-4o-mini
OPENAI_API_KEY=
OPENAI_BASE_URL=Create backend\.env:
DEBUG=True
SECRET_KEY=django-insecure-change-me-now
ALLOWED_HOSTS=127.0.0.1,localhost
CORS_ALLOWED_ORIGINS=http://127.0.0.1:5173,http://localhost:5173
DATABASE_URL=sqlite:///D:/Projects/LawPulse/backend/db.sqlite3
REDIS_URL=redis://127.0.0.1:6379/0
LLM_MODEL=gpt-4o-mini
OPENAI_API_KEY=
OPENAI_BASE_URL=Key backend behavior in the final build:
config/settings.pyloads environment variables from.env- the root endpoint
/returns a JSON health response - media is served in development when
DEBUG=True - Channels is configured to use Redis
- custom request latency middleware adds
X-Request-Latency-Ms - DRF schema generation is exposed through drf-spectacular
When the backend is running, this endpoint should work:
http://127.0.0.1:8000/
Expected response shape:
{
"name": "LawPulse API",
"status": "ok",
"docs": "/api/docs/",
"schema": "/api/schema/",
"admin": "/admin/"
}Run migrations and create an admin user:
cd D:\Projects\LawPulse\backend
.\.venv\Scripts\Activate.ps1
python manage.py makemigrations
python manage.py migrate
python manage.py check
python manage.py createsuperuserSuccess means:
- migrations complete without errors
python manage.py checkreports no issues- superuser is created successfully
Start a local Redis helper container:
docker run --name lawpulse-redis-local -p 6379:6379 -d redis:7If it already exists:
docker start lawpulse-redis-localVerify:
docker pscd D:\Projects\LawPulse\backend
.\.venv\Scripts\Activate.ps1
python manage.py runserverThese pages should load:
http://127.0.0.1:8000/http://127.0.0.1:8000/api/docs/http://127.0.0.1:8000/admin/
Fourth commit:
cd D:\Projects\LawPulse
git add backend
git commit -m "feat: implement Django API, Channels websocket updates, and PDF audit pipeline"Create frontend\.env:
VITE_API_BASE_URL=http://127.0.0.1:8000
VITE_WS_BASE_URL=ws://127.0.0.1:8000The frontend must use the corrected src/api.ts that converts media URLs into absolute backend URLs before react-pdf receives them.
This is required so PDF files load from the backend server rather than the Vite dev server origin.
cd D:\Projects\LawPulse\frontend
npm install
npm run devOpen:
http://127.0.0.1:5173
Verify the following:
- upload a PDF contract
- live status updates appear
- the PDF renders
- the risky clauses list populates
- clicking a clause updates the form
- extracted text highlighting updates
- the PDF loads from the backend media URL correctly
Fifth commit:
cd D:\Projects\LawPulse
git add frontend
git commit -m "feat: implement React side-by-side contract viewer and clause review UI"http://127.0.0.1:8000/api/docs/
http://127.0.0.1:8000/api/schema/
http://127.0.0.1:8000/
GET /api/audit-jobs/POST /api/audit-jobs/GET /api/audit-jobs/{id}/
ws://127.0.0.1:8000/ws/audit-jobs/{id}/
Create backend\Dockerfile:
FROM python:3.13-slim
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
WORKDIR /app
RUN apt-get update && apt-get install -y build-essential libpq-dev && rm -rf /var/lib/apt/lists/*
COPY requirements.txt .
RUN pip install --upgrade pip && pip install -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["sh", "-c", "python manage.py migrate && daphne -b 0.0.0.0 -p 8000 config.asgi:application"]Create frontend\Dockerfile:
FROM node:24-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 5173
CMD ["npm", "run", "dev", "--", "--host", "0.0.0.0"]Create docker-compose.yml in the project root:
services:
db:
image: postgres:17
container_name: lawpulse-db
environment:
POSTGRES_DB: lawpulse
POSTGRES_USER: lawpulse
POSTGRES_PASSWORD: lawpulse
ports:
- "5432:5432"
volumes:
- lawpulse_postgres_data:/var/lib/postgresql/data
redis:
image: redis:7
container_name: lawpulse-redis
ports:
- "6379:6379"
backend:
build:
context: ./backend
container_name: lawpulse-backend
command: sh -c "python manage.py migrate && daphne -b 0.0.0.0 -p 8000 config.asgi:application"
environment:
DEBUG: "True"
SECRET_KEY: docker-secret-key-change-me
ALLOWED_HOSTS: 127.0.0.1,localhost,backend
CORS_ALLOWED_ORIGINS: http://127.0.0.1:5173,http://localhost:5173
DATABASE_URL: postgres://lawpulse:lawpulse@db:5432/lawpulse
REDIS_URL: redis://redis:6379/0
LLM_MODEL: gpt-4o-mini
OPENAI_API_KEY: ""
OPENAI_BASE_URL: ""
volumes:
- ./backend:/app
ports:
- "8000:8000"
depends_on:
- db
- redis
frontend:
build:
context: ./frontend
container_name: lawpulse-frontend
environment:
VITE_API_BASE_URL: http://127.0.0.1:8000
VITE_WS_BASE_URL: ws://127.0.0.1:8000
volumes:
- ./frontend:/app
- /app/node_modules
ports:
- "5173:5173"
depends_on:
- backend
volumes:
lawpulse_postgres_data:Stop local processes and the local Redis helper first:
docker stop lawpulse-redis-localThen run:
cd D:\Projects\LawPulse
docker compose up --buildSuccess means:
- frontend runs on
http://127.0.0.1:5173 - backend runs on
http://127.0.0.1:8000 - Swagger runs on
http://127.0.0.1:8000/api/docs/
Sixth commit:
cd D:\Projects\LawPulse
git add docker-compose.yml backend\Dockerfile frontend\Dockerfile
git commit -m "feat: dockerize frontend backend postgres and redis stack"Save the following files into:
D:\Projects\LawPulse\docs\screenshots
-
backend-swagger-ui.png- page:
http://127.0.0.1:8000/api/docs/ - include visible Swagger title
- include visible
GET /api/audit-jobs/ - include visible
POST /api/audit-jobs/
- page:
-
backend-admin.png- page:
http://127.0.0.1:8000/admin/ - log in
- include visible Audit Jobs, Audit Pages, Risk Clauses
- page:
-
backend-response-headers.png- open browser developer tools
- make a backend request
- capture response headers
- include
X-Request-Latency-Ms
-
frontend-empty-state.png- app before upload
-
frontend-processing.png- while PDF is processing
- include visible progress or status
-
frontend-completed-view.png- after processing
- include left PDF pane
- include extracted text
- include risk list
- include form on the right
-
frontend-selected-clause.png- after clicking a clause
- include selected list item
- include updated form
- include extracted text highlight
Stage screenshots:
cd D:\Projects\LawPulse
git add docs\screenshots
git statusAfter creating this README and collecting screenshots:
cd D:\Projects\LawPulse
git add README.md docs\screenshots
git commit -m "docs: add project setup, screenshots, and usage instructions"Create a new empty GitHub repository named:
lawpulse
Do not add:
- README
- license
.gitignore
cd D:\Projects\LawPulse
git remote add origin https://github.com/YOUR_GITHUB_USERNAME/lawpulse.git
git push -u origin maincd D:\Projects\LawPulse
git remote add origin git@github.com:YOUR_GITHUB_USERNAME/lawpulse.git
git push -u origin mainSuccess means:
- GitHub shows the files
- GitHub shows the commit history
- the README renders screenshots correctly
cd D:\Projects\LawPulse\backend
.\.venv\Scripts\Activate.ps1
python manage.py makemigrations
python manage.py migrate
python manage.py runservercd D:\Projects\LawPulse\frontend
npm install
npm run devdocker start lawpulse-redis-localcd D:\Projects\LawPulse
docker compose up --buildcd D:\Projects\LawPulse
docker compose downcd D:\Projects\LawPulse
git status
git add .
git commit -m "feat: describe one focused change"
git pushConfirm all are true:
http://127.0.0.1:8000/api/docs/loadsPOST /api/audit-jobs/existsGET /api/audit-jobs/worksGET /api/audit-jobs/{id}/returns nested pages and clausesX-Request-Latency-Msexists in response headers
Confirm all are true:
- browser connects to
ws://127.0.0.1:8000/ws/audit-jobs/{id}/ - progress messages arrive during processing
Confirm all are true:
- Vite app runs
- PDF uploads
- risky clauses populate
- selecting a clause updates the form
- selected text highlights in extracted text panel
- PDF renders from backend media URL correctly
Confirm all are true:
docker compose up --buildstarts db, redis, backend, and frontend- frontend communicates with backend successfully
Confirm all are true:
- repository is on GitHub
- commit history is clean
- no secrets are committed
- screenshots render in the README
Backend terminal:
cd D:\Projects\LawPulse\backend
.\.venv\Scripts\Activate.ps1
python manage.py runserverFrontend terminal:
cd D:\Projects\LawPulse\frontend
npm run devRedis terminal:
docker start lawpulse-redis-localcd D:\Projects\LawPulse
docker compose up --buildRun:
cd D:\Projects\LawPulse
git log --onelineExpected shape:
docs: add project setup, screenshots, and usage instructions
feat: dockerize frontend backend postgres and redis stack
feat: implement React side-by-side contract viewer and clause review UI
feat: implement Django API, Channels websocket updates, and PDF audit pipeline
feat: scaffold React frontend with Vite and strict TypeScript
feat: bootstrap Django backend and dependencies
chore: initialize repository and root gitignore
-
Use Python 3.13.12
-
Use Django 5.2
-
Use Node.js 24 LTS
-
Use Redis 7
-
Use PostgreSQL 17
-
Keep local development ports fixed as:
- backend:
8000 - frontend:
5173 - Redis:
6379
- backend:
-
Keep the corrected
frontend\src\api.tsabsolute URL handling for media files -
Keep the root endpoint
/in the backend so health verification works cleanly
cd D:\Projects\LawPulse\backend
.\.venv\Scripts\Activate.ps1
python manage.py migrate
python manage.py runservercd D:\Projects\LawPulse\frontend
npm install
npm run devdocker start lawpulse-redis-localcd D:\Projects\LawPulse
docker compose up --buildDo not commit:
backend\.env- any real API keys
- any personal credentials
The repository should include backend\.env.example as the safe template and keep backend\.env ignored by Git.
LawPulse is the complete single-path build for an AI-powered legal document auditor with:
- Django backend APIs
- WebSocket progress updates
- PDF upload and parsing
- clause extraction and review
- React side-by-side viewer UI
- Redis-backed Channels support
- PostgreSQL-ready Docker deployment
- documented Windows-first local workflow






