Skip to main content

SHARED FACTS — the canonical vocabulary for TimeTracker docs

Every writer MUST read this file before writing a page. It exists so 200 pages cannot contradict each other. If a fact is here, use it verbatim. If a fact is NOT here, go read the source code — never invent it. Source repo: /Users/jaseemabbas/Documents/Lemaistre Lab/Web/timetracker/timetracker-web-3 Knowledge graph: <repo>/.understand-anything/knowledge-graph.json (2,955 nodes with summaries) Graph query helper: node <docs-repo>/.build/graph.mjs <command> <args>

1. What the product is

TimeTracker is a client-work management platform for service businesses — agencies, consultancies and professional-service teams of roughly 2 to 50 people. It replaces the usual split stack of “a project tool + a time tracker + a budget spreadsheet + an invoicing app” with one connected system. The one-line value: every task carries both operational and financial context — estimate, tracked time, billable value, cost, budget impact — so a business knows whether a client project is still profitable before it becomes a problem. The signature workflow (memorise this chain): Client → Project → Task → Estimate → Time entry → Approval → Budget impact → Invoice → Payment Product name in prose: “TimeTracker”. Never “Time Tracker”, never “TT”. Website: timetracker.in

2. The object model — say it this way every time

Workspace is the tenant. Everything lives inside exactly one workspace. A workspace has a URL slug, and every in-app route starts with it: /{workspaceSlug}/projects. A person can belong to several workspaces and switches between them at /spaces.

3. The seven roles — EXACT names and labels

Role values in the system are lowercase snake_case. The human label is title case. Never invent a role. There are exactly seven. The hierarchy is a strict subset chain: owner ⊇ admin ⊇ project_manager / finance ⊇ member ⊇ contractor ⊇ client Each lower role’s capabilities are a subset of the role above it.
  • Owner is a strict superset of Admin. The ONLY difference is workspace.delete.
  • Project Manager and Finance are siblings, not ranked against each other. PM owns delivery; Finance owns money.
  • Client has an empty capability set. A portal contact sees only what is explicitly shared with their client company.
Invitable roles: every role except owner. A client can only be invited from that client company’s detail page, because a portal contact must be tied to a client company. Inviting a bare client with no company is rejected by the server.

4. Capabilities — the 66 named permissions

A capability (also called an “action”) is a single named permission such as time.approve. Roles are seeded with a set of capabilities. Workspaces can define custom roles, and individual people can have specific capabilities denied. The full list, grouped:
  • Workspace: workspace.updateSettings, workspace.delete
  • People: member.invite, member.create, member.changeRole, member.remove, role.manage, invite.revoke, group.manage, audit.read
  • Clients: client.view, client.manage
  • Projects & tasks: project.manage, tag.manage, task.create, task.edit, task.delete, task.reviseEstimate, task.bulkEdit
  • Rates: rate.manage, rate.viewBilling, rate.viewCost
  • Time: time.track, time.edit, time.viewCost, time.submit, time.approve, time.adjust, period.close, time.viewOthers, time.editOthers, time.submitOnBehalf, time.reopenApproval, time.remind
  • Money: budget.manage, invoice.manage, payment.record
  • Expenses: expense.submit, expense.approve, expenseCategory.manage
  • Time off: leave.request, leave.approve, leave.viewOthers, leave.managePolicy
  • Reports: report.view, report.create, report.edit, report.manage, report.share, report.schedule, report.export
  • Time clock: timecard.clock, timecard.view, timecard.manage, timecard.approve, timecard.submit, timecard.submitOnBehalf, timecard.reopen
  • Planner: block.manage, block.manageOthers
  • Admin & integrations: webhook.manage, data.export, billing.manage, location.manage, schedule.view, schedule.manage
Canonical page: /concepts/roles-and-capabilities. Every other page links there rather than re-explaining the model. Two rules writers get wrong:
  1. A capability is not a scope. time.viewOthers says you MAY view other people’s time. Supervision scope says WHOSE time. A manager with time.viewOthers still only sees the people in their scope. Always separate the two.
  2. Owner-only actions cannot be granted to anyone else, and some actions are deny-only overridable per person. Do not promise a capability can be freely moved between roles without checking OVERRIDABLE_ACTIONS and OWNER_EXCLUSIVE_ACTIONS in src/modules/workspace/domain/permissions.ts.

5. Apps (modules) — the 15 togglable areas

An App is a switchable area of the product. Workspace settings → Apps (/{slug}/settings/apps) turns each on or off. Turning one off HIDES it; it never deletes data. They render in three groups: Work, Money, Connections. Dependencies are enforced. You cannot turn on Time Clock without Work schedules, because expected minutes and absence detection resolve from the schedule. Turning OFF a required app warns about the dependents it will take with it. Reports has no plan feature — the app is on every plan. What the plan tiers is the depth: custom reports, scheduling and export are Pro. The two gates are different things. An app being OFF means hidden and gone from the sidebar. A plan not including it means it STAYS in the sidebar and shows a blurred paywall. Never conflate “turned off” with “not on your plan”.

