Problem
The consultancy needed a single internal surface that united ticketing (Zendesk), endpoint management context (NinjaOne), Microsoft 365 telemetry, and project/risk workflows — without forcing analysts to context-switch between four consoles.
Approach
Astro SSR with React 19 islands, deployed on Cloudflare Workers with three D1 databases (tickets, AIssistant, client info) and three cross-script Durable Objects (ProjectManager, RiskManager, PulseManager). Hono on the API path, Clerk for auth, Zendesk and Microsoft Graph as the source-of-truth integrations.
The AI assistant is embedded as a chat widget, orchestrating tool calls (read tickets, read risks, read M365 posture) with explicit guardrails: NinjaOne is not a ticketing backend — Zendesk is authoritative.
What I shipped
- Aligned ticket-status display with Zendesk custom statuses (the renamed-statuses feature)
- Admin-only toggle to show/hide recurring task tickets
- Pulse module: M365 telemetry dashboard powered by the PulseManager DO
- Hardened the unused SESSION KV binding out of
wrangler.jsonc - Fixed HTML-entity rendering bug spanning Pulse dashboard and Emma chat output
- Removed the AI Prompt Versioning module while preserving Emma chat