# Staff Management — Integration Guide ## 1. Register the routes in your Express app ```ts // apps/api/src/index.ts (or server.ts) import express from 'express' import teamRouter from './routes/team' import webhookRouter from './routes/webhooks' const app = express() // Webhook MUST use raw body — register BEFORE express.json() app.use( '/webhooks', express.raw({ type: 'application/json' }), webhookRouter ) // All other routes use JSON app.use(express.json()) // Team routes — mounted under /api/v1/team (matches api-routes.md) app.use('/api/v1/team', teamRouter) ``` --- ## 2. Install the Clerk webhook (Clerk Dashboard → Webhooks) 1. Go to **clerk.com** → your app → **Webhooks** → **Add endpoint** 2. URL: `https://api.RentalDriveGo.com/webhooks/clerk` 3. Events to subscribe: `user.created` 4. Copy the **Signing Secret** and add to `.env`: ```env CLERK_WEBHOOK_SECRET=whsec_xxxxxxxxxxxxxxxxxxxxx ``` 5. Install `svix` for signature verification: ```bash npm install svix ``` --- ## 3. Environment variables needed ```env # Clerk CLERK_SECRET_KEY=sk_live_... CLERK_WEBHOOK_SECRET=whsec_... # Frontend NEXT_PUBLIC_API_URL=https://api.RentalDriveGo.com/api/v1 # Dashboard URL (used in invite redirect) DASHBOARD_URL=https://app.RentalDriveGo.com ``` --- ## 4. Add the page to the Next.js dashboard app ``` apps/dashboard/ ├── app/ │ └── dashboard/ │ └── team/ │ └── page.tsx ← copy frontend/pages/team.tsx here ├── components/ │ └── team/ │ ├── InviteModal.tsx ← copy from frontend/components/team/ │ ├── EditMemberModal.tsx │ └── PermissionsMatrix.tsx └── hooks/ └── useTeam.ts ← copy from frontend/hooks/ ``` Add the route to your dashboard sidebar navigation: ```tsx // components/Sidebar.tsx — add to nav items { href: '/dashboard/team', label: 'Team', icon: UsersIcon } ``` --- ## 5. requireRole middleware placement The `requireRole` middleware is already applied inside the team router. Only expose it if you need it elsewhere (e.g., `PATCH /pricing-rules` → `requireRole('MANAGER')`): ```ts import { requireRole } from './middleware/requireRole' // Example: license approval endpoint (OWNER or MANAGER only) router.post( '/customers/:id/approve-license', requireRole('MANAGER'), approveLicenseHandler ) ``` --- ## 6. Invite acceptance flow (frontend) When a user clicks the magic link in their invitation email, Clerk redirects them to: ``` https://app.RentalDriveGo.com/onboarding/accept-invite?__clerk_ticket=... ``` Create this page in your Next.js app: ```tsx // app/onboarding/accept-invite/page.tsx 'use client' import { useEffect } from 'react' import { useClerk } from '@clerk/nextjs' import { useRouter } from 'next/navigation' export default function AcceptInvite() { const { handleRedirectCallback } = useClerk() const router = useRouter() useEffect(() => { handleRedirectCallback({}).then(() => { // Clerk webhook fires user.created → activates Employee record in DB // Redirect to dashboard after a short delay setTimeout(() => router.replace('/dashboard'), 1000) }) }, []) return (
Setting up your account…