6. Plans — Free and Pro

There is one paid tier, Pro, on two cadences (monthly and yearly), plus a permanent Free tier. Billing runs through Paddle as merchant of record, which handles global tax and VAT. The dividing line is capture vs resolution.
  • Free = record your work. Anyone can track time, fill a timesheet, submit an expense, request leave, and clock in and out.
  • Pro = resolve it. Only a paying workspace can APPROVE any of it, invoice it, or take it out of the product as a file.
Free features: time_tracking, projects_tasks, timesheets, attendance, time_off, expenses. Pro adds: approvals, planner, location_rules, invoicing, payments, budgets, profitability, client_portal, advanced_reports, integrations, exports. Free seat limit: 3 people. The 4th person is the paid wall. Seats count people with access, not just staff: every active membership of every role PLUS every outstanding invitation. An open invite is access. A client-portal contact is a login like any other, so portal contacts count toward seats. Being over the cap is legal and never punished. A 5-person workspace that drops to Free keeps all 5 people working. The rule bounds only the NEXT add — blocked while the count is at or above 3, allowed again if someone leaves. A lapse never destroys data. A Free workspace accumulates submissions it cannot clear, and clears the whole backlog the day it pays. profitability is an honest half-gate. It gates exactly one write: setting a cost rate. Cost, revenue and margin already recorded stay readable on Free. Billing rates stay free to set. Who may SEE those numbers is a capability question (time.viewCost, rate.viewCost), never a plan question.

7. Statuses — the exact sets

Never invent a status. These are the real ones. Timesheet: draftsubmittedapproved / rejected, plus locked. Approved time is locked so only an admin can change it. Invoice: draft, sent, viewed, partially_paid, paid, overdue, void. Allowed transitions:
  • draft → sent, void
  • sent → viewed, partially_paid, paid, overdue, void
  • viewed → partially_paid, paid, overdue, void
  • partially_paid → paid, overdue, void
  • overdue → partially_paid, paid, void
  • paid and void are terminal.
Expense: draft, submitted, approved, rejected, invoiced. Leave request: pending, approved, rejected. Task: tasks move through per-project Sections, which the project defines. Filters also expose a status field with values including todo, in_progress, done. Sections are the user-facing concept; explain sections first. Budget kind: hours or money. Periodicity: one_time or monthly (a monthly budget is a recurring retainer).

8. Terms readers confuse — always disambiguate

Write a short “X vs Y” block wherever these appear.

9. The example cast — REUSE THESE across every page

Do not invent new companies or people. Consistency is what makes the docs feel like one product. The workspace: Northwind Studio — a 12-person digital agency. Slug northwind. People: Clients and projects: Standard numbers — use these so arithmetic matches across pages:
  • Sarah Lin billable rate: 100/hour.Costrate:100/hour**. Cost rate: **45/hour.
  • Jonas Bergman billable rate: 120/hour.Costrate:120/hour**. Cost rate: **60/hour.
  • Ana Ferreira (contractor) billable rate: 80/hour.Costrate:80/hour**. Cost rate: **55/hour.
  • Workspace currency: USD.
  • A standard week is 40 hours, Monday to Friday, 9:00–17:00.
Worked example everyone can reuse:
Sarah tracks 3 hours on “Homepage wireframes” for Bluebird Coffee — Website Redesign. Her billable rate is 100/hour,sotheentryisworth100/hour, so the entry is worth **300** to the project. Her cost rate is 45/hour,soitcostsNorthwind45/hour, so it costs Northwind **135**. The margin on those 3 hours is $165.

10. Voice and writing rules

  • Reading level: 8th grade. Short sentences. Simple words. One idea per sentence.
  • Second person. “You create a project.” Not “the user creates a project.”
  • Present tense. “The timer stops.” Not “the timer will stop.”
  • Say the outcome first, then the steps.
  • En dash (–) only. Never an em dash. Never a hyphen used as a separator.
  • Never say “simply”, “just”, “easy”, “obviously”.
  • Never invent UI. If you did not see the button in the source, do not describe it.
  • Every number must be arithmetically correct. Check your maths.
  • Use bold for UI labels: click Save. Use code for values and keys.
  • Prefer a short table over a long paragraph.
  • Paragraphs are 1–3 sentences. Never a wall of text.
Do NOT document (out of scope, decided):
  • Biometric attendance devices (eSSL / ZKTeco) — a private client-specific module
  • convex/lib/customModules.ts and any custom module
  • The v1 → v3 migration tooling
  • The /dev/emails route
  • Internal architecture, Convex function names, file paths, or the tech stack. These are USER docs. A reader never sees a table name.

