Skip to content

lcorrigan704/client-management-system

Repository files navigation

Client Management System (CMS)

Client and finance management system with a React + Vite frontend and a FastAPI backend backed by SQLite. Includes invoices, quotes, proposals, agreements, expenses, PDF generation, email drafts, and a built-in auth + onboarding flow.

Features

  • Clients, invoices, quotes, proposals, agreements, expenses
  • Line items for invoices/quotes
  • PDF generation for invoices, quotes, agreements, proposals, and expenses
  • Email drafts + optional SMTP send
  • Settings for prefixes, financial dates, bank details, SMTP
  • Role-based access: owner, admin, user
  • One-time setup wizard
  • Supporting documentation uploads for proposals (stored locally)

Structure

  • frontend/ React + Vite + Tailwind + shadcn/ui
  • backend/ FastAPI + SQLAlchemy + Alembic + SQLite

Requirements

  • Python 3.11+ (3.12 recommended)
  • Node 18+
  • WeasyPrint system deps (PDF rendering)
    • macOS: brew install pango libffi
    • Ubuntu/Debian: sudo apt-get install -y libpango-1.0-0 libpangoft2-1.0-0 libpangocairo-1.0-0 libcairo2 libffi8
  • A reverse proxy for production (Nginx recommended). Any reverse proxy/WAF can be used based on your hosting requirements.

Local development (recommended first run)

Start the API:

cd backend
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
alembic upgrade head
uvicorn app.main:app --reload

Start the frontend:

cd frontend
npm install
npm run dev
  • Frontend: http://localhost:5173
  • API docs: http://localhost:8000/docs

One‑click setup (macOS/Linux)

./scripts/setup.sh

Backend setup (manual)

cd backend
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
alembic upgrade head
uvicorn app.main:app --reload

API docs: http://localhost:8000/docs

Backend environment

Create backend/.env (see backend/.env.example):

APP_SECRET=change-me-to-a-long-random-string
DATABASE_URL=sqlite:///./app.db
SESSION_TTL_HOURS=72
SESSION_SECURE=false
ALLOWED_ORIGINS=http://localhost:5173

# Optional SMTP defaults (can also be set in-app)
SMTP_HOST=
SMTP_PORT=587
SMTP_USERNAME=
SMTP_PASSWORD=
SMTP_FROM=
SMTP_USE_TLS=true

APP_SECRET is used to encrypt sensitive values at rest (e.g. SMTP password) and to sign session cookies. Set this to a long, random value (32+ characters, mixed case + numbers + symbols recommended).

Frontend setup (manual)

cd frontend
npm install
npm run dev

Optional frontend environment (see frontend/.env.example):

VITE_API_URL=http://localhost:8000

First-run onboarding

If no users exist, the app shows a setup wizard:

  1. Create owner account
  2. Company profile
  3. Financial dates
  4. Bank details (optional)
  5. SMTP settings (optional)

After setup, login with the owner account.

Roles

  • owner: full access + user management + settings
  • admin: full access to entities, no user management
  • user: full access to entities, no user management or settings

PDFs and email drafts

  • PDFs are generated server-side for invoices, quotes, agreements, proposals, and expenses.
  • Email drafts are created with POST /email/draft.
  • SMTP password is encrypted at rest; user passwords are hashed (Argon2).

Self-hosting notes

  • Frontend and backend are designed to run on the same origin (recommended for cookies).
  • Set SESSION_SECURE=true when using HTTPS.
  • Ensure APP_SECRET is set to a strong, unique value.
  • Persist backend/public/uploads and your SQLite DB.

Production (single server)

  1. Backend (systemd or a process manager):
cd backend
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
alembic upgrade head
uvicorn app.main:app --host 0.0.0.0 --port 8000
  1. Frontend build:
cd frontend
npm install
npm run build
  1. Serve the frontend build and proxy API:
  • Serve frontend/dist with Nginx, Caddy, or any static host.
  • Proxy /api (or all /) to http://127.0.0.1:8000.
  • Update VITE_API_URL if the API is on a different origin.

Nginx (example)

server {
  listen 80;
  server_name your-domain.com;

  root /var/www/cms/frontend/dist;
  index index.html;

  location / {
    try_files $uri /index.html;
  }

  location /api/ {
    proxy_pass http://127.0.0.1:8000/;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
  }
}

Other reverse proxies/WAFs can be used based on your environment.

Docker (backend only)

docker compose up --build

This runs the API on port 8000 with a persistent SQLite volume at backend/data/app.db.

Docker (backend only)

docker compose up --build

This runs the API on port 8000 with a persistent SQLite volume at backend/data/app.db.

Static uploads

Proposal attachments are stored under backend/public/uploads and served at /uploads/.... This directory should be persisted in production.

Resetting local data

python backend/scripts/reset_db.py

This removes backend/app.db and clears backend/public/uploads.

Security notes

  • Passwords are hashed with Argon2.
  • SMTP passwords are encrypted at rest using APP_SECRET.
  • Set APP_SECRET in backend/.env before first run; changing it later will invalidate stored SMTP credentials and sessions.
  • SESSION_SECURE must be true behind HTTPS.
  • APP_SECRET strength is user‑set; weak secrets weaken SMTP encryption at rest.
  • No account lockout or MFA (expected for MVP; add these for public deployments).
  • You can disable API docs in production via ENABLE_DOCS=false.
  • Login rate limiting is configurable via LOGIN_RATE_LIMIT_ATTEMPTS and LOGIN_RATE_LIMIT_WINDOW_SECONDS.
  • Upload size limits are configurable via MAX_UPLOAD_MB (also enforce at your reverse proxy).

Backups

Preferred: run the helper script:

./scripts/backup.sh

Manual alternative (SQLite DB + uploads directory):

tar -czf backups/cms-$(date +%F).tar.gz backend/app.db backend/public/uploads

If you use Docker, back up backend/data/app.db instead. Backups include proposal attachments and expense receipts stored in backend/public/uploads.

License and warranty

This project is open-source and provided “as is”, without warranty of any kind. Use at your own risk.

About

Client management system designed for use by small to medium UK based limited companies and sole traders.

Topics

Resources

License

Contributing

Security policy

Stars

2 stars

Watchers

1 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors