[{"data":1,"prerenderedAt":530},["ShallowReactive",2],{"navigation":3,"\u002Fguide\u002Fprojects-clients-tasks":80,"\u002Fguide\u002Fprojects-clients-tasks-surround":525},[4,9,14,50,75],{"title":5,"path":6,"stem":7,"icon":8},"Getting started","\u002Fgetting-started","1.getting-started","i-lucide-rocket",{"title":10,"path":11,"stem":12,"icon":13},"Installation","\u002Finstallation","2.installation","i-lucide-hard-drive-download",{"title":15,"path":16,"stem":17,"children":18,"page":49},"Guide","\u002Fguide","3.guide",[19,24,29,34,39,44],{"title":20,"path":21,"stem":22,"icon":23},"Timer & entries","\u002Fguide\u002Ftimer-and-entries","3.guide\u002F1.timer-and-entries","i-lucide-timer",{"title":25,"path":26,"stem":27,"icon":28},"Projects, clients & tasks","\u002Fguide\u002Fprojects-clients-tasks","3.guide\u002F2.projects-clients-tasks","i-lucide-git-branch",{"title":30,"path":31,"stem":32,"icon":33},"Reports & calendar","\u002Fguide\u002Freports-calendar","3.guide\u002F3.reports-calendar","i-lucide-chart-column",{"title":35,"path":36,"stem":37,"icon":38},"Theme editor","\u002Fguide\u002Ftheme-editor","3.guide\u002F4.theme-editor","i-lucide-palette",{"title":40,"path":41,"stem":42,"icon":43},"Importing data","\u002Fguide\u002Fimport","3.guide\u002F5.import","i-lucide-hard-drive-upload",{"title":45,"path":46,"stem":47,"icon":48},"Team & organizations","\u002Fguide\u002Fteam","3.guide\u002F6.team","i-lucide-users",false,{"title":51,"path":52,"stem":53,"children":54,"page":49},"Reference","\u002Freference","4.reference",[55,60,65,70],{"title":56,"path":57,"stem":58,"icon":59},"Data model","\u002Freference\u002Fdata-model","4.reference\u002F1.data-model","i-lucide-database",{"title":61,"path":62,"stem":63,"icon":64},"API routes","\u002Freference\u002Fapi","4.reference\u002F2.api","i-lucide-route",{"title":66,"path":67,"stem":68,"icon":69},"Environment variables","\u002Freference\u002Fenv","4.reference\u002F3.env","i-lucide-settings-2",{"title":71,"path":72,"stem":73,"icon":74},"Security","\u002Freference\u002Fsecurity","4.reference\u002F4.security","i-lucide-shield",{"title":76,"path":77,"stem":78,"icon":79},"About","\u002Fabout","5.about","i-lucide-info",{"id":81,"title":25,"body":82,"description":519,"extension":520,"meta":521,"navigation":522,"path":26,"seo":523,"stem":27,"__hash__":524},"docs\u002F3.guide\u002F2.projects-clients-tasks.md",{"type":83,"value":84,"toc":508},"minimark",[85,105,110,126,129,156,178,182,189,199,230,250,254,265,286,301,324,328,339,343,350,393,400,404,424,428,446,459,463,477,495],[86,87,88,89,93,94,98,99,93,102,104],"p",{},"Tick's catalog is deliberately open-ended: a ",[90,91,92],"strong",{},"task"," ",[95,96,97],"em",{},"may"," belong to a project, a ",[90,100,101],{},"project",[95,103,97],{}," belong to a client, and any of the three can stand alone. A time entry can point at any one of them — or at nothing. Three rules make that model predictable.",[106,107,109],"h2",{"id":108},"rule-1-store-only-the-deepest-reference","Rule 1 — store only the deepest reference",[86,111,112,113,116,117,120,121,125],{},"An entry stores exactly one reference: a client, a project, a task, ",[90,114,115],{},"or nothing",". Project and client are never copied onto the entry — they are ",[90,118,119],{},"derived at read time"," by walking ",[122,123,124],"code",{},"task → task.project → project.client",".",[86,127,128],{},"Consequences you will notice:",[130,131,132,140,147],"ul",{},[133,134,135,136,139],"li",{},"Attaching a task to the timer shows the whole chain (",[122,137,138],{},"Task · Project · Client",") as one chip, but only the task id is saved.",[133,141,142,143,146],{},"Reassigning a task to another project ",[90,144,145],{},"re-files its entire history"," automatically — every entry pointing at that task now reports under the new project and client. That is intended.",[133,148,149,150,155],{},"Deleting something an entry pointed at never destroys the time: the entry's reference is cleared instead (see ",[151,152,154],"a",{"href":153},"#rule-3-cascade-delete","Rule 3",").",[86,157,158,159,162,163,166,167,170,171,173,174,177],{},"The database enforces this with a single ",[122,160,161],{},"ref_type"," \u002F ",[122,164,165],{},"ref_id"," pair on ",[122,168,169],{},"time_entries"," (",[122,172,161],{}," is one of ",[122,175,176],{},"client | project | task"," or null).",[106,179,181],{"id":180},"rule-2-rate-inheritance","Rule 2 — rate inheritance",[86,183,184,185,188],{},"The billable rate for an entry is resolved ",[90,186,187],{},"server-side",", first non-null wins:",[190,191,196],"pre",{"className":192,"code":194,"language":195},[193],"language-text","entry.rate_override → task.rate → project.rate → client.rate → org_member.rate → user.default_rate\n","text",[122,197,194],{"__ignoreMap":198},"",[130,200,201,204,217,220],{},[133,202,203],{},"A task's own rate applies whether it belongs to a project or stands alone — it's the rung right below an entry-level override, and above the project it lives in. Clearing it falls back to the project → client → member → user chain, same as clearing a project's or client's rate.",[133,205,206,209,210,213,214,125],{},[122,207,208],{},"billable"," defaults from the project's ",[95,211,212],{},"Billable by default"," flag when a project is resolvable, else ",[122,215,216],{},"true",[133,218,219],{},"Amount = hours × resolved rate, computed only when the entry is billable.",[133,221,222,223,226,227,155],{},"Clients never compute inheritance — every API response carries the already-resolved rate (",[122,224,225],{},"resolvedRate",") and, for projects and tasks, where it came from (",[122,228,229],{},"rateSource",[86,231,232,233,236,237,240,241,244,245,249],{},"You can see the resolution at work on the Projects page: each project card's subline states its effective rate and its origin — ",[122,234,235],{},"$95\u002Fh"," (own rate), ",[122,238,239],{},"$110\u002Fh from client",", or ",[122,242,243],{},"$85\u002Fh default"," (the user's default). A task with its own rate shows it next to the task's name; the timer bar and manual-entry dialog show the resolved rate on their billable toggles, and a ",[151,246,248],{"href":247},"\u002Fguide\u002Fteam#rates-per-member","per-member rate override"," slots into the chain for teams.",[106,251,253],{"id":252},"the-projects-page","The Projects page",[86,255,256,257,260,261,264],{},"The header counts projects and open\u002Fdone tasks, with ",[90,258,259],{},"New task"," and ",[90,262,263],{},"New project"," buttons. Each project is a collapsible card showing:",[130,266,267,276,283],{},[133,268,269,270,162,272,275],{},"Client color dot, name, and a ",[122,271,208],{},[122,273,274],{},"internal"," tag.",[133,277,278,279,282],{},"Subline: client, ",[122,280,281],{},"x\u002Fy tasks open",", and the rate with its source (Rule 2).",[133,284,285],{},"A progress bar of tracked vs estimated time (\"6h 30m tracked \u002F 40h estimated\") — it switches to a brighter accent when over the estimate — plus the billable amount.",[86,287,288,289,292,293,296,297,300],{},"Expanding a card lists its tasks: a done toggle (completed tasks render struck-through and are hidden from the picker), entry count, tracked time, and a ",[90,290,291],{},"▶ start"," button that starts the timer on that task. A task with its own rate shows ",[122,294,295],{},"$X\u002Fh"," right after its name. An ",[90,298,299],{},"+ Add task"," link creates one inline. Standalone tasks (no project) get their own card below with the same row layout.",[86,302,303,306,307,310,311,314,315,319,320,323],{},[90,304,305],{},"Project form",": name, client picker, billable-by-default toggle, rate, estimate (free text — ",[122,308,309],{},"40h",", ",[122,312,313],{},"2h 30m",", same grammar as ",[151,316,318],{"href":317},"\u002Fguide\u002Ftimer-and-entries#date-time-and-duration-formats","durations","), visibility (private\u002Fpublic), archived. ",[90,321,322],{},"Task form",": name, project picker, rate, estimate, completed — the rate field's placeholder shows what an empty field would inherit (the selected project's resolved rate and its source, or your default rate for a standalone task).",[106,325,327],{"id":326},"the-clients-page","The Clients page",[86,329,330,331,334,335,338],{},"A table of clients: a round avatar with initials in the client's color (assigned deterministically from a short palette and reused for dots everywhere), the rate (",[122,332,333],{},"$110\u002Fh",", or the muted ",[122,336,337],{},"$85\u002Fh (default)"," when inheriting), project and task counts, tracked time with its amount, and edit \u002F delete actions. The client form is just a name and an optional rate.",[106,340,342],{"id":341},"rule-3-cascade-delete","Rule 3 — cascade delete",[86,344,345,346,349],{},"Deleting a client (or project) opens a cascade dialog instead of a confirm button. It shows three checkboxes that ",[90,347,348],{},"cascade downward"," — Projects ⇒ Tasks ⇒ Time entries — each with a live count:",[130,351,352,363],{},[133,353,354,355,358,359,362],{},"Checking ",[90,356,357],{},"Projects"," auto-checks Tasks and Entries; unchecking ",[90,360,361],{},"Entries"," unchecks the two above (you can't delete a container while keeping its contents checked-for-deletion).",[133,364,365,366,369,370],{},"An outcome panel spells out what happens to everything ",[90,367,368],{},"unchecked",":\n",[130,371,372,379,382],{},[133,373,374,375,378],{},"Projects kept → their ",[122,376,377],{},"client"," link is cleared and their rate falls back per Rule 2; the panel states the resulting $\u002Fh.",[133,380,381],{},"Tasks kept → if their project was deleted they become standalone, falling back to the project chain's rate unless the task has its own.",[133,383,384,385,388,389,392],{},"Entries kept → entries pointing directly at the deleted object have their reference cleared (",[122,386,387],{},"ref_type = null","). ",[90,390,391],{},"Time is never lost silently."," Entries pointing at a surviving task or project are untouched.",[86,394,395,396,399],{},"Everything that ",[95,397,398],{},"was"," checked soft-deletes to the trash, and an undo toast restores the full snapshot in one click.",[106,401,403],{"id":402},"rule-4-deleting-entries-and-tags","Rule 4 — deleting entries and tags",[130,405,406,414,417],{},[133,407,408,409,413],{},"A single entry deletes immediately with an undo toast (",[151,410,412],{"href":411},"\u002Fguide\u002Ftimer-and-entries#the-undo-window","configurable countdown",", 8s by default).",[133,415,416],{},"Bulk delete confirms the count first, then trashes with undo.",[133,418,419,420,423],{},"Deleting a ",[90,421,422],{},"tag"," strips the label from entries and never touches time. Tag deletion is the one hard-ish case: it removes the tag but leaves every entry's duration and amount alone.",[106,425,427],{"id":426},"the-tags-page","The Tags page",[86,429,430,431,434,435,438,439,442,443,445],{},"Tags are created inline in the page header (Enter works; names are lowercased and a leading ",[122,432,433],{},"#"," is stripped). Creating a name that already exists is a no-op — you get a \"already exists\" toast instead of a duplicate, and a name sitting in the trash is revived rather than recreated. The table shows each ",[122,436,437],{},"#tag"," chip, how many distinct projects\u002Fclients it is used on, entry count, hours, and last-used date. The ",[90,440,441],{},"filter"," action jumps to the Time page with ",[122,444,437],{}," pre-filled; delete strips the label with an undo toast.",[447,448,449],"note",{},[86,450,451,452,454,455,458],{},"Tags are create\u002Fdelete only — there is no rename, so there is no merge either. To consolidate two tags, filter the Time page by ",[122,453,437],{},", fix the tags field on each entry with ",[90,456,457],{},"✎ Edit",", then delete the tag you no longer want.",[106,460,462],{"id":461},"trash","Trash",[86,464,465,466,170,469,472,473,476],{},"Everything deleted anywhere in Tick — clients, projects, tasks, tags, entries — is a ",[90,467,468],{},"soft delete",[122,470,471],{},"deleted_at"," timestamp) and lands in ",[90,474,475],{},"Settings → Trash",", grouped by entity with a per-row \"days left\" countdown.",[130,478,479,486,492],{},[133,480,481,482,485],{},"Items are restorable for ",[90,483,484],{},"30 days","; anything older is purged automatically the next time the trash is loaded.",[133,487,488,491],{},[90,489,490],{},"Delete forever"," hard-deletes selected items (or the whole trash) immediately.",[133,493,494],{},"Undo toasts throughout the app restore exactly the rows a delete removed — including full cascade snapshots (the references a cascade cleared are put back too).",[496,497,498],"warning",{},[86,499,500,502,503,507],{},[95,501,490],{}," and the automatic 30-day purge are both irreversible, and the trash is not a backup. Keep ",[151,504,506],{"href":505},"\u002Freference\u002Fsecurity#what-you-have-to-do","database backups"," if the time data matters.",{"title":198,"searchDepth":509,"depth":509,"links":510},2,[511,512,513,514,515,516,517,518],{"id":108,"depth":509,"text":109},{"id":180,"depth":509,"text":181},{"id":252,"depth":509,"text":253},{"id":326,"depth":509,"text":327},{"id":341,"depth":509,"text":342},{"id":402,"depth":509,"text":403},{"id":426,"depth":509,"text":427},{"id":461,"depth":509,"text":462},"The open-ended catalog, the three data rules that drive it, and the trash.","md",{},{"icon":28},{"title":25,"description":519},"GoxR2-OH7b2_JE6lmr4VhaGWaGITXzpZlIG4JPPocZk",[526,528],{"title":20,"path":21,"stem":22,"description":527,"icon":23,"children":-1},"The timer bar, several timers at once, the picker, manual entries with free-text dates, editing and bulk actions.",{"title":30,"path":31,"stem":32,"description":529,"icon":33,"children":-1},"Aggregated reports with regroupable breakdowns, CSV export, and a drag-editable week calendar.",1790777311701]