VibeWeek
Home/Grow/Time Tracking & Time Entry In-Product — Chat Prompts

Time Tracking & Time Entry In-Product — Chat Prompts

⬅️ Back to 6. Grow

If your B2B SaaS serves any time-based-billing, project-management, services, agency, consulting, legal, or freelancer use case — eventually customers will ask: "Can we track time inside [Product] instead of using a separate tool?" Toggl, Harvest, Clockify, Everhour — these are popular standalone tools, but customers prefer one-app workflow. The naive shape: "Hours" field on tasks. Works for a single freelancer; falls over the moment a team needs timesheets, approvals, project profitability, billable vs non-billable distinction, time off / PTO, or integrations with billing / payroll.

A real time-tracking system handles: timer + manual entry UX, project + task allocation, billable/non-billable, approval workflow, timesheet review, exports, integrations with accounting / billing / payroll, and reporting. Done well, time tracking becomes a sticky feature that compounds product value (customers' billing becomes dependent on your product). Done badly, customers use Toggl alongside and complain about double-entry forever.

This chat walks through implementing real time-tracking + time-entry: data model, UX patterns (timer vs manual), approval workflow, integrations, edge cases, and operational realities.

What you're building

  • Time entry data model
  • Two entry modes (timer + manual)
  • Project / task / category allocation
  • Billable / non-billable classification
  • Daily / weekly timesheet UX
  • Approval workflow (manager → approve → submit to billing)
  • Reporting (per project, per person, per client)
  • Exports + integrations (CSV, QuickBooks, Xero, payroll)
  • Timezone handling
  • Edge cases (overlapping timers, missing entries, edits to approved time)

1. Decide the scope

Help me decide what shape of time tracking to ship.

Three increasingly-deep shapes:

LEVEL 1: BASIC TIME LOG (the simplest start)
- Add hours to tasks
- Daily total view
- No approvals; no exports
- Pros: ships in 1-2 weeks
- Cons: not a complete time-tracking solution

LEVEL 2: FULL TIME TRACKING (timer + timesheets)
- Timer + manual entry both supported
- Daily / weekly timesheet
- Project + billable allocation
- Submission + approval workflow
- Reports + exports
- Pros: 6-12 weeks; stickiness
- Cons: lots of edge cases

LEVEL 3: BILLABLE-OPS-COMPLETE
- Level 2 + invoicing / billing integration
- Per-client rate cards
- Profitability reporting
- Time-off / PTO accounting
- Payroll integration
- Pros: enterprise-grade; replaces standalone tools
- Cons: 16-24+ weeks; ongoing complexity

DEFAULT FOR MOST B2B SaaS:
- Year 1: Level 1 (basic; if customers want it)
- Year 2: Level 2 (full tracking) when customer pull is clear
- Year 3+: Level 3 only if it fits your product positioning (agency / legal / consulting tool)

Don't pre-build Level 3 unless you're explicitly a billable-services SaaS.

Output: scope decision; explicit boundary.

Output: scope statement.

2. Design the data model

Schema for time tracking:

time_entries (
  id              uuid pk
  workspace_id    uuid not null
  user_id         uuid not null  -- who logged the time
  project_id      uuid  -- nullable; some entries don't tie to project
  task_id         uuid  -- nullable
  client_id       uuid  -- nullable; for billing
  category        text  -- 'engineering', 'meeting', 'pto', 'admin', etc.
  description     text
  starts_at       timestamptz  -- start time (or null for manual entry without exact time)
  ends_at         timestamptz  -- nullable while timer running
  duration_seconds int  -- denormalized for query speed
  date            date  -- date the work was performed (in user's timezone)
  is_billable     bool default false
  billable_rate_cents int  -- denormalized at entry time (rate at time of work)
  status          text  -- 'draft', 'submitted', 'approved', 'rejected', 'invoiced'
  approved_by     uuid
  approved_at     timestamptz
  invoice_id      uuid  -- nullable; if rolled into an invoice
  created_at      timestamptz
  updated_at      timestamptz
  
  -- Audit: changes after approval require special handling
  approved_locked bool default false
)

INDEXES:
- (workspace_id, user_id, date) — for timesheet queries
- (workspace_id, project_id, date) — for project reports
- (workspace_id, client_id, status='approved') — for invoicing
- (status='submitted') — for approval queue

active_timers (
  user_id         uuid pk  -- only one active timer per user
  workspace_id    uuid
  project_id      uuid
  task_id         uuid
  description     text
  started_at      timestamptz
)

UNIQUE PER user_id (only one running timer at a time per user)

projects + tasks: assume already exist in your model

clients (
  id              uuid pk
  workspace_id    uuid
  name            text
  default_rate_cents int  -- default billable rate
  rate_card       jsonb  -- per-role / per-task rates
)

approval_workflows (
  workspace_id    uuid pk
  requires_approval bool default true
  approver_role   text  -- 'manager', 'project_lead', 'admin'
  auto_approve_below_hours numeric  -- e.g., entries < 8 hours auto-approved
)

Implement:
1. Migrations for time_entries, active_timers, clients, approval_workflows
2. Indexes for hot queries
3. RLS / multi-tenancy
4. Validators (no overlapping timers, etc.)

Output: schema for tracking.

3. Implement timer + manual entry UX

Two entry modes:

A. TIMER MODE
- Click "Start" on a task
- Timer runs; visible across app (header bar)
- Click "Stop" → entry created
- Or: switch to another task → previous timer stops; new starts

UX:
- Persistent timer widget in header
- Project + task fields (selectable mid-timer)
- Description field
- One timer at a time per user (system enforced)

Implementation:
- POST /api/timers/start { project_id, task_id, description }
- DELETE /api/timers/stop → creates time_entry
- Real-time UI update via subscription / refresh

Anti-pattern:
- Multiple concurrent timers (confusing; double-counts)

B. MANUAL ENTRY MODE
- Click "Add time"
- Form: date, project, task, hours, description, billable
- Submit → creates time_entry with manual flag

UX:
- Date defaults to today
- Project / task last-selected memory
- "Time spent" input formats: hh:mm or decimal hours
- Backfill multiple days at once

Implementation:
- POST /api/time-entries { date, project_id, task_id, hours, description, billable }

Both modes:
- Auto-save drafts; not require submission
- Edit-in-place
- Bulk-edit support

Mobile:
- Timer always accessible (notification with current timer)
- Quick-entry form mobile-optimized

Implement:
1. Timer start/stop UI + endpoints
2. Manual entry form
3. One-timer-per-user enforcement
4. Persistent timer widget
5. Mobile timer
6. Edit / delete entries

Output: entry UX users use daily.

4. Build the timesheet (weekly review + submission)

Timesheet UX:

Page: /time/timesheets

Layout:
- Week selector (current week, prev / next)
- Day-by-day grid
- Per day: list of entries
- Summary: total hours, billable hours, % billable
- Per-project rollup
- Submit button

Per-week submission:
- Customer selects week
- Reviews entries
- Edits / adds missing
- Clicks "Submit for approval"
- Status: draft → submitted

Per-day quick entry:
- Click day → modal with all entries for that day
- Add / edit / delete

Edge cases:
- Past weeks: show but flag if not yet submitted
- Future weeks: don't allow entries (unless intentional pre-planning)
- Submitted weeks: read-only unless reverted

Approval-side UX (for managers):

Page: /time/approvals

- Queue of submitted timesheets
- Per submission: user, period, total hours, summary
- Click → detail view
- Approve / Reject (with reason)
- On approve: status → 'approved'; lock entries (unless admin overrides)
- On reject: notify user; allow re-submit

Auto-approval:
- Configurable per workspace
- Auto-approve below threshold (e.g., < 40 hours/week, no edge cases)
- Above threshold: manual review

Notifications:
- Submitted: notify approver
- Approved: notify user
- Rejected: notify user with reason

Implement:
1. Weekly timesheet UI
2. Submission flow
3. Approval queue UI
4. Notification triggers
5. Auto-approval logic
6. Lock-after-approval enforcement

Output: weekly review + approval workflow.

5. Build reports + exports

Reports needed:

Per-project:
- Total hours
- Billable hours
- Hours by user
- Trend over time
- Budget vs actual

Per-person:
- Total hours per period
- Billable %
- Project breakdown
- Manager view: team-wide

Per-client:
- Hours by project
- Billable + ready-to-invoice hours
- Trend over time

Per-category:
- Time on meetings vs admin vs deep work
- Trend analysis

Export formats:
- CSV (most common)
- Excel
- PDF report (formatted)
- API access (programmatic)

Filtering:
- Date range
- Project / client / user
- Status (draft / approved / invoiced)
- Billable / non-billable

Implement:
1. Per-project report
2. Per-person report
3. Per-client report
4. Date-range picker + filters
5. CSV / Excel / PDF exports
6. Schedule: weekly / monthly auto-export to admin

Output: reports for billing + management.

6. Integrations (the stickiness multiplier)

The killer feature: integrations with billing / accounting / payroll.

Integration targets:

ACCOUNTING:
- QuickBooks Online
- Xero
- Zoho Books
- Sage
- Wave

What syncs:
- Approved billable hours → invoice line items
- Per-client; per-project; per-rate
- Customer mapping (your client_id → their customer)

PAYROLL:
- Gusto, Rippling, ADP
- Approved hours → payroll period
- Hourly employees: hours fed in
- Salaried with overtime tracking

PROJECT BILLING:
- Direct invoice generation (if you have billing module)
- Or: send to external billing tool

CRM:
- Salesforce, HubSpot
- Customer engagement / project hours visible to sales

CALENDAR:
- Google / Outlook integration
- Auto-suggest entries based on calendar events

Implementation per integration:
- OAuth setup with vendor
- Mapping UI (your projects / clients to theirs)
- Sync schedule (daily; on-demand)
- Conflict resolution (which side wins on edit?)
- Audit log of syncs

Webhook outbound:
- Time-entry-created webhook for customer's automations
- Invoice-ready webhook

Implement:
1. QuickBooks / Xero integration as v1
2. Customer mapping UI
3. Scheduled sync
4. Manual force-sync
5. Conflict + error reporting
6. API + webhooks for customer DIY

Output: integrations that make customers stay.

7. Timezone + DST handling

Time entries cross timezones; DST shifts; international teams.

Rules:

A. Entry timezone:
- Capture in user's local timezone (IANA)
- Store starts_at + ends_at as UTC; date as local-date
- Display in viewer's timezone (or user's choice)

B. Date attribution:
- "Date of work" = local date when work started
- A timer starting 11:30pm and ending 1:30am: 2-hour entry on START date
- Or: split across days (some products do this; complex)

C. DST transitions:
- Spring-forward: 1am-3am skip; entries crossing this period adjust
- Fall-back: 1am-3am happens twice; mark explicitly

D. International team:
- Each user's local timezone
- Aggregate reports in workspace's timezone
- Or: per-report timezone choice

E. Travel:
- User in Tokyo for week; entries should still be in their workspace's primary tz?
- User choice: entry-tz follows them OR follows workspace
- Default: user-tz

Implementation:
- Always store IANA timezone with entry
- starts_at / ends_at in UTC
- date field in user's local time at entry creation
- Render in viewer's tz with appropriate notes

Anti-patterns:
- Storing local time without tz
- Using server tz
- Letting tz auto-change without notice

Output: tz handling that doesn't betray customers.

8. Edge cases + operational realities

Walk me through:

1. Active timer crashes (browser closed; no stop)
- On reconnect: detect orphaned timer
- Prompt: "Was this still running?" (yes / no / round to nearest 15min)
- Don't auto-stop without user input

2. Multiple devices (timer on phone + laptop)
- Single timer per user (system enforced)
- Stopping on one device stops everywhere
- Sync via subscription

3. Entry > 24 hours
- Validation: warn at 24+ hours
- Hard error at 168 hours (week)
- Likely a bug or forgot-to-stop scenario

4. Editing approved entries
- Lock by default (compliance)
- Admin override with audit log
- "Unlock" button rarely used

5. Forgot to log time (multi-day backfill)
- Allow up to 30 days back (configurable)
- Beyond: require admin permission
- Audit who backfilled what

6. Project deleted; entries reference it
- Soft-delete project (don't lose entries)
- Allow re-categorization to "Archived"

7. User leaves company
- Their entries preserved (audit + billing)
- Reassign approver responsibilities

8. Currency conversion (international clients)
- Per-client currency
- Rate cards in their currency
- Reports in workspace base currency (with FX conversion)

9. Overtime tracking
- Workspace setting: standard hours/week (e.g., 40)
- Above standard: flag as overtime
- Pay rate may differ (1.5x)

10. PTO / time off
- PTO tracked separately from billable
- Counts toward "total hours" but not "billable"
- Approval flow may differ

11. Public holidays
- Per-region holiday calendars
- Auto-fill (optional)

12. Entry with future date
- Allow (intentional pre-planning)
- Don't auto-submit until date passes

13. Bulk operations (delete / re-categorize / approve)
- Bulk select; bulk action
- Audit bulk actions

14. Mobile offline
- Local cache; sync on reconnect
- Conflict resolution if edits diverge

15. Client viewing time
- Some clients want visibility into hours billed
- Read-only client portal
- Per-project sharing toggle

For each: code change + UX impact + ops consideration.

Output: ops handling.

9. Recap

What you've built:

  • Time-entries data model
  • Timer + manual entry both
  • Weekly timesheet + submission
  • Approval workflow
  • Reports per project / person / client
  • Exports (CSV / Excel / PDF)
  • Integrations: QuickBooks / Xero (v1), more later
  • Timezone + DST handling
  • Edge cases (forgot-to-stop, backfill, deletion, etc.)

What you're explicitly NOT building in v1:

  • Native invoicing (use accounting integration)
  • Native payroll (use payroll integration)
  • Per-task time budgets (defer)
  • AI-suggested time entries from calendar / activity (defer; nice-to-have)
  • Productivity-pulse insights (defer; different category)
  • Cross-tenant time-sharing (anti-pattern)

Ship Level 1 in 2 weeks. Level 2 in 8-12 weeks. Level 3 only if billable-services SaaS.

The biggest mistake teams make: shipping time tracking without integrations. Time is logged but doesn't flow to billing / payroll → customers maintain Toggl alongside.

The second mistake: approval flow without lock-after-approve. Customers edit time after billing → audit chaos.

The third mistake: forgetting timezone. International teams = wrong reports.

See Also