We built the web application, iPhone and Android apps, and admin site for a patient platform for managing skin allergies. Patients can see products matched to their patch test results and learn about their allergens. They can also scan products in a store and track their quality of life. More than 150,000 products were brought into the platform. About 140,000 raw ingredient names were normalized to roughly 40,000 canonical ingredients, while retaining the variants and relationships needed for allergen matching.
A patient starts with patch test results entered by a physician. The platform uses those allergens to generate a personal list of products that do not contain them. Patients can search by product type, brand, or name, or scan a barcode while shopping.
The catalogue contains more than 150,000 products. Patients and clinicians can suggest products and report ones that have been discontinued. They can also rate the products they use. Each allergen comes with educational material. The platform also records quality of life over time using the questions defined by the customer.
The ingredient data has to be dependable. A missed allergen can affect the product list shown to a patient.
The customer came to us with an existing patient platform that needed an update to its software and interfaces. The mobile and web experiences had diverged, and patient feedback was never built in. The product catalogue also needed to grow. We took on all four pieces: the web application for patients and physicians, the iPhone app, the Android app, and the admin site.
The build covers the customer's requirements across the patient, physician, and administration workflows.
| Area | What it covers |
|---|---|
| Software and interfaces | Modernise the outdated web and mobile software for patients and clinicians |
| Mobile and web sync | Bring the mobile site and the app to the same look, feel and behaviour |
| Feedback | A built in mechanism for patients to report problems and suggest products |
| Product coverage | Expand the number of products in the database |
| Product data API | Integrate a third party product data API for names, ingredients, categories, manufacturers, images and UPC codes |
| Search | Fuzzy matching, spelling tolerance and predictions on one search page |
| Administration | Manage products, ingredients, users and reports from one admin site |
The platform is live and the engagement is ongoing. The ingredient data was one of the main engineering problems.
Product data comes from a third party API. Its ingredient lists are extracted from packaging with OCR. The output contained stray characters, merged ingredients, and different spellings and naming conventions for the same ingredient.
Each variation was stored as a separate ingredient, taking the table to about 140,000 unique names.
The product list depends on matching a patient's allergens against ingredient lists. Different names for the same allergen can break that match and affect the product result. The same variations also make ingredient search harder.
Cleaning 140,000 strings by hand was not practical. Rules handled the common cases, but the remaining records had many different forms of noise.
We ran two language model passes across the ingredient table.
The first pass split combined ingredient strings into individual names. It separated ingredients that OCR had joined together and removed stray characters around names. Simple cases went through fixed rules, and the model stepped in wherever the pattern did not fit.
The second pass mapped each parsed name to its INCI name, the International Nomenclature of Cosmetic Ingredients. Different spellings and trade names for the same substance were consolidated into one record. INCI is also the naming system used on cosmetic labels.
The raw list contained about 140,000 names. After normalization, it contained roughly 40,000 canonical ingredients, with the source variants retained.
We used a mix of OpenAI models and self hosted open weight models, picking whichever fit a given step best.
The ingredient data is one part of the platform. The product data API supplies names, ingredients, categories, manufacturers, images, and UPC codes on a regular refresh. Products already in the system that are not in the API are migrated and brought into the same structure.
Search uses fuzzy matching, spelling tolerance, and predictions. Patients and physicians can enter part of an ingredient name and find the relevant record. Ingredients can be selected as potential allergens, and barcode scanning lets patients check a product while shopping.
The admin site manages products, ingredients, cross reactor and synonym lists, users, and reports. It also handles notifications, patient feedback with photo upload, education content, and quality of life tracking. The web and mobile applications share the same interface, with hosting designed to meet HIPAA requirements.
The same issue occurs when reference data comes from OCR, user entry, or several vendors using different naming conventions. Simple duplicates and formatting differences go through rules, and whatever is left gets checked against the chosen reference standard.
A model can map a name incorrectly, so the output needs a review path and an approved or unapproved status for each record. Standardisation also requires a reference standard. INCI provides one for cosmetics; another domain may require a different standard.
Whether a hosted or self hosted model makes more sense comes down to volume, cost, and the data handling rules that apply. We work with both approaches. The same team can handle the cloud, data pipeline, model processing, and resulting data tables.
The physician enters the patch test results, and from there the platform builds a list of products that leave out whatever allergens those results flagged. A patient can pull that list up at home, or scan a barcode while out shopping. The platform also tracks quality of life and gives patients background on each allergen it flags.
Ingredient lists came from a third party product data API using OCR from packaging, and OCR is noisy. It sometimes misread characters, merged two ingredients into one string, or spelled the same ingredient differently from one package to the next. Each variant like that got its own entry, and the table grew to roughly 140,000 names in total.
Two language model passes did the work. One pass broke apart ingredient strings that had been run together into their separate names. The other matched each of those names to its INCI name, so two names for the same ingredient ended up as a single record. Between the two passes, the list went from about 140,000 names down to about 40,000.
Some steps ran on OpenAI's models, and others ran on open weight models we host ourselves, picked task by task.
Yes, it has been live for a while now, and we keep extending it.
Tell us what the platform needs to do and what data it uses. We can discuss the scope.
Start a conversation