A small SaaS to run a freelance web-dev business: track clients, projects, and invoices, and let clients pay online — built by Fouad Sabbani to manage his own freelance work (ITS PROS and future client projects).
Live demo: add your deployed URL here once hosted (see Deployment below)
Running freelance client work off WhatsApp threads and notes doesn't scale. This app gives a freelancer one place to see: which clients they have, what each project's status is, and which invoices are outstanding — plus a simple portal so clients can check progress and pay without a back-and-forth.
- Backend: Node.js + Express, JWT auth, JSON-file storage (zero-setup — no database server to provision, trivial to deploy)
- Frontend: React (Vite), React Router, hand-written CSS design system
- Payments: Stripe Checkout in test mode (falls back to a mock "pay" flow automatically if no Stripe key is configured — the whole app is fully demoable with zero cost and zero external accounts)
- JWT-based login with two roles: admin (you) and client (read-only portal scoped to their own data)
- Admin dashboard: manage clients, create projects, move project status (quote → in progress → review → completed), create and track invoices
- Client portal: see project status and pay outstanding invoices
- Stripe test-mode checkout, with a webhook endpoint that marks invoices paid automatically when a payment completes
- Manual "mark paid" for cash/bank-transfer payments
Requires Node.js 18+.
# 1. Backend
cd server
cp .env.example .env # defaults work as-is for local dev
npm install
npm run seed # creates demo admin + client + sample data
npm start # http://localhost:4000
# 2. Frontend (new terminal)
cd client
cp .env.example .env
npm install
npm run dev # http://localhost:5173Demo accounts (created by npm run seed):
| Role | Password | |
|---|---|---|
| Admin | admin@demo.dev | admin123 |
| Client | client@demo.dev | client123 |
By default the app runs in mock payment mode — clicking "Pay now" marks the invoice paid instantly, no Stripe account needed.
To see a real Stripe Checkout page (still test mode, still free, no real money moves):
- Create a free Stripe account and grab your test secret key from
https://dashboard.stripe.com/test/apikeys (starts with
sk_test_). - Put it in
server/.envasSTRIPE_SECRET_KEY. - Restart the server. It now redirects to a real Stripe Checkout page,
using Stripe's test card
4242 4242 4242 4242, any future date, any CVC.
- API: Railway or Render
free tier — push the
server/folder, set the env vars from.env.example. - Frontend: Netlify or
Vercel free tier — build command
npm run build, publish directorydist, and setVITE_API_URLto your deployed API URL.
- Postgres instead of the JSON file once there's real concurrent usage
- Email notifications when an invoice is sent or paid (Resend/SendGrid)
- PDF invoice generation
- Multi-currency support (MAD / EUR)
freelance-manager/
├── server/ Express API, JWT auth, JSON-file storage
│ └── src/
│ ├── index.js Routes: auth, clients, projects, invoices, Stripe
│ ├── auth.js JWT sign/verify middleware
│ ├── db.js Tiny file-backed data layer
│ └── seed.js Demo data
└── client/ React (Vite) frontend
└── src/
├── pages/ Login, AdminDashboard, ClientPortal
├── api.js Fetch wrapper
└── AuthContext.jsx