Barnicoat Branding CRM
A custom CRM for an agency’s sales operations.
- Problem
- The agency needed a shared way to manage leads, renewals, team access, and commissions.
- My role
- Designed and built the full-stack CRM, database, permissions, and reporting; I continue to support updates.
- Result
- Delivered to a paying client, with a separate public sandbox containing dummy data.
Sandbox sign-in · dummy data
Explore the lead board, team permissions, and commission reports in a separate demo.
- tester.admin@example.com
- Password
- JYUYBGCNrv%zZjCetz5y
What I delivered
CRM software delivered to a paying client company, with ongoing updates driven by their requests. I designed the lead pipeline, team access controls, and financial reporting around the agency’s day-to-day operations. Lead ownership checks keep responsibility clear, role permissions control sensitive actions, and renewal records support commission reporting. The live demo is a separate sandbox with dummy data and generic branding; the proprietary source remains private.
Follow a lead through the CRM
A guided explanation of the implemented workflow.
An enquiry enters a shared pipeline.
Website and manual intake use the same validation rules for contact details, plans, and prices.
The problem
The agency needed one place to manage incoming enquiries, assign responsibility, track follow-ups, and understand sales and renewals. A useful CRM had to do more than display a board: it needed clear ownership rules, different access levels for team members, and reporting that accounted for commissions, onboarding fees, and editor costs. Those rules needed to hold on the server and in the database as well as in the interface.
Engineering decisions
A pipeline built around ownership
Implemented a stage-based lead board with drag-and-drop movement, priorities, tags, and a detail drawer for contact information and activity history. Team members claim a lead before working on it; server-side ownership checks control who can move it, edit it, or log activity. This keeps responsibility explicit even when several people share the same board.
Permissions beyond the interface
Used Supabase Auth to verify sessions, API permission checks to gate operations, and PostgreSQL row-level security policies for database access. Administrators can manage users and configurable role permissions. Sensitive actions have additional role checks, including restricting the full database export to super administrators.
Reporting that follows the business rules
Modeled renewal events separately from leads so their revenue and editor costs can be tracked over time. PostgreSQL functions aggregate client, pipeline, and operator analytics for date ranges. Reporting includes onboarding fees, editor costs, and configurable commission rates, with per-user overrides for sales and renewal commissions.
Validated intake and practical exports
Separated API routes, business services, and database repositories. Manual and website lead intake share validation for contact details, plans, packages, and non-negative prices. PDF reports are generated in the browser, while an authorized server endpoint packages database tables as CSV files in a ZIP archive.
Delivery, maintenance, and a separate demo
Vitest covers lead services, retry behavior, intake validation, and export authorization, alongside Playwright browser scenarios and an Artillery load-testing profile. CI runs lint, typecheck, unit tests, and a dependency audit before deployment. The public sandbox uses dummy data and generic branding.
Access controls are backed by PostgreSQL row-level security, with automated tests and CI checks.
Delivered outcomes
- Delivered a paid CRM to a client company and continue to support requested updates
- Brought lead ownership, renewals, permissions, and commission reporting into one workflow
- Made the core workflow available in a separate public sandbox using dummy data
Let’s talk engineering
Have a role or project in mind?
I’m available for remote software & cloud engineering roles and B2B contracts.
Email me View résumé ↗Explore another project
Real-time collaboration in NovaStage →