11. Mintlify page format

Every .mdx file starts with frontmatter:
  • title — matches real search intent. Sentence case. Under 60 characters.
  • description — 120–160 characters, useful to a human AND a search engine. Never keyword stuffing. It is the meta description.
Components available (use them where they genuinely help, do not decorate):
Every page ends with a “Related guides” section — a <CardGroup> or a short bullet list of 3–6 internal links. Internal links are absolute paths with no extension: /timesheets/submit-a-timesheet. Standard page skeleton (adapt, do not force):
  1. One or two sentences answering the reader’s question immediately.
  2. ## What is X? — plain definition.
  3. ## When to use it — realistic situations.
  4. ## How it works — the concept.
  5. ## How to <do the thing><Steps>.
  6. ## Example — use the cast from section 9.
  7. ## Options and settings — every field and control.
  8. ## Permissions — which roles and capabilities.
  9. ## What happens next — downstream effects.
  10. ## Common questions<AccordionGroup>, real search questions.
  11. ## Troubleshooting — real problems.
  12. ## Related guides — internal links.

11a. Corrections found while writing — DO NOT regress these

These were all verified against source after the first draft. Several contradict what a reasonable person would assume, which is exactly why they are written down. Workspace
  • The slug cannot be renamed. No mutation writes it after creation. Renaming the workspace does not change the URL, which is why old links keep working. Never warn a reader to “change it early”.
  • There is no self-service “leave workspace” control. Someone with member.remove removes you, or you delete your account.
  • Editable workspace settings are exactly: name, base currency, timezone, date format, time format, week start, trash retention, timesheet period, invoice sender.
Rates
  • There is no workspace default rate. The resolver has a fifth tier but nothing ever supplies it. The real chain is task → project member → person → client, then unresolved. A missing rate is unpriced, never $0.
  • Cost rates have exactly one tier: the person.
  • Finance holds no rate capabilities at all – no rate.manage, no rate.viewBilling, no rate.viewCost – yet holds invoice.manage and payment.record. Counter-intuitive, and true.
Roles and permissions
  • ACTIONS is 66. The role editor shows ~62 checkboxes because owner-exclusive and non-assignable actions are not offered. Say 66 for capabilities, and explain the editor’s count where it appears.
  • Only Owner and Client are locked. Admin, Project Manager, Finance, Member and Contractor are editable, renameable and deletable despite their System badge.
  • Supervision scope has five levels: none, project, group, project_group, workspace. Only workspace widens PROJECT reach; the middle three differ only in which PEOPLE you reach.
  • Per-person exceptions are subtractive only, and today the only exposed switch is Clock in and out. OVERRIDABLE_ACTIONS is a per-project grant for task.reviseEstimate – the opposite of a deny. Do not describe it as one.
  • You see a client only when you can see one of their projects. There is no client scope.
Statuses
  • Timesheets have two layers: the entry chain (draft → submitted → approved → locked → invoiced) and the submission aggregate (submitted / approved / changes_requested / withdrawn). rejected is derived, never stored. Rejecting and reopening both land on changes_requested.
  • Leave has a fourth status, withdrawn, alongside pending / approved / rejected.
  • Nothing sets an invoice to viewed or overdue. Only send, void and payment re-derivation move an invoice. Document the transition table, but say so honestly.
Plans
  • Trial is 14 days, granted per person on their first workspace.
  • past_due has a 7-day grace period, then Free.
  • Trash retention is selectable: 7 / 14 / 30 / 60 / 90 days, default 30.
Notifications
  • There is no full-page Inbox – the bell popover is the whole surface (50 rows, badge caps at 99+).
  • /settings/notifications is the workspace defaults page. Personal settings live on the profile.
  • Digests have no user-facing control. Do not invent a toggle. Quiet hours are gone.
Product gaps to write around, not describe
  • No bulk importer exists (no CSV, no Toggl/Clockify/Harvest).
  • No project templates reachable in the UI.
  • No workspace FX-rate screen – only the per-invoice exchange-rate section.
  • Invoice Terms/Notes are stored but never rendered.
  • Auto-create time entries on leave policies and holidays is not wired to time entries.

12. Accuracy contract

You have full tool access to the product repo. Ground every claim.
  • Read the actual page component under src/app/[workspaceSlug]/… for what is on screen.
  • Read src/modules/<domain>/ui/ for the forms, fields, filters and dialogs.
  • Read src/modules/<domain>/domain/ for the rules, states and maths.
  • Query the graph for a fast orientation: node .build/graph.mjs tag <tag>.
If you cannot confirm a behaviour from the source, leave it out. A missing sentence is fine. A wrong sentence is not — this product is a system of record for time and money, and a wrong doc costs a customer real money.