Prior work, organized around the problem it solved.
Start with the pain point, see what changed, then open the deeper case, live site, demo, video, or document where one is available. Recorded figures belong to their stated window; they are evidence snapshots, not current or lifetime totals. Prototypes are separate, on the Labs page.
Projects delivered
86across the delivery records, counted once
Sectors
53industries these systems were built for
Case pages
8problem, response, and recorded outcome
Shipping since
2022the earliest dated system in the register
01
Track record
What clients did after the first engagement.
A retainer that follows a fixed-price build, a second contract from the same client, a marketplace rating earned across dozens of deliveries. These are the outcomes that need no one's permission to publish.
Marketplace standing
Top Rated
on Upwork, from a first contract in August 2023 to Top Rated in under two years
Longest retainer
26 months
one hourly engagement, March 2024 to May 2026
Clients who came back
2 of 9
marketplace clients who signed a second contract after the first
Fixed price to retainer
1 engagement
a five-milestone build converted to an open-ended hourly retainer, still running
Countries delivered into
13
the US, the UK, Canada, Switzerland, Saudi Arabia, Turkey, Singapore, Australia, Denmark, Mexico, Lithuania, South Africa and Pakistan
Fig. 1
The 34 catalogued projects, by sector
Derived at build time from the project catalogue. One dot is one project, counted once, in the sector its own record carries.
Catalogued projects by sector
Business intelligence
7
Knowledge management
3
B2B SaaS
2
Finance
2
Financial markets
2
Applied machine learning
1
B2B sales
1
Enterprise IT
1
Healthcare
1
Hospitality
1
Human resources
1
Logistics
1
Manufacturing
1
Marketing
1
Multi-industry
1
Procurement
1
Professional services
1
Property management
1
Publishing
1
Real estate
1
Research
1
Retail
1
Wholesale distribution
1
02
Featured
Three problems, and the systems that changed them.
Each story connects the operating constraint to the response. Figures are supporting snapshots, not the story itself.
Travel-market intelligence · In production
A high-volume hotel pricing-data system
A hotel market-intelligence company ran its competitor-rate scrapers on self-hosted Windows servers, with data audits done by hand in-house. It needed Python scraping and data-extraction capacity added to that setup, a pipeline that stays reachable against sources that block automated traffic, and, from early 2026, an outbound engine alongside its inbound demo flow.
What Qelv built
Data-collection infrastructure for hotel market intelligence, running in production
API-first Python collectors with residential and mobile proxy rotation, retry, and anti-blocking strategy that keep a single high-volume source reachable, writing results into the client's MariaDB through a stored-procedure interface
Scheduled collection, monitoring, and the operational work of keeping a high-volume pipeline healthy
Under client agreement. The client owns this system. Ask and we will walk you through how it was built and what it changed.
a property data audit briefed and delivered inside one business day
Delivery record, Qelv engineering record · 2026
Snapshot for this period, not a current or lifetime total.
8M+ requests/month: live collection volume against a single source
Fish Frenzy · Restaurants · Delivered
Turning local search demand into a usable three-location ordering path
A three-location seafood restaurant had no working online ordering path, so the local search demand around its locations and menu had nowhere to convert. It needed online ordering keyed to the customer's zip code across three locations, a WooCommerce-compatible theme to build on, and social content and local ads to bring people to it.
What Qelv built
Website redesign and UX improvement on WordPress and WooCommerce
Zip-code-based online ordering across three locations, integrated with the point of sale; live in December 2023 and still taking orders in January 2026
Email newsletter live on 28 November 2023, ahead of the ordering launch
Google Search Console · 16 months from 20 June 2024
Snapshot for this period, not a current or lifetime total.
5.6K organic-search sessions: up 154.9% year on year; order-page views up 311.2% over the same period
Home: hours, the menu, and directions above the fold
93 Brew · Owned venture · Specialty coffee · In production
A café website the owner can update without a developer
A new owner-operated café, one we hold a stake in, needed a customer-facing website ready for its opening in March 2026, local discovery from the first week, paid-social measurement, and a menu that stays accurate as prices change without a developer on call for every update.
A central menu data model, so pricing and item changes flow through the whole site from one place: 25 drinks across five categories (Classic, Matcha, Signature Iced, Flavours, Slow Bar), each with its own page carrying a tasting profile, ingredients, and milk options
Local search is covered: page metadata, a sitemap, a 14-question FAQ, and a Business Profile
Production site live with menu, visit, and FAQ content
Delivered build, live check of every route, 29 August 2026 · 29 August 2026
Snapshot for this period, not a current or lifetime total.
41 production deployments: of the Next.js build between first go-live and the June menu-pricing revision, each one linked to a commit in the site's repository
03The portfolio
Browse 34 shipped projects without the long scroll. 23 sectors.
Filter by the problem area or sector. Open a row to connect the constraint to the response, then follow its case study where one is available.
All practices · Every sector: showing 8 of 34 projects
Problem and response
An outbound program run on infrastructure we own rather than a seat in someone else's tool. Contacts are pulled from Apollo and pass a verification engine before any send: a commercial verifier on the 2025 program, our own Python engine from its first production run in June 2026. Mail goes out through Smartlead or Instantly from secondary domains with SPF, DKIM and DMARC set and warmed before use, on sequenced copy segmented by persona. Replies are triaged and the qualified conversations handed to a person, and a weekly deliverability report per domain shows whether authentication held as volume rose.
What changed
Verification engine in Python: DNS lookups, then multi-stage SMTP probing with provider profiles and greylisting and tarpit handling, plus SPF, DMARC, PTR and TLS signals per address
Each address gets one of four verdicts (valid, invalid, risky, unknown) with one of 34 reason codes across 25 output columns, so every classification traces back to the check that produced it, before a send rather than after a bounce
Secondary sending domains with SPF, DKIM and DMARC set and warmed before the first campaign, so the primary domain never carries cold mail
Sending identity spread across domains and mailboxes provisioned per program with per-mailbox volume ceilings, DNS on Cloudflare, and warm-up tooling compared before adoption
Sequenced copy segmented by persona: ten templates run on our own program and one five-step sequence kept; a 42-combination offer-by-segment grid behind the sequences staged in August 2026
Reply triage that separates a real answer from an auto-responder and hands qualified conversations to a person, with a weekly deliverability report per domain showing DKIM, SPF and DMARC pass rates on the messages sent
2025 to 2026 · Internal product: run on our own pipeline from July 2025, then for a partner under their brand from October 2025 and as a client pilot from February to May 2026. Two hourly contracts, February to May 2025, covered the same Apollo campaign work and contact scraping for a manufacturer. · Built with: Python · Apollo.io · Instantly · Google Workspace · PostgreSQL · Smartlead · MillionVerifier · Cloudflare · Hostinger Mail · GitHub Actions
A set of telephone agents that answer, qualify and book, built once as a core and specialised per industry. Each one takes the call, works a script that branches on what the caller says, writes the outcome into the business system behind it, and hands off to a person on the cases that need one.
What changed
One conversation core, eight industry configurations over it
Inbound answering and outbound calling from the same agent definition
Calendar booking and CRM write-back at the end of the call, not by hand afterwards
Escalation rules that route to a person rather than looping the caller
A marketing site whose content is edited by the people who own it. The public pages are a fast front end; the editing surface is a real content model with roles, drafts and a publish step, so a page change does not require a developer or a deploy.
What changed
Content model with typed fields
Draft, review and publish states with per-role permissions
Media library with derivative sizes generated on upload
Front end rendered from the content API, so an edit is live without a rebuild
Built with: Next.js · React · WordPress · REST API · TypeScript
Problem and response
An operating system for a freight business: consignments from booking through delivery, the fleet and drivers assigned to them, the rates that price them, and the invoices that follow. Built from the schema up, because the parts a logistics business gets wrong are the joins between them.
What changed
Consignment lifecycle from booking to proof of delivery, with status history retained
Fleet, driver and route assignment with availability checked at assignment time
Rate cards per client and per lane, applied at booking rather than at invoicing
Invoicing and settlement generated from the movements, not re-keyed
Role-based access separating dispatch, finance and management views
Built with: React · Node.js · PostgreSQL · REST API · Docker
Problem and response
The administration of a multi-unit residential compound in one place. Units with their tenancies. The rent plus service charges that come off them. Maintenance requests from report to closure. Visitor and gate records. The office ran on paper files and a shared drive before it.
What changed
Unit register with tenancy history, so a unit's past is readable years later
Rent and service charge schedules generated per unit with an arrears view
Maintenance tickets from resident report through assignment to sign-off
Visitor and vehicle records against the unit that authorised them
Built with: React · Node.js · PostgreSQL · REST API
Problem and response
A CRM shaped around how property is actually sold in the Gulf: the listing inventory on one side, the buyer and enquiry pipeline on the other, and the agent activity that connects them. Arabic and English throughout, including in the data, not only in the interface chrome.
What changed
Listing inventory with media, availability and per-listing agent ownership
Enquiry pipeline with stages, assignment and follow-up scheduling
Bilingual interface and bilingual content fields, right to left and left to right
Agent activity and pipeline reporting for management
Built with: React · Node.js · PostgreSQL · i18n · REST API
Problem and response
A group holding several operating entities could not answer what cash it held, in which currency, on any given day without a week of collation. This pulls the balances and the committed movements into one model and projects the position forward per entity and consolidated.
What changed
Balances and movements consolidated across entities and currencies
Forward cash position projected from committed inflows and outflows
Intercompany positions netted rather than double counted
Per-entity and consolidated views off the same underlying model
Built with: Python · SQL · Power BI · Excel integration
Problem and response
A prototype of the order-to-purchase loop for a wholesale distributor whose orders arrived by email and whose sales and purchasing records sat in two systems, Zoho CRM and Odoo. Customer orders come in against price lists held per sales portal, open demand is gathered into supplier baskets that track each supplier's minimum order value, orders to supplier go out, received stock is allocated to the customer orders waiting on it, and shipping, invoicing, returns and credit notes follow, with role-based permissions and an audit log across the system. Scoped for a catalogue of 3,000 to 10,000 SKUs and built as a discovery demo in two passes in 2026, the second with a partner team, then reviewed by the prospect's own team against a 59-item requirement tracker.
What changed
Customer orders entered against live stock and price lists held per sales portal, with margin per line
Supplier baskets assembled from open demand across orders, each tracking the supplier's minimum order value
Orders to supplier raised from the baskets; received stock allocated to the customer orders waiting on it and reconciled against the originating demand
Shipping, payments and invoicing, returns and credit notes handled in the same system
Role-based permissions and an audit log on every state change
2026 · Discovery prototype, built in two passes, the second with a partner team, then reviewed by the prospect's seven-person team against a 59-item requirement tracker and revised through two gap-closure waves · Built with: React · Node.js · PostgreSQL · REST API · Next.js · TypeScript · Zustand · v0 · Vercel
Problem and response
Employee records, attendance and payroll as one system rather than three spreadsheets and a bank file. Attendance feeds the pay run directly, so the hours that were worked and the hours that are paid come from the same source.
What changed
Employee register with contracts, documents and expiry reminders
Attendance capture with shift patterns, overtime and leave accrual
Payroll run computed from attendance with allowances and deductions applied per policy
Payslip generation and a per-run register for finance
Leave requests with an approval chain
Built with: React · Node.js · PostgreSQL · PDF generation
Problem and response
A till that keeps working when the connection does not. Orders, payments and the kitchen queue run against local storage first and reconcile with the server when the link returns, because a restaurant during service cannot stop for the internet.
What changed
Local-first writes with conflict resolution on reconnect
Table, counter and takeaway order flows on the same terminal
Kitchen display queue driven by order state rather than paper tickets
Split payment, part payment and refund handled at the till
Day-end reconciliation per terminal and per shift
Built with: React · IndexedDB · Node.js · PostgreSQL · Service workers
Problem and response
Product design for a B2B software company: the flows, the screens and the component set behind them, delivered as a system a front-end team can build from rather than a set of pictures.
What changed
User flows mapped before screens were drawn
Component library with states, not just default renders
Responsive behaviour specified rather than left to implementation
Handoff with spacing, type and colour tokens named
Built with: Figma · Design tokens · Prototyping
Problem and response
A chat surface over a company's own documents. Questions are answered from the document set rather than from the model's general knowledge, and every answer carries the passages it came from so a reader can check it.
What changed
Retrieval augmented generation over a private corpus, not a public index
Chunking and embedding pipeline rebuilt on document change
Citations returned with every answer
Refusal path when the corpus does not contain the answer
The same retrieval pattern built inside Azure, for an organisation whose data was not permitted to leave its tenant. Indexing, embedding and inference all run on Azure services under the customer's own subscription.
What changed
Indexing and retrieval through Azure AI Search
Inference through Azure OpenAI inside the customer tenant
Document ingestion pipeline with incremental reindexing
Access scoped through the tenant's own identity provider
Built with: Azure OpenAI · Azure AI Search · Python · Azure Functions
Problem and response
A tool that writes post captions from an image and a short brief, in a house voice supplied as examples rather than as adjectives. Built for a team producing a high volume of social posts against a fixed tone.
What changed
Vision input, so the caption describes the actual image
Tone carried by supplied examples rather than instruction words
Variant generation with length and platform constraints applied
Batch mode for a content calendar rather than one post at a time
Built with: OpenAI GPT-4o · Python · FastAPI · React
Problem and response
A model that combines price history with signals drawn from filings and news rather than from price alone. Built as a research instrument with the backtest as the deliverable, not as a trading recommendation.
What changed
Price, fundamental and text-derived features in one feature store
Regulated-source ingestion from SEC EDGAR
Walk-forward backtesting with the evaluation window held out
Feature attribution reported alongside the prediction
Built with: Python · pandas · scikit-learn · SEC EDGAR · PostgreSQL
Problem and response
A pipeline that turns a large body of unstructured text into something countable: topics, entities, sentiment and the relationships between them, with the output shaped for a dashboard rather than for a notebook.
What changed
Entity extraction and normalisation across inconsistent source text
Topic modelling with a labelled taxonomy rather than bare cluster ids
Sentiment scored per entity, not per document
Output written to a warehouse table the reporting layer reads
Built with: Python · spaCy · Transformers · PostgreSQL
Problem and response
Upload a document, then ask it questions. Built for people working through long documents one at a time rather than searching a whole library, so the retrieval is scoped to the file in front of them.
What changed
Per-document session scope, so answers cannot drift to another file
Handles long documents by chunk with overlap rather than truncating
Passage highlighting against the source view
Supports the document formats people actually send
Built with: Python · OpenAI · LangChain · Streamlit
Problem and response
A question-answering layer over a company's own metrics: a plain-language question becomes a query against the warehouse, and the answer comes back with the numbers and the chart rather than as prose.
What changed
Natural-language question translated to SQL against a governed schema
Generated query shown alongside the answer so it can be checked
Result rendered as a table and a chart, not a paragraph
Schema scoped so the assistant cannot reach tables it should not
A question answering service built on LangChain, with the retrieval chain, prompt templates and evaluation harness kept as code so a change to the prompt is reviewable in a pull request.
What changed
Retrieval chain defined in code, versioned with the repository
Prompt templates parameterised rather than pasted per environment
Evaluation set run against changes before release
Swappable model provider behind one interface
Built with: Python · LangChain · OpenAI · Vector search
Problem and response
A writing assistant that lives where the writer already is. Drafting, rewriting and research run as a Telegram conversation, with per-user state so a thread picks up where it left off.
What changed
Conversational state held per user across sessions
Draft, rewrite and summarise as distinct commands rather than one prompt
Long output split to fit the platform's message limits
Rate limiting per user to keep model cost bounded
Built with: Python · Telegram Bot API · OpenAI · Redis
Problem and response
A conventional model handled the structured features while a vision model read the images the structured data described. The two signals were combined so the prediction used what the photograph showed as well as what the record said.
What changed
Structured model and vision model combined at the feature level
Vision output constrained to a fixed schema rather than free text
Fallback to the structured model when the image is absent or unusable
Per-source contribution reported for each prediction
Built with: Python · GPT-4 Vision · scikit-learn · pandas
Problem and response
A question answering surface over healthcare regulation, where being confidently wrong is the failure mode that matters. Answers are grounded in the regulatory text and cite the clause, and the assistant declines rather than guesses.
What changed
Answers grounded in regulatory source text with the clause cited
Explicit refusal when the corpus does not support an answer
Regulated-source ingestion with the effective date carried through
A product rather than a script: meetings are transcribed, summarised into decisions and actions, and made searchable across the history, with the multi-tenant plumbing a SaaS needs behind it.
What changed
Transcription and speaker separation per meeting
Summary split into decisions, actions and open questions rather than one blob
Search across the meeting history, not only within one call
Multi-tenant data isolation with per-workspace access control
A conversational surface over currency market data: rates, movement over a window, and the definitions traders ask about, answered from live data rather than from the model's memory of it.
What changed
Live rate lookup through a market data API rather than model recall
Historical windows computed on request
Terminology answered from a curated reference set
Explicit statement that nothing returned is trading advice
Built with: Python · OpenAI · Market data API · FastAPI
Problem and response
A monthly finance pack that stopped being assembled by hand. The source data is pulled, transformed and refreshed on a schedule, and the report renders the current position without anyone opening a workbook.
What changed
Scheduled refresh against the accounting source, no manual export
Profit and loss, balance sheet and cash views from one model
Period comparison and variance computed in the model rather than per visual
Row-level security so each viewer sees their own entity
Built with: Power BI · DAX · Power Query · SQL
Problem and response
A reporting layer rather than a single report: a shared data model with consistent definitions, and the individual dashboards built on top of it, so two reports asking the same question return the same number.
What changed
One semantic model with metric definitions held centrally
Report set built on the shared model rather than per-report queries
Scheduled distribution to the people who will not open a portal
Definitions documented alongside the model
Built with: Power BI · Looker Studio · SQL · BigQuery
Problem and response
An operating view for a management team: the measures that matter, at the grain decisions are taken, with drill-through from the summary to the transactions behind it.
What changed
Summary tiles that drill through to the underlying rows
Filters that persist across pages so a question survives navigation
Measures written once in the model and reused across pages
Built with: Power BI · DAX · Power Query
Problem and response
A dashboard built around a defined set of indicators with targets attached, so a reading is against a bar rather than against nothing.
What changed
Each indicator carries its target and its trend
Period-on-period comparison in the model
Alert thresholds surfaced visually rather than buried in a table
Built with: Power BI · DAX · SQL
Problem and response
A KPI dashboard fitted to one organisation's own definitions rather than to a template, including the awkward measures that no standard report carries.
What changed
Metric definitions taken from the client's own policy documents
Non-standard measures implemented in DAX rather than approximated
Layout organised by team, so each audience finds its own section
Built with: Power BI · DAX · Power Query
Problem and response
Test data from a component testing programme turned into a set of statistical graphics: distributions, wear curves and comparisons across product variants, produced as a reproducible script rather than a spreadsheet chart.
What changed
Reproducible plots generated from raw test output
Distribution and variance shown rather than averages alone
Variant comparison on shared axes
Built with: R · RStudio · ggplot2
Problem and response
A segmentation built from behaviour rather than assumption: transaction history clustered into groups, then rendered as a dashboard where a marketer can see who is in each group and what changed since last period.
What changed
Clustering over recency, frequency and value from transaction history
Segment membership refreshed on schedule, not fixed at build
Migration between segments shown period on period
Built with: Python · scikit-learn · Power BI · SQL
Problem and response
A view of suppliers against the terms they agreed to: delivery timeliness, quality returns, price variance and responsiveness, ranked so a procurement conversation starts from the record.
What changed
On-time delivery measured against the agreed date, not the revised one
Quality returns and price variance attributed per vendor
Vendor ranking with the components of the score exposed
Built with: Power BI · DAX · SQL
Problem and response
A shared report for a team that lives in Google Workspace: connected directly to the sources they already use, scheduled to their inboxes, with no new tool to log into.
What changed
Connected to Google Analytics, Sheets and BigQuery sources directly
Scheduled email delivery to stakeholders
Blended sources so one chart can span two systems
Built with: Looker Studio · BigQuery · Google Analytics · Google Sheets
Problem and response
Dashboard development as a delivery rather than a demo: the data model, the transformations, the measures and the report, handed over with the model documented so the client's own analyst can extend it.
What changed
Star schema modelled before any visual was placed
Transformations in Power Query rather than in the source
Measures documented so the model can be extended without the author
Built with: Power BI · DAX · Power Query · SQL
Or choose a filter to narrow the list first.
04
Where the numbers come from
39 sourced figures, 6 kinds of source, and the material behind them.
A figure on this site is a value, what it measures, the artifact it was read from, and the window it covers. Here is how much of each kind there is, and what else a reader can open.
What the site never publishes, and why, is on the sources page too. A reader who wants more than the page shows asks for a walkthrough; nothing restricted is linked to get there.
Send a short description. We will tell you whether to automate it, build around it, staff it, or leave it alone, and which of the systems above it most resembles.