How MagicTicket works
MagicTicket is an in-app support desk: sign in, pick a workspace, open tickets, and reply in threads with realtime updates. Nothing is sent by email — conversations stay inside the app.
- An operator creates an invite in Super admin → Users & invites (email + role: Admin, Team, or Customer).
- The person opens the invite link, sets a password, and is signed in. There is no public sign-up page.
- If
DEFAULT_ORGANIZATION_IDis not set, self-serve onboarding can still create a new workspace (that creator becomes admin of that org) — support deployments should set the default org env var.
To change someone's role after they join, use Super admin → Users & invites or the database fallback below.
Operators whose email appears in the server environment variable SUPER_ADMIN_EMAILS (comma-separated, matches your sign-in email case-insensitively) get a shield icon in the dashboard header. That opens Super admin where you can:
- Users & invites — create invite links (Admin, Team, or Customer) and adjust roles for members in the default workspace.
- Vessels & locations — maintain the list users pick when opening a ticket (vessel, office, or other).
Also set DEFAULT_ORGANIZATION_ID and SUPABASE_SERVICE_ROLE_KEY on the server (see .env.example). Redeploy after changing env vars. Run the organization_invites migration in Supabase so invite links work.
If you don't see the shield, sign in with an email allowed for super admin: set SUPER_ADMIN_EMAILS on the server, or rely on the default (same as PROTECTED_ACCOUNT_EMAIL, usually landucci@me.com). Redeploy after changing env.
Membership is stored in organization_members (user ↔ workspace + role). You normally manage this from Super admin. Use Supabase directly only if you need a one-off fix or the app can't load.
organization_membersTo add a row manually: create the user under Authentication → Users (or use an invite link), then insert organization_id, user_id, and role.
A workspace is a separate box for tickets and members — like one company or team. With a default org configured, invited users join that workspace directly. Without it, onboarding can ask you to create a workspace (name + URL slug). You can belong to more than one workspace later; use the workspace switcher in the header to change the active one.
With invites, the role on the invite (Admin, Team, or Customer) is what you get in the workspace — not “everyone is admin.” Whoever creates a workspace via self-serve onboarding (only when no default org is set) is still stored as workspace Admin for that org. Super admin (shield) is separate: those operators manage invites, members, and locations for the default org when env is configured.
Each membership is per workspace. The same person can be a customer in one workspace and an agent in another.
- Dashboard shows your inbox for the active workspace. Open a ticket to see the full thread.
- New ticket asks for a title, description, and priority. Tickets get a number per workspace (#1, #2, …).
- Search & tabs filter by text or by status.
When someone posts a reply on a ticket, Supabase Realtime can refresh the thread so you see new messages without manually reloading the page.
Not in this app (yet)
- Email invite links (sign-up is self-serve today)
- Customer email notifications
- A separate public “portal” URL (optional product split)
- Billing
Questions while building? Check your Supabase project (data + auth) and Vercel (hosting + env vars) alongside this app.