# 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 ```bash 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) ```bash 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 ```bash 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