Pillar: RunoSO is the freelance business OS — see the full freelancing management system pillar for comparison vs Notion/Sheets.
You email invoice PDF, then Slack the vault password, then Notion the scope. Client loses one of three and blames you. A portal is one link: tasks, invoices, domains, vault names — revocable via portalTokens.
Portal portalTokens { tenantId, clientId, revokedAt } src/lib/db/schema-public.ts:169 renders client-specific view via portal/[token] without login, joins invoices/assets/vault names. That is why freelance client portal in RunoSO is not a template — it is a query SELECT * FROM personalTasks WHERE projectId = ? AND isToday = true joined to clients and vault.
Email Threads Fail
- Three tools, one client: Invoices, creds, assets in 3 threads — no
clientIdjoinsrc/lib/db/schema.ts:7so client hunts. - No revoke: Email forward leaks vault
gcm:iv:tag:encsrc/lib/vault/crypto.ts:28forever. - No status: Client asks ‘where are we?’ you screenshot sheets.
The Linked Productivity Model: Freelance Client Portal Knows Its Context
Portal portalTokens { tenantId, clientId, revokedAt } src/lib/db/schema-public.ts:169 renders client-specific view via portal/[token] without login, joins invoices/assets/vault names.
portalTokens {
token text primaryKey
tenantId uuid
clientId uuid → clients.id unique src/lib/db/schema-public.ts:178
revokedAt timestamp // revokes share
}
GET /portal/[token] → leftJoin(invoices)+assets+vaultItems filtered clientIdWhat linked gives you: one clientId to filter every asset src/app/api/assets/[category]/route.ts:91 with buildPaginatedQuery src/lib/utils/pagination.ts:11, vault hint vaultItemName without plaintext src/lib/vault/crypto.ts:28, and notifications RENEWAL_MILESTONES [7,3,1,0] src/app/api/cron/daily/route.ts:17 that nag before failure.
Sheets vs RunoSO Productivity: Freelance Client Portal Test
| Scenario | Sheets / Generic | RunoSO Linked |
|---|---|---|
| Share invoice | PDF email attachment | Portal invoice.status sent/paid live |
| Share creds | Slack plaintext | Vault name only, encrypted gcm:iv:tag:enc |
| Handover | Email zip | Portal + handover PDF public/templates/domain-handover-template |
Sheets list freelance client portal. RunoSO links freelance client portal to projectId and vaultItemId.
Deploy in 30 Minutes
- Create
portalTokensper active clientclientIdunique. - Verify portal shows 3–5 invoices, 2 hosting, 1 vault name.
- Send link once; client bookmarks, you update source, link stays fresh.
- At offboarding, export handover PDF + keep portal live 30 days then
revokedAt. - Track opens? ask feedback day 3, referral ask day 14 via
isTodaytask.
Mistakes & Pro Move
- Emailing
VAULT_MASTER_KEYbreaks zero-knowledge — portal never exposes ciphertext. - One token for all clients leaks cross-client data — unique
clientIdper tokensrc/lib/db/schema-public.ts:178. - No expiry risks stale share — set
revokedAtreview quarterly.
Freelance Client Portal fails quietly until a client asks "where is it?" Keep freelance client portal linked to projects, vault and invoices so work ships and money follows.
→ Fix Freelance Client Portal in RunoSO — Free
By Gautam Parmar — your freelance client portal never slips with RunoSO linked.
Keep Reading
- Pillar: freelance business OS
- Client offboarding revoke access safely: Client offboarding revoke access safely
- Digital asset handover template clients: Digital asset handover template clients
- Freelance client offboarding referral system: Freelance client offboarding referral system
FAQ
How secure is portal vs email? Portal rows RLS tenant_${id} and revokedAt check; vault secrets stay gcm:iv:tag:enc — only names shown, copy needs auth.
Can client pay via portal? Portal shows invoice.status and dueDate; Razorpay/Stripe link src/lib/razorpay/helpers.ts routes payment → transactions auto.
What if client forwards portal link? Token is unguessable nanoid() src/lib/db/schema.ts:198; revoke via revokedAt and regenerate — instant invalidation.



