work/build/agency-crm
// case 07 · build · laravel + react · 21 screens

A CRM the agency drew as a prototype — built to it, screen for screen.

A digital agency’s manager designed their CRM as a clickable prototype and asked for exactly that — the same blocks, the same buttons, the same fields, not something like it. Behind every screen it needed what a prototype does not have: a database, roles, money that adds up across pages.

client
digital agency, UA
stack
Laravel 13, Inertia, React
screens
21
service
07 · build
status
acceptance testing
year
2026
screens, to the prototype
2112 report tabs
roles × sections
5 × 1852 access tests
companies moved from Bitrix24
267demo data replaced

the brief

The agency wanted one system for clients, sales, invoices and the team. Their manager drew it as a clickable prototype — dashboard, companies, tasks, eight finance screens, reports — and the brief was the prototype itself: build this, literally.

how it went

It took three rounds. A first version to a simpler brief; then a design of my own; then the agency drew its prototype, and the application was rebuilt to it.

The first comparison against the prototype came back as “nothing like it, on every page”. The cause was not in the components at all: the design kit’s stylesheet loaded before Tailwind, whose reset wiped the kit’s headings and font. One change in load order, and the screens started to match — after that, the work was going through them side by side with the prototype open in the next tab, block by block.

what was built

  1. Companies: list with filters, column sorting and bulk actions, a kanban board with drag and drop, a company card with inline editing, client health, contacts, credentials stored encrypted, activity log.
  2. Tasks, and finance in eight screens: invoices, acts, contracts, payments, expenses, ads, a finance cabinet and a cost calculator — with a printable invoice and Telegram reminders.
  3. Reports in twelve tabs, a dashboard with a period picker, and global search on Cmd+K.
  4. A Telegram bot with a daily digest and personal notifications.
  5. Money that adds up across screens: a payout reserved on an invoice is split in proportion when the invoice is paid in parts, the same way on every page.

access, not just menus

Roles that only hide menu items are not access control: a hidden page still opens by its address. So five roles (admin, manager, copywriter, SEO, developer) get view, edit and create rights per section, 18 sections in all, checked on every route, editable by the admin on one screen. Search is filtered by the same rights, so a hidden section cannot be read through Cmd+K. An executor can change the status and description of their own task, but not its deadline or its money. 52 tests hold this in place.

the data

The demo data went, and 267 real companies came in from a Bitrix24 export through a command with a dry run. Bitrix’s “activity” date went into “days since last contact”, not into “next contact” — every one of those dates was in the past, and the CRM would have opened with the whole client base marked overdue.

where it stands

The agency’s manager is going through the system in acceptance testing. Gmail, Google Sheets and Zapier integrations drawn in the prototype are not wired yet: they need the agency’s own accounts and tokens.