Audience: consultant. Prerequisite: 01 — Engagement lifecycle.
How the client sees the work, gets into the app, and stays informed.
Two different client audiences
Do not conflate these — they use different products with different access:
| Audience | Uses | Sees |
|---|---|---|
| Portal client — the sponsor, the buyer, the stakeholder | the client portal | the engagement: contracts, invoices, progress, change requests |
| App end user — the client’s day-to-day staff | the delivered app | the app you built: their records, their screens |
And separately from both: operators are people from your firm. Operator and client-user directories are kept apart on purpose, and a picker that offers client users will never offer operators.
The client portal
The portal is a separate application from the builder. Its surfaces per engagement:
| Portal page | Client can |
|---|---|
/engagement | see the engagement at a glance |
/engagement/contracts | review and approve contracts |
/engagement/invoices | see and pay invoices (a zero-total one reads “No payment due” and asks nothing) |
/engagement/progress-reports | read progress reports |
/engagement/change-requests | raise change requests |
/engagement/quotes | approve quotes |
/engagement/deliverables | see what is being delivered, and open the files and links it hands over |
/engagement/demos | review demos |
/engagement/documents | shared documents |
/engagement/schedule | the plan |
/engagement/onboarding | get set up |
/engagement/notifications | what happened |
/engagement/account | manage their account |
Portal access and sign-in
Engagement ▸ Portal Users (/engagements/:id/client-users) — invite the client’s
stakeholders. Sign-in is a magic link: they enter their email at /login, get a
link, and land authenticated at /verify. There is no password to manage or leak.
Portal access is engagement-scoped. A client user sees that engagement and nothing else — not other engagements for the same client, and certainly not other clients.
From the portal into the app
The portal’s “your tools” surface hands the client into the delivered app through a single-use, short-lived, triple-bound handoff token. They do not need a second set of credentials.
Branding
The portal renders your firm’s logo and identity post-authentication. Note honestly: the pre-authentication portal pages are TTP-branded by design — operator colours are not applied before we know which operator the visitor belongs to. If a client demands a fully white-labelled sign-in, that is a feature request, not a setting.
Onboarding
Engagement ▸ Operate carries the onboarding flow: what the client needs to provide, who needs accounts, what has to be decided. There are onboarding templates so you are not writing the same checklist each time.
⚙️ Who may act on onboarding. Starting it (which creates the client’s checklist link), and marking a
step complete or skipping it on the client’s behalf, need the same modify_scope capability as the
engagement’s scope — narrowed by the seat’s role on that engagement. Other seats see the checklist, not the
client’s link. Saving an onboarding template is an administrator’s action.
Finishing a step does not move the engagement for you. When the client completes a step in their portal, the step is ticked on the Onboarding checklist — but the engagement’s stage (signed, active, …) moves only when someone at the firm with that stage’s permission does it. And an engagement is signed only when a signed contract is on file: ticking “Sign your contract” is not a signature.
Progress reports
Engagement ▸ Progress & Handoff (/engagements/:id/progress-reports).
A progress report is generated from the engagement’s real state — scope items and their status, time logged, what shipped — not typed from memory. Templates control the shape; the content comes from the engagement. The client reads it in the portal.
Send them on a rhythm the client agreed to. A progress report that arrives only when there is bad news trains the client to dread them.
⚙️ Who may act on a report. Generating, sending and archiving a report are the engagement’s
client-facing acts, so they need the same modify_scope capability as its scope — the admin and build
roles, narrowed by the seat’s role on that engagement. A billing seat reads every report, downloads its
PDF and can preview one, but is offered none of the steps. Customising a report template — the
layout every future report starts from — is an administrator’s action.
A report reads sent only because it was sent: Send emails it to the client and records when and to whom, and nothing else can mark a report sent.
Change requests, from ask to live
Engagement ▸ Contracts & Change (/engagements/:id/change-orders), then a request.
A change request runs a full ladder rather than stopping at “Approved”: the detail screen carries every rung, and a Next action panel tells you which one is yours — so a client who signed off weeks ago can see that the work shipped.
Both kinds of change order, one ladder
A change can start on either side, and both run the same ladder:
- The client asked — they raise a request in the portal, you price it, they approve.
- You proposed — you raise a change order with its cost impact, and they approve it in Change Orders in their portal.
Both carry the same eight rungs, the same Next action panel, and the same client-side sign-off. You should not be able to tell from this screen which kind you are looking at, apart from the Operator / Client badge.
| Rung | Who |
|---|---|
| Cost it, quote it | you |
| Approve the price | the client, in the portal |
| Mark in build | you |
| Put it on the preview site | a deploy — nobody presses anything |
| Approve for production | the client, in the portal — you have no such button |
| Ship it | a deploy to production |
Only two of those are buttons on your screen. The stages between them are derived from where the named release actually is: publish a version, deploy it to preview, and the request moves itself. Deploy to production and it says Live. Roll that release back and it stops saying Live, because the derivation is re-read rather than remembered.
Claiming the release
Claim release is the one link the machine cannot make for you: which published version actually contains this change. The screen offers a suggestion with the reason it picked that version — you press to confirm it.
⚠️ The suggestion is offered, never applied silently. A defaulted claim nobody read is how the wrong release gets named, and a wrong claim is how a client gets told their change is live when it is not. Read the version it names before you confirm.
The server refuses a claim on a draft version, and refuses one belonging to a different engagement.
Closing one without a release
Not every change order ships as software. A report re-run, a setting changed, a misunderstanding resolved — Close without a release is the honest terminal for those, and it requires a reason of at least a few words.
That reason is not paperwork. It is what the client’s “Done” is explained by when they open the request three months later and ask what happened.
⚠️ Without this terminal, a request that never needed a release sits on In progress forever, and your client’s portal quietly tells them you forgot.
⚠️ Two shapes, and which one this engagement is on
The ladder above assumes a preview site. Not every engagement has one.
| With a preview site | the full ladder. The change goes to preview, the client reviews it, and they approve it for production. |
| Without one | In Build → Live. There is no review step, the client is not asked, and the two review rungs never fire. |
⚙️ The change-order screen tells you which shape you are on, and the client’s portal tells them. That is deliberate: before it did, an engagement with no preview site drew the same eight rungs as any other and the fifth simply never arrived — so an operator could wait for a client approval that was never coming, and the client could wait for a review step that did not exist.
⚠️ A preview site is a separate deployment target with its own database — real recurring infrastructure, not a setting. Add one from Build ▸ Deploy by choosing the Staging environment, and only when the client genuinely should sign off before production.
What the client is seeing while you do this
They see the same ladder in their own words, and a Ready for you to review label when the ball is in their court. If a release carrying their change is rolled back, their portal explains it in a sentence rather than silently reverting the label. See Your client portal.
Support
The client raises problems from the portal; they arrive at Run ▸ Support
(/engagements/:id/run/support) with a badge count in your sidebar so they are hard
to miss.
Handoff
The end state of an engagement. Engagement ▸ Progress & Handoff produces the handover package: what was built, how it works, what the client now owns and operates. Handover templates keep it consistent between engagements.
Do the handoff while you still remember the decisions. A handoff written six weeks after the last commit is an archaeology exercise.
What “done” looks like for client collaboration
- Every client stakeholder who should have portal access has it, and has used it.
- The client has approved contracts and change orders in the portal, not by email.
- Every change order that shipped says so — a release claimed, or closed with a reason.
- No change order is sitting on In progress that actually finished weeks ago.
- Progress reports go out on a rhythm, not on demand.
- The client’s staff can sign into the delivered app without asking you.
- The handoff package exists before the engagement ends, not after.