Income logging, projections, and quarterly estimated tax calculations for US 1099 contractors.
Find a file
2026-03-04 21:21:59 -05:00
client initial code commit 2026-03-04 21:21:59 -05:00
server initial code commit 2026-03-04 21:21:59 -05:00
.gitignore initial code commit 2026-03-04 21:21:59 -05:00
package-lock.json initial code commit 2026-03-04 21:21:59 -05:00
package.json initial code commit 2026-03-04 21:21:59 -05:00
README.md initial code commit 2026-03-04 21:21:59 -05:00

ten99timecard

Income logging, projections, and quarterly estimated tax calculations for US 1099 contractors. Entirely client-side by default — your data is encrypted with your password and stored in a browser cookie. Optionally sync to a self-hosted MongoDB backend (still encrypted end-to-end; the server never sees plaintext).

Not tax advice. Calculations are federal-only approximations. Talk to a CPA.


What's inside

Page What it does
Dashboard Configurable stat widgets + charts. YTD income, projected annual tax, next quarterly due date.
Ledger Three tabs: Work Log (non-taxable billable record — flat amount or hours×rate), Payments (taxable 1099 income), Expenses (with deductible flag). Each is a year→month→day→item collapsible spreadsheet with global expand-to-level controls. Period summaries show totals, per-child averages, and linear projections.
Tax Full estimated-tax breakdown: SE tax (with SS wage-base cap + additional Medicare), QBI deduction, progressive federal brackets, safe harbor (100%/110% rule), quarterly schedule with past-due flags. Fields you haven't filled in (prior-year AGI, W-2 withholding, etc.) appear as highlighted prompts explaining why they'd sharpen the estimate.
Timer Billable-work stopwatch. Start / Pause / Split / Reset. Each split captures the rate at split time (changing the rate never rewrites history). Editable split table with two-step confirm. One-click push to Work Log. Logged rows get a badge. Crash-proof: state is heartbeated to a cookie every second; if the page reloads while running, a red banner shows exactly when you crashed, when you came back, and the gap — with a button to subtract the gap or keep it (because you were working during the outage).
Settings Theme picker (10 themes × dark/light), default hourly rate, storage mode (cookie / file / cloud), encrypted file import/export.

Themes

Standard · Sakura · Pumpkin · Fall · Aqua · Lavender · Comic · Manga · High Contrast · Cyberpunk — each in dark & light.


Quick start

npm install
npm run dev            # client on http://localhost:5173

The app works out of the box with cookie storage. No server, no database, no account. Open the page, create a local vault (username + password), start logging. Your password derives an AES-256-GCM key via PBKDF2 (100k rounds); the cookie holds only ciphertext.

Run the cloud sync server (optional)

cp server/.env.example server/.env   # edit MONGO_URI + JWT_SECRET
npm run dev:server                   # Express on http://localhost:4000

Then switch storage mode to Cloud in Settings. The server stores one opaque blob per user. Plaintext never leaves the browser.

Google OAuth (optional)

Fill GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET in server/.env. Without these the server still serves email+password auth.


Tests

npm test           # 155 tests: 135 client (Vitest+RTL) + 20 server (supertest+mongodb-memory-server)
npm run build      # tsc --noEmit && vite build, both workspaces

Coverage spans the tax engine, crypto round-trip, cookie chunking, statistics rollup/projection, timer crash recovery, store CRUD, and component interaction.


Stack

Client: Vite · React 18 · TypeScript 5 · Zustand · React Router · Recharts · date-fns · Web Crypto API Server: Express · MongoDB · bcrypt · jsonwebtoken · Passport (Google OAuth) · zod Testing: Vitest · React Testing Library · jsdom · supertest · mongodb-memory-server

Everything is MIT/Apache/BSD licensed.


Tax math (summary)

  • SE tax = 15.3% of netProfit × 0.9235 (12.4% Social Security up to wage base, 2.9% Medicare uncapped, +0.9% additional Medicare above threshold)
  • Half of SE tax is an above-the-line deduction
  • QBI §199A = 20% of qualified business income, limited to 20% of taxable income, phased out above threshold
  • Taxable income = gross deductible expenses ½SE QBI standard deduction other adjustments
  • Safe harbor = pay the lesser of 90% of current-year tax or 100% (110% if prior AGI > $150k) of prior-year tax, split across four quarters
  • Tax year data shipped for 2024 and 2025; unknown years fall back to closest

State tax is intentionally out of scope.


Storage model

Mode Where Encrypted?
Cookie (default) document.cookie, chunked at ~3.8KB, mirrored to localStorage AES-256-GCM
File Download/upload .t99 blob Same key derivation
Cloud PUT /api/data on your server Encrypted before upload

Ciphertext format: base64( salt[16] || iv[12] || aes-gcm-ciphertext ). Lose your password → lose your data. That's the point.


License

MIT