Time Tracker & Invoicing app for 1099 contractors
  • JavaScript 96.8%
  • CSS 2.6%
  • Dockerfile 0.3%
  • HTML 0.3%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-09-08 05:59:42 -04:00
.github/workflows Add GitHub Release creation on version tags 2026-02-09 08:18:02 -05:00
migrations Fix rate snapshotting, payment terms, filters and PDF pagination 2026-09-06 10:57:53 +00:00
public Initial commit: TimeTracker app 2026-02-09 08:07:28 -05:00
server Warn instead of exiting on a short ENCRYPTION_KEY 2026-09-06 23:06:34 +00:00
src Fix rate snapshotting, payment terms, filters and PDF pagination 2026-09-06 10:57:53 +00:00
test Warn instead of exiting on a short ENCRYPTION_KEY 2026-09-06 23:06:34 +00:00
.dockerignore Initial commit: TimeTracker app 2026-02-09 08:07:28 -05:00
.gitignore Initial commit: TimeTracker app 2026-02-09 08:07:28 -05:00
context.md Fix rate snapshotting, payment terms, filters and PDF pagination 2026-09-06 10:57:53 +00:00
docker-compose.yml Update docker-compose.yml 2026-09-08 05:59:42 -04:00
Dockerfile Fix rate snapshotting, payment terms, filters and PDF pagination 2026-09-06 10:57:53 +00:00
eslint.config.js Fix rate snapshotting, payment terms, filters and PDF pagination 2026-09-06 10:57:53 +00:00
index.html Initial commit: TimeTracker app 2026-02-09 08:07:28 -05:00
package-lock.json Fix rate snapshotting, payment terms, filters and PDF pagination 2026-09-06 10:57:53 +00:00
package.json Fix rate snapshotting, payment terms, filters and PDF pagination 2026-09-06 10:57:53 +00:00
postcss.config.js Initial commit: TimeTracker app 2026-02-09 08:07:28 -05:00
README.md Update README.md 2026-09-08 05:57:50 -04:00
tailwind.config.js Initial commit: TimeTracker app 2026-02-09 08:07:28 -05:00
vite.config.js Initial commit: TimeTracker app 2026-02-09 08:07:28 -05:00

TimeTracker

Time tracking and invoicing app for 1099 contractors. Log hours, manage clients, generate PDF invoices, and track income analytics.

Features

  • Time Entries — Log hours by client and task with rate snapshotting
  • Invoicing — Generate, email, and track PDF invoices (draft → sent → paid)
  • Dashboard — Revenue analytics, charts, and income breakdowns
  • Clients — Manage clients, contacts, and billing addresses
  • Auto-Invoicing — Scheduled automatic invoice generation (weekly/biweekly/monthly)
  • Customizable Invoices — Logo, accent color, font size, footer text
  • Email — Send invoices directly via Gmail SMTP
  • Dark Mode — Full light/dark theme support
  • Mobile Friendly — Responsive card layouts on small screens

Tech Stack

  • Backend: Node.js, Express, SQLite (WAL mode)
  • Frontend: React, Vite, Tailwind CSS
  • PDF: PDFKit
  • Charts: Recharts
  • Email: Nodemailer (Gmail SMTP)

Quick Start

export ENCRYPTION_KEY=$(openssl rand -hex 32)   # generate once, then keep it
docker compose up -d

Access at http://localhost:3002

Keep ENCRYPTION_KEY safe and stable. It encrypts the Gmail App Password at rest; if it changes, that password can no longer be decrypted and must be re-entered. A key shorter than 16 characters logs a warning at startup but still runs, so an existing install is never forced into a rotation it did not ask for.

There is no authentication. Anyone who can reach the port can read and change all financial data and send mail through the configured Gmail account. Run it only on a trusted network, or put a reverse proxy with authentication in front of it.

Docker Compose

Images are published to this Forgejo instance's own container registry and can be pulled without authenticating:

services:
  timetracker:
    image: git.serversatho.me/serversathome/timetracker:latest
    ports:
      - "3002:3000"
    volumes:
      - timetracker-data:/data
    environment:
      - NODE_ENV=production
      - ENCRYPTION_KEY=${ENCRYPTION_KEY:?ENCRYPTION_KEY must be set}
      - TZ=America/New_York
    restart: unless-stopped

volumes:
  timetracker-data:

Update with docker compose pull && docker compose up -d.

Every push is tagged with its short commit SHA alongside latest, so pinning — or rolling back — is just:

image: git.serversatho.me/serversathome/timetracker:ad6493a

Building from source instead

Skips the registry entirely — useful when testing an unmerged change:

build:
  context: https://git.serversatho.me/ServersatHome/timetracker.git#main

Then docker compose build --no-cache && docker compose up -d.

Development

git clone https://git.serversatho.me/ServersatHome/timetracker.git
cd timetracker
npm install
ENCRYPTION_KEY=dev-only-key npm run dev

Runs the Express backend (with node --watch) and the Vite dev server concurrently.

npm test        # unit + HTTP integration tests, against a scratch database
npm run lint    # eslint

Environment Variables

Variable Required Description
ENCRYPTION_KEY Yes Key for encrypting the Gmail App Password at rest. Missing is fatal at startup; shorter than 16 characters only warns
NODE_ENV No Set to production for Docker deployment
BASE_URL No Base URL for the app (used in emails)
TZ Recommended Server timezone, e.g. America/New_York. Drives "today", invoice due dates and the auto-invoice schedule. Defaults to UTC, which dates evening entries to the following day for anyone west of it
DB_PATH No Override the SQLite file location (used by tests)

License

Private