Projects & Types
Every piece of work in VERA lives inside a project. A project has a type, a client, and a budget. The type determines how VERA calculates revenue.
Project types
VERA supports T&M, Fixed Price, Pro Bono, Internal, and Retainer for new projects. The type must always be specified when creating a project — VERA will never assume a default.
Note: Agile is not currently available for new projects. Existing Agile projects continue to work — they can be viewed, reported on, and managed. Only creation of new ones is blocked. Retainer's own creation was reinstated on 2026-09-23 — maintenance retainers are ordinary for the agencies VERA serves, and Agile has no comparable demand, so only Agile stays frozen.
T&M (Time & Materials)
Bill as you go. Revenue is calculated from logged hours.
- Budget: total project hours
- Revenue:
hours_logged × billing_rate - Billing model: per-entry accrual
- Work gate: stop work when
hours_budgetis exhausted - Use case: open-scope work where effort is unpredictable
"Create project Nike Campaign as T&M"
Fixed Price
A flat contract for a defined scope. Revenue accrues as work is completed.
- Budget: total project hours (the effort estimate)
- Contract value: the agreed price in dollars
- Revenue:
(hours_logged ÷ hours_budget) × contract_value— capped at 100% - Billing model: percentage-of-completion
- Work gate: stop work when
hours_budgetis exhausted - Use case: scoped deliverables with a negotiated price
"Create project Nike Rebrand as Fixed Price for $50,000 with 200 hour budget"
Pro Bono
Free work. Hours are tracked but no revenue is recognized.
- Budget: total project hours (optional)
- Revenue: always $0
- Billing model: none
- Use case: charity work, community projects, internal initiatives
"Create project Community Website as Pro Bono"
Retainer
A standing engagement billed in serial periods rather than one lump contract. Creating a Retainer creates the parent engagement, and VERA immediately auto-creates its first billing period as a child of that parent — time is always logged to the active period, never to the parent itself.
- Budget & contract value: entered per period, not for the whole engagement — they flow onto the first period child, never the parent. A later period is added by asking for a new period (
create_retainer_period), which by default inherits the previous period's terms unless told otherwise. - The parent's page shows the engagement to date. The hours budget shown on a retainer's own page — in its Analytics and Allocation figures — is the sum across every closed and current period, so it sits against revenue, hours logged, and allocations, which cover the same closed-and-current set — a person's envelope on an upcoming (not-yet-started) period is likewise left out of the allocation total, so that claim is now genuinely true on both sides, not just the budget side. A period that hasn't started yet contributes nothing until it starts — its dates haven't arrived, so its budget isn't part of the engagement to date, and it joins the sum the day its window opens. (A budget drawn from only the current period, compared against figures from every period, would read as though the engagement were far more over-allocated than it is; a budget that already counted an upcoming period would overstate the engagement before that period had even begun.) Each period's own figure stays on the Periods card and on that period's own page.
- The on-course verdict is judged on the current period alone. A retainer with no shaped plan compares the hours recorded in its current period with that period's budget, in proportion to how much of its window has passed: a 10-day period on its 4th day is expected to have used 40% of its own budget. Other periods do not enter it, so an overrun this period can't be hidden by an underrun in an earlier one. The working line under the verdict names the period. Between periods, when none is current, VERA falls back to every finished period's full budget plus nothing for one that hasn't started. The Logged figure and Budget health above it still describe the whole engagement.
- A renewal that is due is on the page. When the current period ends within a week and no next period exists, the project's own page says so and links to the Periods card, where Re-up creates the next period. It is the same test as the renewal message VERA sends that morning.
- A period is a window, not a calendar month. A new period's start can be any real date, and its end is named explicitly or, left unstated, defaults to the last day of the start's month — so a plain monthly cadence needs no extra step, but a 10-day sprint of billing or a 6-week engagement is just as supported. Two periods on the same retainer can never claim the same day.
- A period's status tracks itself. VERA marks a period
plannedwhile its window is still ahead,activewhile today falls inside it, andclosedonce its window has passed — automatically, with no manual step. At most one period is everactiveat a time. - Revenue:
(hours_logged ÷ hours_budget) × contract_value, computed per period, capped at 100% - Billing model: percentage-of-completion, reset every period
- Deadline: none — a retainer's periods roll forward and the parent itself has no end date
- Renewal: parents carry a monthly renewal cadence by default, and VERA warns an owner when the latest period is about to run out with no successor lined up
- Vendor liabilities live on each period: when a vendor does a period's work for a fixed fee (a maintenance job farmed out the same way every month, say), the owner adds a vendor liability on that period's own page. It builds up evenly across the period's own window — nothing before the period opens, all of it by its last day — so it can be added to next month's period in advance. The vendor's hours count toward the period's hours, revenue and pace the same way a Fixed Price project counts them, and roll up into the retainer's own page. Re-up copies the previous period's active liabilities onto the new period, the same way it copies tasks; ordinary envelopes copy too unless you untick the option. The retainer's own page offers no Vendor liabilities card, because a retainer has periods instead of a deadline
- Use case: ongoing maintenance or standing monthly work with a recurring fee
"Create project Acme Maintenance as Retainer, 40 hours and $6,000 for this month"
Project fields
| Field | Description | Who sets it |
|---|---|---|
name | Project name, unique per tenant | Owner |
client | The client this project belongs to | Owner |
type | One of T&M, Fixed Price, Pro Bono, Internal, or Retainer | Owner |
budget_hours | Total hours cap (or monthly for Retainer) | Owner via set_project_budget |
contract_value | Dollar amount (Fixed Price & Agile sprints) | Owner |
billing_rate | Hourly rate billed to client | Owner (in Projects Master) |
is_billable | Whether hours generate revenue | Auto: false for Pro Bono, true otherwise |
alert_threshold | % budget used before warning fires (default 80%) | Owner/Manager |
start_date | The day the project starts; every schedule reading is measured from it | Set at creation (today unless named); owner or the project's PM via set_project_start_date |
deadline | Target delivery date | Owner via set_project_deadline |
pm_user_id | Assigned project manager | Owner via assign_pm |
project_category | client, internal, pto, sick, leave, time_off | Auto-set |
status | active or inactive | Owner |
Client
Every project belongs to a client. An owner or admin can move a project to another client from Edit project; a retainer's periods move with it. Internal projects stay with the Internal client and client work stays off it, so moving across that line means changing the project's type first. The PTO, Sick and Leave projects never move.
Project names
A project's name is unique within its client, not across the workspace. Two clients can each have a "Website Redesign"; one client cannot have two. The check ignores case and surrounding spaces, and archived and cancelled projects still count. The web console always knows which project you mean. When you ask VERA in Slack about a name that two clients share, VERA asks which one you mean instead of picking one.
Start date
Every project has a start date. When a project is created without one, it starts today in the workspace's timezone, or on its deadline if that has already passed. An owner, or the manager who is the project's PM, can change it later from Edit project, with two limits:
- It can't be after the deadline (and the deadline can't be moved before it).
- It can't be later than the first hours already recorded on the project, including its periods and sprints. Those hours show the work had already begun. Moving the start date earlier is always allowed.
- Envelope windows sit inside the project's dates, so neither date can move inward past an active envelope's window, and on a Fixed Price project neither can move past a month that has a billing-schedule amount. Change or clear the window, or move the amount, first. Moving a date outward is always allowed.
- Time can't be recorded, or moved, onto a day before a client project's start date. If work genuinely began earlier, move the start date earlier first. Time after the deadline is always accepted, and Internal projects (including PTO, Sick and Leave) accept any date.
When VERA added this, each existing project's start date was moved back to its earliest recorded hours wherever those came first, so no project starts after work was recorded on it.
Project category vs. type
These are two separate fields:
- Type (
T&M,Fixed Price, etc.) governs billing and revenue recognition - Category (
client,internal,time_off, etc.) governs how VERA treats the project in reports and queries
Internal projects (training, admin, hiring) should use the "Internal" client and project_category = "internal". Selecting the Internal client automatically forces the project type to Internal — the type field is locked in the console form and coerced server-side. No budget, deadline, or billing rate is required for Internal projects.
PTO, Sick and Leave are created with every workspace. They can't be renamed, cancelled, closed or deleted. They are also evergreen: they have no status, start or end date, hours budget, billing or financials, and only their notes can be edited. Time can still be recorded against them as usual.
The two-tier budget model
There are two completely separate budget concepts. Do not confuse them.
Tier 1 — Project total: budget_hours in the Projects sheet. This is the sold or contracted hours for the whole project. Set by Owner only via set_project_budget. Think of it as the pie.
Tier 2 — Envelopes: rows in the Budgets sheet (07. Budgets). This is how Managers slice the pie — each team member gets a per-person envelope. The sum of all envelopes should not exceed Tier 1.
A Manager asking "how do I set the budget?" wants to distribute hours to their team (Tier 2). The overall budget is set by the Owner (Tier 1) and is not the Manager's to change.
See Envelopes for the full picture.
Retainer periods in the console
A Retainer's own page in the console (/console/p/:id) shows every period on a Periods card — dates, status, hours budget, contract value (owner/admin only), and hours logged so far — with the currently active period marked in words in its Status column, never by color alone. The hours budget in this page's Financials and Allocation figures is the total of the closed and current periods' budgets — the engagement to date — not the active period's alone, and not a not-yet-started period's either; a period joins that total the day its own window opens. The parent's page carries no envelope list or Add-envelope control of its own — envelopes are added, cancelled, and reactivated only from a period's own staffing page, linked below.
Each period's dates on that card are a link to a page of its own, so a period can be staffed before it starts: a PM who rolls the engagement forward with Re-up (below) can open the brand-new, still-planned period immediately and add its envelopes right away, rather than waiting for its window to begin. That page shows the period's own dates, status, hours budget, contract value (owner/admin only), and its own list of active and cancelled envelopes — adding a new envelope, cancelling an existing one, and reactivating a cancelled one all happen here, scoped to that one period (editing an envelope's own hours or shape still happens on its own separate page, as it always has, linked from here the same way). When no period is currently active, the Add-envelope control on the parent's page — which used to target the active period automatically — no longer exists to hide; opening a period's own page and staffing it there works for a planned period exactly as it does for an active one.
A period still has no full project page of its own — its schedule and revenue stay rolled up onto the parent, so a page trying to report them for a period alone would report nothing (zero hours logged, in particular). The staffing page above is deliberately narrower than that: it never claims to compute schedule or revenue for the period. The parent's page remains where a retainer is understood end to end; the period's own page exists only to staff it.
Editing a period, and Re-up
An owner/admin, or the manager who is PM of record on the retainer, can correct a period's own terms — its hours budget, contract value (owner/admin only), and window — on the period's own page: open the period from its dates on the Periods card, change the fields, and press Save period, which returns to the same page. Hours can be fractional, to two decimal places (1.5, or 1.18 for 1h 11m), here and in every other hours field in the console. A closed period cannot be edited: its terms are history that revenue recognition has already consumed, so rewriting them would silently rewrite recognized revenue. A window can't be widened over a sibling period's own dates, and can't be shrunk past a date that already has time logged against it.
The Periods card also offers Re-up — a form prefilled with the previous period's terms, so rolling the engagement forward doesn't mean retyping numbers that mostly haven't changed. A plain monthly retainer rolls to the next calendar month; a retainer billed in some other cadence (a 10-day sprint of billing, say) rolls to the same length of time immediately following. The PM reviews the prefilled terms — changing anything that's been renegotiated — and submits to actually create the period; nothing is created just by opening the form.
What carries over automatically, and what doesn't: the new period's enabled tasks are copied from the one before it, exactly as they are for any new period (see Project lifecycle below) — no manual step needed. Envelopes can carry over, and the option is on by default. The Re-up form offers to copy the previous period's active envelopes onto the new one: same person, task, hours and label, each covering the new period's whole window. A contractor's envelope that belongs to a liability is not copied separately, because its liability's copy brings one. An envelope's weekly plan comes along only when the new period starts a whole number of weeks after the old one; otherwise the copy has no plan and the success message says so, so reshape it on the new period's page. Untick the box to start the new period with no envelopes. A copy records no time and has no link back to its source.
A period's PM can differ from the parent's
A retainer runs for years, and the person managing it can change mid-engagement — sometimes for the whole retainer, sometimes for just one period. Each period's own page shows a Project Manager row, separate from the parent's, with a control to change it whenever the viewer is an owner or admin, or the manager who is PM of record on the parent (the same people who can edit that period's terms). A period with no PM of its own shows an em dash rather than the parent's name.
Reassigning the PM at the parent level rolls that change down onto every period that was simply going along with the parent's own PM. A period whose PM was deliberately set to someone else — from that period's own page — is left alone: it keeps its own PM through the next parent-level reassignment, rather than being silently overwritten. A closed period's PM can never be changed at all, on either surface — its history is not rewritten. (Owners and admins may still correct a closed period's dates, hours budget and contract value; doing so changes the revenue already shown for its months.)
The Periods card shows each period's own PM in a read-only PM column, so a retainer with several periods under different PMs is legible at a glance; the control that changes it lives on the period's own page.
What this does not change: VERA's PM performance rollups still credit a period's hours, revenue, and cost to the parent's PM, not to whichever person is set as a period's own PM. Giving a period its own PM affects who can staff and manage it — it does not yet affect who VERA holds accountable for its numbers.
Changing a project's type
An owner or admin can change a project between Fixed Price, T&M, Pro Bono, Internal and Retainer from the project's page (Edit project, then Change project type), in any direction and as often as needed. Agile projects and the PTO, Sick and Leave projects cannot be converted.
Every hour already recorded stays on the project. Time recorded against a retainer period always stays with that period: when a retainer becomes another type its periods are kept as closed history and still count toward the project's hours, and when a project becomes a retainer, the time recorded directly on it moves into the retainer period whose dates cover it, or into one new period created by the change.
Revenue for the project's whole history is recalculated under the new type, so its numbers can change when you convert. The page says so before you confirm.
Duplicating a project
An owner or admin can make a new project from an existing one (Edit project, then Duplicate project), so a project set up like another doesn't have to be configured again by hand. You give the copy a name and a start date, and every other date moves forward by the same number of weeks: the deadline, each envelope's window and weekly plan, and a Fixed Price billing schedule (by the same number of months). The start date can't be in the past, and it is always a whole number of weeks from the original's, so a weekly plan lands on real weeks.
The copy takes the project's type, client, notes, project manager and target LER; its hours budget, contract value and billing rate; its enabled tasks; its active envelopes (same person, task, hours and label); and its active vendor liabilities. A retainer is copied from its last period: that period's terms, tasks, envelopes and liabilities become the new retainer's first period. Recorded time, time approvals, cancelled envelopes and liabilities, and a retainer's earlier periods are not copied. If any part can't be copied, the new project's page says which, so you can add it there.
Project lifecycle
Created → Budget set → PM assigned → Tasks enabled → Envelopes created
↓
Team logs time → Alerts fire if approaching budget
↓
Completed / InactiveNo formal state machine enforces this flow — VERA relies on the configured status field and the business rules in its system prompt.
For a Retainer or Agile project, "Tasks enabled" happens once per period, not once for the whole engagement — each new period is created with the same tasks already enabled that its source had, so it needs no manual step before it can receive envelopes. See A new period inherits enabled tasks automatically.
Clients
Every project belongs to a client. If a client doesn't exist yet, VERA creates it automatically when a project is created.
Internal or overhead work belongs to the built-in "Internal" client. VERA creates "Internal" automatically when the first internal project is provisioned.
Financial rollups are client-aware: get_client_summary aggregates hours, budget, and spend across all of a client's projects.
Agile projects are documented above for reference — existing Agile projects remain fully operational, though new ones can no longer be created.