Files
elegalsoftware/README.md
T
2026-04-26 02:42:42 -04:00

122 lines
5.1 KiB
Markdown

# eLegal Software
All-in-one practice management for law firms. Single Node app that serves both the React SPA and the API on one port — designed to run behind Plesk's Node.js extension on a single domain.
## Stack
- **Frontend** — Vite + React 18 + TypeScript + Tailwind + Framer Motion + Recharts + lucide-react
- **API** — Fastify 5 + TypeScript + Zod
- **DB** — Drizzle ORM → DigitalOcean Managed Postgres (TLS)
- **Auth** — local: argon2id passwords + Postgres-backed sessions in httpOnly cookies (no third-party auth provider)
- **Storage** — DigitalOcean Spaces (S3-compatible, presigned uploads)
- **Email** — Resend
- **Payments** — Stripe
- **Hosting** — Plesk + Phusion Passenger (Node 20 LTS)
## Repository layout
```
.
├── apps/
│ ├── api/ # Fastify server (also serves built web/dist in prod)
│ └── web/ # Vite + React SPA
├── packages/
│ └── db/ # Drizzle schema + migrations (shared)
├── certs/ # DO Postgres CA cert (do-ca.crt) — not in git
├── scripts/
│ └── plesk-deploy.sh
├── tmp/restart.txt # touched by deploy script to bounce Passenger
└── app.js # Plesk entrypoint (loads apps/api/dist/server.js)
```
## Local development
Prerequisites: Node 20+, pnpm 9+, a Postgres database (managed DO instance, or local).
```bash
cp .env.example .env
# fill in DATABASE_URL, SESSION_SECRET, CSRF_SECRET (generate with `node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"`)
pnpm install
pnpm db:generate # generate SQL migrations from schema
pnpm db:migrate # apply to the DB
pnpm dev # starts api on :8080 and web on :5173 (proxies /api → :8080)
```
Visit http://localhost:5173.
## Production build
```bash
pnpm build # builds packages/db → apps/web → apps/api
pnpm start # runs node app.js → apps/api/dist/server.js
```
The API serves `apps/web/dist` at `/` with SPA fallback and routes `/api/*` to Fastify handlers.
## Plesk deployment (single domain)
1. **Create the domain** in Plesk and enable **Let's Encrypt** TLS.
2. **Install Node.js extension** (Plesk → Extensions → "Node.js"). Set Node version to **20.x** in the domain's Node.js settings.
3. **Pull the repo** into the domain's document root via Plesk → Git, or `git clone` over SSH into `/var/www/vhosts/yourdomain.com/httpdocs`.
4. **Node.js settings** in the Plesk panel for that domain:
- **Application root** → the repo root
- **Document root** → leave as default; nginx will proxy to Passenger
- **Application startup file** → `app.js`
- **Custom environment variables** → set every entry from `.env.example` (Passenger does **not** read `.env` files)
5. **Add DigitalOcean's Postgres CA** to `certs/do-ca.crt` (download from the DO Postgres dashboard) and set `DATABASE_CA_CERT_PATH=./certs/do-ca.crt`.
6. **Run the deploy script** over SSH:
```bash
bash scripts/plesk-deploy.sh
```
This installs deps, builds, runs migrations, then `touch tmp/restart.txt` to bounce Passenger.
7. **Stripe webhook** — add `https://yourdomain.com/api/stripe/webhook` in the Stripe dashboard. In Plesk → Apache & nginx → "Additional nginx directives" add:
```nginx
location /api/stripe/webhook {
proxy_request_buffering off;
}
```
8. **Auto-deploy on push** (optional) — in Plesk → Git, enable "Enable additional deploy actions" and set the script to `bash scripts/plesk-deploy.sh`.
## Environment variables
See `.env.example` for the full list. Highlights:
| Var | Purpose |
|---|---|
| `DATABASE_URL` | DO Managed Postgres connection string (`?sslmode=require`) |
| `DATABASE_CA_CERT_PATH` | Path to DO CA cert (recommended for `rejectUnauthorized: true`) |
| `SESSION_SECRET` | 32+ byte hex used to sign cookies and as Fastify cookie secret |
| `CSRF_SECRET` | 32+ byte hex for CSRF token derivation |
| `SPACES_*` | DigitalOcean Spaces credentials + bucket |
| `RESEND_API_KEY` | Transactional email |
| `STRIPE_*` | Billing |
| `PORT` | Port for Fastify (Plesk usually injects this; falls back to 8080) |
| `COOKIE_DOMAIN` | Set to your apex domain in production (e.g. `lawdesk.com`); leave blank in dev |
## Database commands
```bash
pnpm db:generate # create a new migration from schema changes
pnpm db:migrate # apply pending migrations
pnpm --filter @lawdesk/db studio # open Drizzle Studio
```
## Auth model
- Passwords hashed with **argon2id** (64MB memory cost).
- Cookie holds a 32-byte random token; the DB stores its **SHA-256 hash** (so a DB read can't impersonate users).
- Sessions are 30-day sliding (touched on every request).
- Login rate limited: 5 failed attempts per email per 15 minutes.
- All `/api/*` requests automatically attach `req.user` if a valid session cookie is present. Use `app.requireAuth` / `app.requireFirm` as preHandler guards on protected routes.
## What's next
- Wire DO Spaces upload routes for documents
- Build the `/app` dashboard (cases, time tracking, invoices)
- Free public tools (`/tools/*`)
- Stripe checkout + webhook
- Email templates via Resend
- pg-boss background jobs