S

Selected work · 2026

Xyora

Type

AI sales CRM

Duration

3 months

Year

2026

Role

CTO and Fullstack Developer

Outcome

Lead discovery, email verification and outreach automation shipped as one workspace in three months

Tools

  • React
  • TypeScript
  • Vite
  • Tailwind CSS
  • TanStack Query
  • Zustand
  • Recharts
  • Python
  • Django
  • Django REST Framework
  • Celery
  • Redis
  • PostgreSQL
  • Docker
  • Cloudflare

An AI sales CRM built around one idea: describe the leads you want in plain English and the system finds them. It verifies every email, then automates personalised cold outreach, with prospecting, pipeline and AI marketing living in one workspace rather than three tools. Django and PostgreSQL behind it, Redis for the queues and caching that the enrichment and sending pipelines need, React on the front.

Xyora is a CRM that starts from a sentence. You describe the leads you want in plain English, the system goes and finds them, checks that each email is real, and then runs personalised cold outreach against the ones that survive. Prospecting, pipeline and the AI marketing side all live in the same workspace, which is the point: the alternative is three tools and a spreadsheet holding them together.

Architecturally it is the most involved thing here. Django and PostgreSQL own the data, Celery runs the enrichment and sending as background work so nothing blocks a request, Redis backs both the queue and the cache, Channels carries the realtime updates, and S3 holds what gets uploaded. Three separate frontends, the marketing site, the product and the admin, all deploy to Cloudflare. It is containerised, so what runs locally is what runs in production.

Inside Xyora

Xyora workspace overview with pipeline figures, overdue invoices and a task queue
The names and invoice references in Needs attention are pixelated. They belong to real accounts in a live CRM. The figures, layout and controls are untouched.

Built so the first ten seconds are useful

Xyora is a CRM that starts from a sentence: describe the leads you want in plain English and the system goes and finds them. That premise only pays off if the workspace tells you what changed while you were away, so the overview opens on exceptions rather than on charts. Four figures across the top, then a Needs attention list of overdue invoices with the deal and the delay on each, then the next task with Mark done and Snooze on it. Deals closing soon says so plainly when nothing is, instead of showing an empty chart. The right rail is the six things people actually come here to do. Every panel is a question a founder asks on a Monday, answered before it is asked.

Xyora pipeline kanban board with deals grouped by stage

The board is the source of truth for every chart elsewhere

Six stages, each column carrying its own count and total, each card its amount, probability and close date. The reason it is a board and not a table is that a salesperson will drag a card but will not fill in a status field, and every stage change here writes a history row. That history is what the funnel on the analytics page is computed from, which is the difference between reporting that reflects reality and reporting somebody typed up at month end. PostgreSQL holds it, and the write is a single transaction so a card cannot land in two stages at once.

Xyora leads table with status, source and owner columns
Lead names, contact emails and company names are pixelated. These are real businesses in a live CRM and they are not mine to publish. The interface around them is untouched.

Where the AI half of the product lands

You describe an audience, the system enriches and verifies each address, and the survivors arrive here. Everything on the row exists to answer whether a lead is worth a human's time: status, source, owner. Because enrichment and verification are slow, network-bound work, they run as Celery jobs against Redis rather than in a request, and this table is simply what the workers have finished writing. That architectural choice is the reason the page is instant while the pipeline behind it may still be running.

Xyora analytics with deals by stage, value by stage and a pipeline funnel

Two charts because count and value disagree

Deals by stage next to value by stage, deliberately side by side: ten small deals stuck in Quoted is a different business problem from one large one, and a single chart hides which you have. The funnel underneath shows the drop between stages. Recharts draws it from the stage history the board writes, so nothing here is self-reported. This is the view that gets screenshotted into an investor update, which is why it had to be right rather than merely pretty.

Xyora reports page with conversion metrics and source breakdown
One lead row beneath the source table is pixelated for the same reason as the others.

The question every founder actually has

Total leads, converted, conversion rate, average score, enrolled, and then the only breakdown that changes behaviour: conversion by source. Knowing that one channel converts at 18% and another at nothing is what tells a small team where to spend next month. Filterable by period and exportable, because it exists to be pasted into a board deck rather than admired in the app.

Xyora bulk email campaign list with delivery and open rates

Where a background job becomes visible

Campaigns with type, status and per-send delivery and open rates. Sending is the part of this product most likely to fail quietly: an SMTP timeout, a throttled provider, a bad address. It runs on Celery workers, and this page is how a failed run surfaces as a status rather than as silence. Mixing Draft and Active into the same list means it doubles as the queue, so there is one place to look rather than two.

← All work