- Years
- 2022 - PresentActive
Everything the agency does commercially passes through this system. A project starts as a brief, gets costed against suppliers and influencers, turns into contracts and payment requests that route through a reviewer chain, and lands in finance - while the same platform holds the org chart, staff records, leave and overtime, document storage and the permission model governing who may see any of it. I built it twice: first as the in-house tool from late 2022, then as the current workspace, a pnpm/Turborepo monorepo with a React SPA, an Express API on Sequelize and PostgreSQL, and a shared TypeScript interface package between them. Across both generations I have done essentially all of it myself - schema design, API, interface, migrations and deploys.
What I built
- Designed the domain model from nothing and it has held up through a full rewrite: around 60 tables covering projects, briefs and brief history, clients, brands and client representatives, suppliers with their costs, notes, representatives and influencer links, documents, payments, day-off requests, notices and the whole org tree.
- Built the project spine - costing, pitching, timeline, members, documents and payments - with per-project supplier costing, contract values and interaction logs, and multi-member assignment with project-level permissions layered on top.
- Built the finance side across both generations: payment requests and HR payments with advances, a configurable multi-step reviewer chain with ordering, batch approve, batch cancel and batch update for month-end, PIT and VAT contract handling, evidence uploads, and a payment control desk for whoever is approving that day.
- Built HR request handling end to end - annual leave, WFH, working-out-of-office and overtime - with approval chains whose length scales with the days requested, monthly-cycle date validation, multiple days in one request, remaining-balance display, per-year filtering, attendance codes and a full audit trail with a per-request timeline.
- Wrote the permission layer myself: permission codes, grants and project-level overrides, plus direct-staff and manager relationships, enforced identically across the REST API and every other surface that has since been added.
- Built the organisation model - company, division, department, team, position and level, with groups, staff relations and employee-by-location views - and the org chart rendered from the full tree.
- Added an MCP server so staff can query the workspace from Claude, backed by an OAuth 2.1 + PKCE authorisation server with .well-known discovery, per-user client credentials stored only as hashes, and a “Connect to Claude” settings page. Tools are read-only, built per request, and run as the calling user against the same permission checks as the API.
- Real-time notifications over Socket.IO and Firebase, Google Chat delivery, notices with read acknowledgements, and a My Desk dashboard pulling each person’s pending requests, leave balance, review queue and recent projects into one page.
- Reporting and exports throughout: costing, payment, overtime, day-off and staff reports to Excel via ExcelJS, PDF generation with Puppeteer, and Google Drive integration for document storage.
- Rebuilt the platform in 2025 without downtime - moving from two separate repos to a Turborepo monorepo with shared interfaces, and carrying four years of live data and every workflow across.
- Kept it current on my own: AWS SDK v2 → v3, moment → dayjs, Biome in place of ESLint and Prettier, Vite and React Router upgrades, Sentry, and CI/CD on GitHub Actions.
Stack
- React
- TypeScript
- Vite
- Ant Design
- TanStack Query
- Zustand
- Express
- Sequelize
- PostgreSQL
- Redis
- Socket.IO
- MCP
- OAuth 2.1
- Turborepo
- AWS S3
- Firebase
- Puppeteer
- ExcelJS