The hosted /app workspace includes account, team and billing areas for setting up the organisation profile, invitation links, billing ownership, entitlement visibility and delegated work.
What it does
- Stores the workspace name, slug, billing email, owner email, plan and account status in the shared MechanicDesk records.
- Adds team members with an invited status and a hosted invitation link.
- Lets an owner/admin save member role/status changes or remove persisted member access through a server-owned access route.
- Keeps the account/team data in the same export/import record shape as jobs, forms, invoices and templates.
- Saves and loads account/team state through the hosted API when signed in.
- Opens through
/auth/sign-infirst when production deployments enable the hosted app auth gate. - Seeds shared organisation/member rows for the organisation-scoped snapshot API.
- Accepts invitation links through a signed-in hosted API when
SUPABASE_SERVICE_ROLE_KEYis configured. - Emails persisted invitation links through a signed-in hosted API when the Brevo (preferred) or Resend email provider variables are configured.
- Checks the signed-in user's current organisation role, status and shared-snapshot capabilities.
- Shows recent organisation activity for shared snapshot saves, shared exports, shared calendar feed publishing, member access changes/removals, shared import checks/merges and invitation actions.
- Shows signed-in Stripe entitlement state from
GET /api/billing/status, including plan, subscription status, Pro access, included seats and linked Stripe ids. - Starts hosted Stripe checkout for Pro or Team plans, and opens the Stripe customer portal when a Stripe customer is already linked.
- Enforces the signed-in billing seat allowance before adding or reactivating members, before saving account/team or shared organisation workspace data, and before focused member access updates/removal persist through the hosted APIs.
Current limitation: the app now creates, emails and accepts invitation links, can require sign-in before /app renders, shows current access/activity and billing status, can open hosted Stripe checkout/customer portal actions, enforces paid seat limits, and enforces shared-snapshot read/write plus member access updates/removal server-side for shared export/save/import/member flows, but it does not yet enforce every screen server-side by role or prove live payment/email delivery.
Where to find it
- URL:
/app - Navigation:
Account - Section:
Account and team
Step by step
Sign in to the hosted workspace
- Open
/auth/sign-inif the production deployment redirects you there. - Enter your Supabase
Email. - Enter your
Password. - Select
Sign in. - After sign-in, the page opens
/app.
Local prototype builds normally open /app directly. Production deployments can set MECHANICDESK_REQUIRE_APP_AUTH=true so /app requires this sign-in cookie before it renders.
Update the organisation profile
- Open
/app. - Select
Accountin the left navigation. - In
Organisation, editWorkspace name,Workspace slug,Billing emailorOwner email. - Choose the current
Plan. - Choose the current
Status.
Add an invited team member
- Open
/app. - Select
Account. - In
Team access, enter the memberName. - Enter the member
Email. - Choose a
Role. - Select
Add member.
The member appears in the team list with an invited status and an invitation link.
If all included seats are already assigned, Add member is disabled until another member is disabled or the billing plan is upgraded. Active and invited members use seats; disabled members do not.
Copy or refresh an invitation link
- Open
/app. - Select
Account. - In
Team access, find an invited member. - Select
Copy inviteto copy the hosted invitation link. - Select
Email inviteto send the persisted invitation link by email. - Select
Refresh inviteif the link has expired or should be replaced.
The link opens /app?invite=<token>.
Email delivery requires the invited member row to be saved to the shared organisation workspace first, because the server sends the persisted Supabase member invitation rather than trusting a browser-provided link.
Accept an invitation
- Open the invitation link.
- Sign in through the hosted access panel with the invited email address.
- In
Account and team, useTeam invitation->Accept invitation. - After acceptance, use
Data import and export->Shared organisation snapshot->Merge sharedto add the shared workspace records by slug,Replace from sharedwhen the shared workspace should become the whole browser workspace, orExport sharedwhen you only need a JSON copy of the shared snapshot.
Change member access
- Open
/app. - Select
Account. - In
Team access, find the member row. - Change
RoletoOwner,Admin,TechnicianorViewer. - Change
StatustoActive,InvitedorDisabled. - Select
Save accessto persist the role/status change to the hosted organisation. - Select
Remove accessto remove persisted hosted access, orRemove localto delete an unsaved/local scaffold row before the next full account/shared save.
The last remaining owner cannot be removed from the current local workspace.
Changing a disabled member back to Active or Invited is blocked when the billing seat limit is already full.
Save access requires a signed-in owner/admin for the current Workspace slug; the server also prevents updates that would leave the organisation without an active owner or exceed the paid seat limit.
Remove access requires a signed-in owner/admin for the current Workspace slug; the server deletes the persisted organisation member row, blocks removal when it would leave the organisation without an active owner and records member-removal activity.
Save or load hosted account settings
- Open
/app. - Sign in through the hosted Pro/access panel.
- Select
Account. - In
Hosted account workspace, selectSave accountto write the organisation and member rows to Supabase. - Select
Load accountto restore the saved hosted account/team state into the current browser workspace.
If the buttons are disabled, sign in first. If the backend reports that it is not configured, re-run the latest docs/backend/supabase-setup.sql and confirm the Vercel/local server has NEXT_PUBLIC_SUPABASE_URL and NEXT_PUBLIC_SUPABASE_ANON_KEY.
Check organisation access
- Open
/app. - Sign in through the hosted Pro/access panel.
- Select
Account. - In
Organisation access, selectCheck access. - Review the displayed
Role,Status,ManageandShared snapshotsvalues.
The check uses the current Workspace slug. If the signed-in user is an owner, admin, technician or viewer, the panel shows whether they can manage the workspace, write shared snapshots or only view. The hosted shared-snapshot API uses the same capability boundary.
Review organisation activity
- Open
/app. - Sign in through the hosted Pro/access panel.
- Select
Account. - In
Organisation activity, selectRefresh activity. - Review recent shared snapshot, shared import and invitation events.
The activity panel reads GET /api/organisations/activity for the current Workspace slug. It shows the event type, summary, timestamp and actor email when available. Activity writes are server-owned and are recorded after successful shared snapshot saves, shared exports, shared calendar feed publishing, member access changes, shared import previews/merges, invitation emails and invitation acceptance when the latest Supabase setup SQL has been applied.
Check billing status
- Open
/app. - Sign in through the hosted Pro/access panel.
- Select
Billing. - In
Hosted billing status, selectRefresh billing. - Review the displayed plan, subscription status, Pro template access, included seats, Stripe customer/subscription ids and entitlement timestamps.
The billing status route validates the signed-in Supabase bearer token and reads the current user's user_entitlements row through Supabase RLS. If no entitlement row exists, the panel reports Workspace/inactive defaults.
Start checkout or manage billing
- Open
/app. - Sign in through the hosted Pro/access panel.
- Select
Billing. - Choose
Upgrade to Proto start Pro Templates checkout, orStart Team checkoutto start the Team plan checkout. - If the account already has a linked Stripe customer id, choose
Manage subscriptionto open the Stripe customer portal.
Checkout requires the hosted app to have STRIPE_SECRET_KEY and the matching plan price id configured. Manage subscription stays disabled until the entitlement status includes a linked Stripe customer id from a previous checkout/webhook update.
Use the account profile for shared snapshots
- Open
/app. - Select
Account. - Confirm
Workspace slug,Owner emailand the member email rows are correct. - Select
Data import and export. - Use
Shared organisation snapshot->Save sharedto create or update the organisation and member rows before saving the structured records.
If Organisation access has been checked and says the current role cannot write shared snapshots, Save shared is blocked. If it says the role cannot view, Export shared, Merge shared and Replace from shared are blocked.
Owners and admins can update organisation/member metadata and save the snapshot. Active technicians can save the shared snapshot for an existing organisation, but the API keeps the persisted organisation/member metadata rather than accepting account/team edits from that technician session.
What each screen shows
| Area | What it shows |
|---|---|
Account and team heading |
Current plan, status, active member count, invited count and owner count. |
Hosted account workspace |
API save/load status plus signed-in save and load controls. |
Organisation access |
Signed-in role/status check for the current workspace slug, including manage and shared-snapshot capability values. |
Organisation activity |
Recent server-recorded organisation events plus Refresh activity. |
Organisation |
Workspace identity, billing ownership and plan/status fields. |
Team access |
Seat usage, invite form, editable member list, per-member Save access, Remove access, Remove local, generated invitation links, copy, email and refresh controls. |
Billing and APIs |
Signed-in billing status, Pro access state, included and assigned seats, hosted checkout buttons, customer-portal button, linked Stripe ids and the hosted Stripe/conversion route inventory. |
Shared organisation snapshot |
The Data import/export panel that saves, exports, merge-loads or replace-loads the full structured workspace against the organisation slug. |
Team invitation |
Appears when /app is opened with an invitation token in the URL. |
Next server step |
Reminder that this scaffold still needs full RBAC enforcement, organisation-scoped records, live email provider proof and live payment proof. |
/auth/sign-in |
Noindexed hosted sign-in page used when production route protection is enabled. |
Tips and good to know
- Active and invited members count against the included seat allowance returned by billing status. Disabled members stay in the record but do not consume a seat.
- Use
Save accessafter changing a persisted member's role or status when you want the hosted organisation row updated immediately. UseRemove accessfor persisted hosted members andRemove localfor unsaved rows that only exist in the current browser workspace. - If billing status has not loaded yet, the workspace uses the local plan value as a prototype fallback: Workspace/Pro allow 1 seat, Team allows 5 seats and Enterprise allows 50 seats.
- Use
Disabledfor people who should remain visible in the record but should not have future access. - Exporting workspace data from
/appincludes the account/team scaffold data. - Hosted account save/load stores only the account/team workspace shape. It is separate from the full structured record snapshot in
Data import and export. - Shared organisation snapshots use member emails to create membership rows. A signed-in user's email is linked as an active owner when it is not already present in the member list.
- Invitation links expire after 14 days and can be refreshed from the member row.
Email inviteusesPOST /api/organisations/invitations/send, validates the signed-in user's manage access for the workspace slug, reads the persisted invited member row and sends through Brevo (preferred) or Resend whenBREVO_API_KEYorRESEND_API_KEYplusMECHANICDESK_INVITATION_EMAIL_FROMare configured.- Invitation acceptance requires the invited person to sign in with the same email address used on the member row.
Organisation accessis a live capability check for the current slug. Owners/admins can manage and write shared snapshots, technicians can write shared snapshots without changing account/team metadata, and viewers are read-only when active. Read-only access is enough forExport shared.Organisation activityrequires the latestdocs/backend/supabase-setup.sqlbecause it creates theorganisation_activitytable and RLS policies.Save accessandRemove accessusePATCH/DELETE /api/organisations/memberswith the signed-in user's bearer token; they recordMember accessactivity when the setup SQL is current.- The hosted app auth gate uses a server-visible session cookie for
/app; API routes still validate the signed-in user's bearer token for each protected operation. GET /api/billing/status,POST /api/billing/checkoutandPOST /api/billing/portaluse the signed-in user's bearer token. Webhook writes still use the server-side Stripe/gateway route.
Troubleshooting
| Problem | What to try |
|---|---|
Add member does not create a row |
Add both a name and an email address. |
Add member is disabled |
The account has used all included seats. Disable a member, refresh billing after upgrading, or start Team checkout from Billing. |
| Account or shared workspace save says the team seat limit is exceeded | Disable members until active plus invited members fit within the included seat count, or upgrade the plan and refresh billing. |
Refresh activity says organisation activity cannot be read |
Re-run the latest docs/backend/supabase-setup.sql, then confirm the signed-in user is an active member of the current workspace slug. |
Copy invite shows the link instead of copying |
Copy the link text from the status message; some browsers block clipboard access without a user gesture or permission. |
Email invite is disabled |
Sign in through the hosted Supabase access panel first. |
Email invite says no invited member was found |
Select Save shared first so the invitation row is persisted to the organisation workspace, then try again. |
Email invite says the provider is not configured |
Set server-only BREVO_API_KEY (or RESEND_API_KEY) and MECHANICDESK_INVITATION_EMAIL_FROM; optionally set MECHANICDESK_INVITATION_EMAIL_REPLY_TO. |
Accept invitation is disabled |
Sign in with the invited email address first. |
| Invitation acceptance says the backend is not configured | Set NEXT_PUBLIC_SUPABASE_URL, NEXT_PUBLIC_SUPABASE_ANON_KEY, and server-only SUPABASE_SERVICE_ROLE_KEY. |
The Remove access button is disabled |
Sign in through the hosted Supabase access panel first. If the row is the last active owner, add another owner or change another active member to Owner first. |
| Hosted save/load buttons are disabled | Sign in through the hosted Supabase access panel first. |
| Hosted save/load says the backend is not configured | Apply the latest docs/backend/supabase-setup.sql and set NEXT_PUBLIC_SUPABASE_URL and NEXT_PUBLIC_SUPABASE_ANON_KEY for the Next.js app. |
/auth/sign-in says hosted auth is not configured |
Set NEXT_PUBLIC_SUPABASE_URL and NEXT_PUBLIC_SUPABASE_ANON_KEY before enabling MECHANICDESK_REQUIRE_APP_AUTH=true. |
/app keeps redirecting to sign-in |
Sign in again, then confirm the deployment can reach Supabase Auth and that browser cookies are not blocked for the site. |
Check access is disabled |
Sign in through the hosted Supabase access panel first. |
Check access says no membership was found |
Confirm the workspace slug, accept any pending invitation, or ask an owner/admin to add the signed-in email as an active member. |
Save access is disabled |
Sign in through the hosted Supabase access panel first. |
Save access says no organisation member was found |
Save the shared organisation workspace first so the member row exists in Supabase. |
Save access says the current role cannot manage team access |
Ask an active owner/admin to make the change. |
Save access says at least one active owner must remain |
Make another member an active owner before demoting or disabling the current owner. |
Save access says the team seat limit is exceeded |
Disable another active/invited member or upgrade the plan and refresh billing before reactivating the member. |
Remove access says no organisation member was found |
Save the shared organisation workspace first so the member row exists in Supabase, or use Remove local for an unsaved row. |
Remove access says the current role cannot manage team access |
Ask an active owner/admin to remove the member. |
Remove access says at least one active owner must remain |
Make another member an active owner before removing the current owner. |
Refresh billing is disabled |
Sign in through the hosted Supabase access panel first. |
| Billing status says the backend is not configured | Set NEXT_PUBLIC_SUPABASE_URL and NEXT_PUBLIC_SUPABASE_ANON_KEY for the Next.js app, then re-run docs/backend/supabase-setup.sql if the entitlement table is missing. |
| Checkout says Stripe is not configured | Set STRIPE_SECRET_KEY plus STRIPE_PRO_PRICE_ID and/or STRIPE_TEAM_PRICE_ID in the hosted app environment. |
Manage subscription is disabled |
Complete checkout first, then wait for the Stripe webhook to write the linked customer id into user_entitlements. |
Save shared says the current role cannot save shared snapshots |
Ask an owner/admin to activate the member row and set the role to owner, admin or technician. |
Export shared says the current role cannot export shared snapshots |
Ask an owner/admin to activate the member row or confirm the signed-in user belongs to the current workspace slug. |
| A member does not receive an email | Confirm the email provider accepted the send, check the recipient address and spam folder, then use Copy invite as a fallback. |
| Shared snapshot save says the slug is already owned | Change the workspace slug or sign in as a member/owner of the existing organisation. |
Related guides
Ready to try it? Open the workspace and follow along — it works in your browser, installs as an app and runs offline.
Open the workspace