← back to projects
LIVE2025

Session Logger — Freelance Time Tracker

Freelancers and consultants who bill clients hourly typically juggle a stopwatch, a notes app, and a spreadsheet. Session Logger replaces that entire workflow with a single self-hosted web app. One-click session start with a live elapsed timer, concurrent-session guard (409 on duplicates), billing snapshots that freeze the rate at session start so future rate changes never corrupt historical invoices, monthly billing breakdowns with CSV export, and a filterable session history. The timer initialises from the real start timestamp on every page load — a browser refresh never resets the clock. The entire stack runs on a single VPS with zero external SaaS dependencies.

$ Architecture

  • Frontend: React 18 + TypeScript + Vite 5. React Query v5 as the single source of truth for all server state; Zustand only for auth token management. Tailwind CSS dark-only design.
  • Backend: Node.js + Express + TypeScript. Zod schema-first validation on every request body and query parameter. JWT auth (jsonwebtoken + bcryptjs).
  • Database: Prisma v5 ORM over PostgreSQL 16 in Docker Compose. Billing snapshot pattern — client rate copied into session row at start time.
  • Timer architecture: useTimer hook initialises elapsed seconds in useState lazy initialiser (Date.now() - startTime), not in useEffect — no "00:00:00" flash on page load or refresh.
  • Concurrent session guard: API returns 409 Conflict if a second session is started for the same client. Server-side duration and cost computation on session close.
  • Infra: single VPS, Docker Compose for Postgres, nohup process for the Node server, nginx reverse proxy. ./start.sh builds frontend + backend, runs migrations, and starts the server.

$ Tech Stack

ReactTypeScriptViteTailwind CSSReact QueryZustandAxiosNode.jsExpressPrismaPostgreSQLZodJWTDockerNginx

$ Outcomes

Dashboard with real-time stat cards: total clients, sessions this month, revenue this month, currently active sessions — auto-refreshes every 10 seconds
One-click session start/stop with live HH:MM:SS elapsed timer initialised from real start timestamp on every page load
Billing snapshot: client rate frozen at session start — rate changes never retroactively alter past invoices
Concurrent session guard: 409 Conflict on duplicate session start for the same client
Monthly billing reports: filter by month (up to 12 months back) and by client, with per-client summary and grand total row
CSV export for dropping straight into an invoice template or accountancy tool
Full session history: filterable by client, status (ACTIVE / COMPLETED / ABANDONED), and date range
Client CRUD with per-client hourly/fixed rate, optional monthly budget, tags, and notes
Secure auth: bcrypt + JWT, 401 auto-redirect, token stored in localStorage with Axios interceptor
Self-hosted, zero external SaaS dependencies — entire stack on a single VPS