Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Aking16/timify/llms.txt

Use this file to discover all available pages before exploring further.

Projects are the core organizational unit in Timify. Every time entry belongs to a project, which gives you a named container with an optional description, a display color, and an hourly rate for billing calculations. When you open the app, Timify redirects you straight to your last active project, so you can resume tracking with zero friction.

Project data shape

Each row in the projects table carries the following fields.
id
string
required
UUID primary key, auto-generated with crypto.randomUUID() on insert.
userId
string
required
Foreign key referencing the user table. Cascades on delete — removing a user removes all their projects.
name
string
required
Human-readable project name. Must be at least 4 characters long.
description
string
Optional free-text description of the project. Accepts null.
color
string
Hex color code used to visually identify the project in the UI. Defaults to #3b82f6 (Tailwind blue-500) when not supplied.
hourlyRate
number
Billing rate in the user’s currency per hour. Defaults to 0. Individual time entries can override this value.
isActive
boolean
Whether the project is currently active. Defaults to true. Inactive projects are hidden from the primary project selector.
createdAt
timestamp
Unix timestamp of when the project was created. Set automatically by SQLite via unixepoch().
updatedAt
timestamp
Unix timestamp of the last update. Refreshed automatically on every write via Drizzle’s $onUpdateFn.

Creating a project

You can create a project from two places in the UI: the sidebar dialog (accessible from any page) or the dedicated /app/projects page.
1

Open the Create Project dialog

Click the New Project button in the sidebar or navigate to /app/projects and press the + button at the top right.
2

Fill in the project details

Enter a name (minimum 4 characters), an optional description, and an optional hourly rate. The color is assigned automatically and can be changed later.
3

Submit the form

The createProject server action validates the fields with Zod, inserts the row into the projects table under your userId, and revalidates the get-projects and retrieve-project cache tags so the sidebar updates instantly.
The name field is validated with z.string().min(4). Submitting a name shorter than 4 characters returns a validation error and no row is written to the database.

Validation rules for createProject

FieldRule
nameRequired · minimum 4 characters
descriptionOptional · null accepted
hourlyRateOptional string coerced to Number() · defaults to 0

Editing a project

Navigate to any project’s settings page or open the edit dialog from the project card. The editProject server action accepts the same fields as creation, plus color and isActive.
1

Open the Edit dialog

Click the menu on a project card and select Edit Project, or visit /app/projects/[id]/settings.
2

Update the fields

You can change name (4–32 chars), description, hourlyRate, color (hex string), and isActive (boolean toggle).
3

Save changes

editProject calls db.update(projects).set(...) filtered by eq(projects.id, id) and revalidates the project cache.
Setting isActive to false hides the project from the sidebar selector without deleting any data. You can re-activate it at any time.

Validation rules for editProject

FieldRule
idRequired · must be an existing project UUID
nameRequired · 4–32 characters
descriptionOptional
hourlyRateOptional string coerced to Number()
colorOptional · hex color string (e.g. #3b82f6)
isActiveRequired · string "true" / "false" converted via convertStringToBoolean

Deleting a project

Deleting a project is irreversible. Because timeEntries.projectId references projects.id with onDelete: "set null", all time entries that belonged to the project will have their projectId set to null — they are not deleted, but they lose their project association.
Call deleteProject(id) or use the Delete option in the project card menu. The action verifies your session, calls db.delete(projects).where(eq(projects.id, id)), then revalidates the project list cache.

Active project and navigation

Timify keeps track of which project you last viewed using the browser’s localStorage key "active-project". The getActiveProject() helper reads and parses this value on the client side.
// src/data/get-active-project.ts
export function getActiveProject(): { id: string | null; name: string | null } {
  if (typeof window === "undefined") return { id: null, name: null };

  const activeProjectJSON = window.localStorage.getItem("active-project");
  const activeProject = activeProjectJSON && JSON.parse(activeProjectJSON);

  if (!activeProject) return { id: null, name: null };

  return activeProject;
}

Active project set

The app redirects to /app/project/[id] for the stored project ID and loads its time entries.

No active project

The app redirects to /app/projects so you can select or create a project before tracking starts.
The sidebar always shows the currently active project name and provides a quick-switch dropdown to change projects without navigating away.

Build docs developers (and LLMs) love