[{"data":1,"prerenderedAt":1107},["ShallowReactive",2],{"\u002Fwork":3},[4,305,474,650,796,938],{"id":5,"title":6,"body":7,"description":266,"extension":267,"featureImage":268,"featured":21,"links":269,"meta":270,"navigation":21,"order":271,"path":272,"seo":273,"stem":274,"tags":275,"tools":279,"__hash__":304},"work_en\u002Fwork\u002Fagentic-analysis-report.md","Agentic Analysis Report",{"type":8,"value":9,"toc":254},"minimark",[10,14,24,29,32,36,43,49,55,59,62,65,76,80,83,86,91,94,97,100,104,107,110,113,121,125,128,131,134,137,144,151,155,158,161,164,171,175,181,187,193,199,206,210,213,247,251],[11,12,6],"h1",{"id":13},"agentic-analysis-report",[15,16,17],"p",{},[18,19],"video",{"src":20,"controls":21,"preload":22,"muted":21,"poster":23},"\u002Fimages\u002Fagentic-analysis-report\u002Fanalysis-report.webm",true,"none","\u002Fimages\u002Fagentic-analysis-report\u002Fanalysis-report-feature.png",[25,26,28],"h2",{"id":27},"tldr","TL;DR",[15,30,31],{},"Designed and led frontend development of the Agentic Analysis Report, the most technically ambitious feature shipped during my time at Keatext. The report takes a CSV through the NLP pipeline and an LLM to generate a detailed written analysis: an overall summary, breakdown of key topics, recommendations, and a short implementation roadmap. It also included a filtering workflow, in-browser PDF export, multi-language generation, and an agentic chat interface for querying the dataset. A marquee demo feature that generated strong excitement with prospective customers.",[25,33,35],{"id":34},"context","Context",[15,37,38,42],{},[39,40,41],"strong",{},"My role:"," Designer and primary frontend developer; approximately 50% of active implementation, with involvement reviewing every PR that shipped",[15,44,45,48],{},[39,46,47],{},"Stack:"," React, TypeScript, RTK Query, server-sent events, react-pdf",[15,50,51,54],{},[39,52,53],{},"Timeline:"," Design and development from Q3 2025; first release Q4 2025; filtering, PDF, agent panel, and additional features shipping through Q1-Q2 2026; multi-language support in QA",[25,56,58],{"id":57},"background","Background",[15,60,61],{},"The Agentic Analysis Report was the centrepiece of a longer-running initiative to turn Keatext into an automonous analyst, reducing the interpretive work a CX professional has to do by having the product do more of it. Earlier steps in that initiative included Focus Recommendations and its Actionable Insights module. The Agentic Analysis Report represented a step change: a full written report, generated by an LLM, grounded in the platform NLP pipeline output.",[15,63,64],{},"The project started from scratch, built around the upload of a single CSV containing any number of text and metadata fields. Unlike previous implementations that required users to manually configure the satisfaction field, the Agentic Analysis Report detected it automatically in the backend. Users could correct a mis-identified field, but in most cases the setup required nothing from them. The question driving the project was how much of the analytical workflow we could hand off to the model.",[15,66,67],{},[68,69,70,71],"em",{},"Focus Recommendations, which the Agentic Analysis Report largely superseded, is covered in a ",[72,73,75],"a",{"href":74},"\u002Fwork\u002Ffocus-recommendations","separate case study ->",[25,77,79],{"id":78},"what-i-did","What I did",[15,81,82],{},"I designed the feature end-to-end and led frontend development, handling the report display, API integration, intermediate and error states, chart implementation, filtering workflow, PDF generation, and the agent interface. I also proposed the architecture for multi-language support and collaborated with the NLP team to translate elasticity into something understandable for non-technical users.",[15,84,85],{},"Four problems shaped the most important decisions and customer interviews during the prototype phase shaped what the feature became.",[87,88,90],"h3",{"id":89},"research-and-refinement","Research and refinement",[15,92,93],{},"We involved customers through interviews using an early prototype, testing assumptions before committing to the full build. The findings changed the feature in concrete ways.",[15,95,96],{},"There were initially sections for \"topics\" and \"drivers\". Interviews showed users did not meaningfully distinguish between them; the separation added structure without adding clarity. We merged them. A segmentation analysis that had performed well in prototyping did not meet expectations with real customers and was cut entirely.",[15,98,99],{},"Impact was the most significant shift. The prototype presented it primarily as a number, which required explanation and created friction. We moved it to the meter visualisation, keeping the underlying figures accessible for users who wanted to go deeper but leading with the visual. This became the general principle: move from numbers to labels and visualisations where possible, preserving depth without surfacing it by default. The interviews also clarified which sections of the report needed descriptive text to orient users, and which could stand on their own, directly informing how the LLM output was structured between prose and data.",[87,101,103],{"id":102},"designing-for-constrained-space","Designing for constrained space",[15,105,106],{},"The application was built around vertical panels (navigation, filters, data) that had accumulated over time. Adding a chat interface for the agent introduced significant pressure on horizontal space, particularly at 1366x768, the smallest viewport we needed to support according to our user data.",[15,108,109],{},"The core constraint was that the agent panel needed to be resizable but not collapsible. Navigation was already collapsible, and reasonable to assume users would collapse it during report workflows where it is not a core part of the task. The filter panel was also collapsible. The problem was primarily the report configuration screen, which included a data table, and where the agent would ultimately be implemented as well.",[15,111,112],{},"I landed on a horizontal layout for the filters, positioned above the table rather than in a side panel. This freed up the horizontal space the table needed, reduced the total number of competing panels, and established a reusable pattern for additional configuration options in future screens.",[15,114,115],{},[116,117],"img",{"alt":118,"src":119,"title":120},"Layers are now laid out above the table, saving critical horizontal space","\u002Fimages\u002Fagentic-analysis-report\u002Freport-creation-filters.png","Report configuration screen with horizontal filters",[87,122,124],{"id":123},"communicating-impact","Communicating impact",[15,126,127],{},"Similar to Focus Recommendations, the Agentic Analysis Report surfaces a four-quadrant chart plotting topics by two axes. The methodology here uses elasticity rather than correlation, a more rigorous measure of how strongly changes in a topic relate to changes in satisfaction. The challenge was the same: making this meaningful to CX professionals who are unlikely to be familiar with elasticity as a concept.",[15,129,130],{},"I called it \"impact\", avoiding the term entirely in the user interface.",[15,132,133],{},"The net elasticity value (positive minus negative) was visualised as a meter. The meter could be expanded to reveal the positive and negative components separately, giving users who wanted more detail a path to it without surfacing complexity by default.",[15,135,136],{},"Sorting introduced a subtler problem. Sorting topics by net elasticity alone would misrepresent volatile topics; a subject with strong positive and negative elasticity would produce a small net value and drop toward the bottom of the list, despite being highly significant. I used total magnitude (the absolute sum of positive and negative elasticity) as the sort value instead, surfacing the most impactful topics, rather than the most polarized. Total magnitude was not exposed directly to users; it informed the order without requiring explanation.",[15,138,139],{},[116,140],{"alt":141,"src":142,"title":143},"The impact meter could be expanded to access raw stats","\u002Fimages\u002Fagentic-analysis-report\u002Fimpact-meter-states.png","Impact meter, collapsed and expanded",[15,145,146],{},[116,147],{"alt":148,"src":149,"title":150},"The impact chart classifies topics as strengths, weaknesses, or nice to have","\u002Fimages\u002Fagentic-analysis-report\u002Fimpact-chart.png","Impact vs. Satisfaction chart",[87,152,154],{"id":153},"the-agent-interface","The agent interface",[15,156,157],{},"The agent panel provides a chat interface for querying the dataset and asking questions about the report following generation. The longer-term vision is to bring the agent into the full application, not just the report.",[15,159,160],{},"The design focus for the agent was microinteractions. In a data-heavy application where most interactions are immediate, a conversational interface introduces a new kind of waiting, and how that wait feels matters. Chat elements appearing without transition are jarring; they break the conversational flow the interface is trying to establish.",[15,162,163],{},"I implemented subtle animations and transitions throughout: elements easing in rather than snapping, and a bouncing dot animation while waiting for agent responses, the same pattern chat applications use to show a contact is typing. The effect is small but meaningful: it signals that work is being done, maintains the sense of a live exchange, and gives the interface a quality of responsiveness that the underlying latency would otherwise undermine.",[15,165,166],{},[18,167],{"src":168,"style":169,"controls":21,"preload":22,"muted":21,"poster":170},"\u002Fimages\u002Fagentic-analysis-report\u002Fchat-interaction.webm","width: 380px;","\u002Fimages\u002Fagentic-analysis-report\u002Fchat-interaction.png",[25,172,174],{"id":173},"additional-technical-work","Additional technical work",[15,176,177,180],{},[39,178,179],{},"Multi-language reports:"," The application supported English and French localisation via react-i18n, but the LLM could generate reports in many languages. This created a mismatch: fixed UI strings from the application and variable content from the model needed to coexist in the same document. I proposed a model for storing the entire report content (including fixed strings) in the backend, translating and caching them on demand, and assembling the final output server-side. This avoided the application needing to handle arbitrary language rendering and kept the translation logic in one place. It also brought consistency to an inherently non-deterministic process: fixed strings were translated once and cached rather than regenerated each time, and the LLM was never asked to produce them, only to translate. Key descriptions stay consistent from one report run to the next, regardless of language.",[15,182,183,186],{},[39,184,185],{},"Chart improvements:"," The report chart shared its approach with Focus Recommendations but with a more dynamic implementation of quadrant boundaries. I added label collision detection to prevent topic labels from overlapping, a meaningful improvement on the FR chart, which had no mechanism for this.",[15,188,189,192],{},[39,190,191],{},"In-browser PDF generation:"," The report was designed as a final deliverable; something clients could hand directly to stakeholders rather than a screen to work from. The PDF was generated in-browser using react-pdf, producing a document with properly selectable rich text rather than a rasterised image. For a report intended to be shared, annotated, and quoted from, text quality is not a cosmetic concern.",[15,194,195,198],{},[39,196,197],{},"AI-assisted development:"," I used AI tooling throughout the project for early iteration, prototyping, and implementation. On a feature of this scope, the time saved was huge.",[15,200,201],{},[116,202],{"alt":203,"src":204,"title":205},"The quality of the in-browser PDF generation allowed it to be easily shared with stakeholder","\u002Fimages\u002Fagentic-analysis-report\u002Fpdf-report-example.png","Page preview from the PDF export",[25,207,209],{"id":208},"shipping-incrementally","Shipping incrementally",[15,211,212],{},"The feature shipped in stages:",[214,215,216,223,229,235,241],"ul",{},[217,218,219,222],"li",{},[39,220,221],{},"Q4 2025:"," First version of the report: generation, display, chart, markdown rendering, intermediate and error states",[217,224,225,228],{},[39,226,227],{},"Late Q1 2026:"," In-browser PDF export",[217,230,231,234],{},[39,232,233],{},"Q1-Q2 2026:"," Filtering workflow; composable filter component refactor",[217,236,237,240],{},[39,238,239],{},"Q2 2026:"," Agent panel; roadmap to retire Focus Recommendations",[217,242,243,246],{},[39,244,245],{},"Q2-Q3 2026:"," Multi-language support (in QA at time of writing)",[25,248,250],{"id":249},"outcome","Outcome",[15,252,253],{},"The Agentic Analysis Report became a marquee feature for demos and industry events, generating strong excitement from prospective customers. The sales cycle was too long to attribute closed deals at the time I left, but the reception during the beta phase was the strongest of any feature launched during my time at the company.",{"title":255,"searchDepth":256,"depth":257,"links":258},"",2,1,[259,260,261,262,263,264,265],{"id":27,"depth":256,"text":28},{"id":34,"depth":256,"text":35},{"id":57,"depth":256,"text":58},{"id":78,"depth":256,"text":79},{"id":173,"depth":256,"text":174},{"id":208,"depth":256,"text":209},{"id":249,"depth":256,"text":250},"AI-generated CX report including an agentic chat interface","md","\u002Fimages\u002Fagentic-analysis-report\u002Fagentic-report-thumbnail.png",null,{},0,"\u002Fwork\u002Fagentic-analysis-report",{"title":6,"description":266},"work\u002Fagentic-analysis-report",[276,277,278],"Design","Development","AI",[280,284,288,292,296,300],{"name":281,"img":282,"href":283},"Figma","\u002Fimages\u002Ftools\u002Ffigma.svg","https:\u002F\u002Fwww.figma.com",{"name":285,"img":286,"href":287},"React","\u002Fimages\u002Ftools\u002Freact.svg","https:\u002F\u002Freact.dev",{"name":289,"img":290,"href":291},"TypeScript","\u002Fimages\u002Ftools\u002Ftypescript.svg","https:\u002F\u002Fwww.typescriptlang.org",{"name":293,"img":294,"href":295},"MUI","\u002Fimages\u002Ftools\u002Fmui.svg","https:\u002F\u002Fmui.com",{"name":297,"img":298,"href":299},"RTK Query","\u002Fimages\u002Ftools\u002Fredux.svg","https:\u002F\u002Fredux-toolkit.js.org",{"name":301,"img":302,"href":303},"react-pdf","\u002Fimages\u002Ftools\u002Freact-pdf.png","https:\u002F\u002Freact-pdf.org","naxtIdYO7aVBMN4rM4tQf88Ct2tcxZseZ2JlBzzllpo",{"id":306,"title":307,"body":308,"description":461,"extension":267,"featureImage":462,"featured":21,"links":269,"meta":463,"navigation":21,"order":257,"path":74,"seo":464,"stem":465,"tags":466,"tools":468,"__hash__":473},"work_en\u002Fwork\u002Ffocus-recommendations.md","Focus Recommendations",{"type":8,"value":309,"toc":453},[310,313,320,322,325,327,332,337,341,344,347,349,352,355,359,362,369,372,379,385,388,392,395,398,405,409,412,415,418,425,429,432,435,438,448,450],[11,311,307],{"id":312},"focus-recommendations",[15,314,315],{},[116,316],{"alt":317,"src":318,"title":319},"Focus Recommendations provided key insights on what needs attention, now","\u002Fimages\u002Ffocus-recommendations\u002Ffocus-recommendations-feature.png","The Focus Recommendations page",[25,321,28],{"id":27},[15,323,324],{},"Designed Focus Recommendations, the application's approach to Key Driver Analysis, from the ground up. The feature translated complex correlation and satisfaction data from our NLP\u002Fstats team into actionable insight for CX professionals: which topics were driving their scores, and where to focus efforts. It shipped in August 2022, later gained AI-generated recommendations, and became a key demo feature and factor in closing clients. As the product matured, I identified that a newer feature had superseded most of its functionality, and contributed to the roadmap to retire it.",[25,326,35],{"id":34},[15,328,329,331],{},[39,330,41],{}," End-to-end design, internal testing and iteration; implementation contributions on the FR chart and Actionable Insights widgets",[15,333,334,336],{},[39,335,53],{}," Initial release August 2022; Actionable Insights October 2023",[25,338,340],{"id":339},"the-opportunity","The opportunity",[15,342,343],{},"There was nothing like Focus Recommendations in the product before it. The platform was already strong at surfacing what customers were saying, but it did not tell clients what to do about it. FR was conceived to bridge that gap: not just analysis, but recommendations. A client could see which topics were driving their satisfaction score (whether NPS, CSAT, or another scale) up or down, and where to focus their efforts.",[15,345,346],{},"The initial concept came from our NLP\u002Fstats team. My role was to translate it into something a CX professional building reports for their stakeholders could actually use.",[25,348,79],{"id":78},[15,350,351],{},"I owned the design end-to-end, translating the statistical concept into something usable, testing and iterating internally, and contributing to implementation on the FR chart and Actionable Insights widgets.",[15,353,354],{},"Three design problems defined the project.",[87,356,358],{"id":357},"turning-correlation-into-a-visual","Turning correlation into a visual",[15,360,361],{},"The four-quadrant chart handled the big picture; plotting topics by correlation and average satisfaction score made priorities immediately clear. The harder problem was the table view: communicating the same information at a topic level, in a single icon, without requiring users to understand what correlation means.",[15,363,364],{},[116,365],{"alt":366,"src":367,"title":368},"The chart allows quick identification of what really needs attention","\u002Fimages\u002Ffocus-recommendations\u002Ffocus-recommendations-chart.png","Close up on the chart",[15,370,371],{},"I landed on a target-like icon: three concentric rings, where more rings filled indicated stronger impact. Positive or negative impact was communicated through color (green for positive, red for negative), deliberately breaking from our praise\u002Fproblem palette, since this analysis is based on satisfaction scores rather than our sentiment categories. An arrow icon and correlation percentage reinforced the direction for users with color blindness.",[15,373,374],{},[116,375],{"alt":376,"src":377,"title":378},"Impact icons expressed magnitude and polarity","\u002Fimages\u002Ffocus-recommendations\u002Ftarget-icons.png","Target icon variants",[15,380,381],{},[116,382],{"alt":383,"src":384},"The table view shows a bit more detail","\u002Fimages\u002Ffocus-recommendations\u002Ftable-view.png",[15,386,387],{},"The first version used an absolute threshold to determine how many rings to fill. Testing revealed the problem: datasets vary significantly across clients, and absolute thresholds produced wildly inconsistent results: some clients seeing mostly three-ring topics, others mostly one. We moved to a relative calculation, setting thresholds against the distribution of results within each dataset. The icon became stable and meaningful regardless of dataset characteristics. Labelling went through similar iteration; the language describing quadrants and impact levels needed to be precise without requiring a statistics background.",[87,389,391],{"id":390},"expanding-beyond-nps","Expanding beyond NPS",[15,393,394],{},"The initial release supported a single NPS response-question pair, the most common case but one that excluded clients using other satisfaction scales or running complex surveys with multiple rating-response pairs.",[15,396,397],{},"We extended coverage in stages. First, a modal that let users order any field (numeric, or non-numeric, a Likert scale, for example) from least to most satisfied and use it as the response variable. Then support for multiple rating-response pairs, enabling analysis of surveys containing several question sets, a meaningful unlock for enterprise clients running complex research.",[15,399,400],{},[116,401],{"alt":402,"src":403,"title":404},"Ratings could be easily re-ordered in terms of satisfaction","\u002Fimages\u002Ffocus-recommendations\u002Fratings-configuration.png","The ratings configuration dialog",[87,406,408],{"id":407},"actionable-insights","Actionable Insights",[15,410,411],{},"In October 2023 we added Actionable Insights: AI-generated recommendations on how to improve the topics identified as key drivers. Rather than surface recommendations for every topic, I defined selection criteria (the three most correlated negative drivers and three most correlated positive), keeping the output focused and actionable rather than exhaustive.",[15,413,414],{},"The recommendations appeared as paginated cards above the chart, each covering a single topic with the option to expand for more detail. I included a dismiss mechanism on each card, which served two purposes: letting users clear recommendations they had acted on or found irrelevant, and giving us an implicit feedback signal on recommendation quality. A PDF export of the full recommendations summary supported the workflow of clients building reports for stakeholders.",[15,416,417],{},"The list of key opinions in the table view was also migrated to an AI-generated summary around this time, reducing noise and improving readability.",[15,419,420],{},[116,421],{"alt":422,"src":423,"title":424},"Actionable Insights provide real recommendations to improve satisfaction","\u002Fimages\u002Ffocus-recommendations\u002Factionable-insights.png","The Actionable Insights cards",[25,426,428],{"id":427},"what-came-next","What came next",[15,430,431],{},"As the Agentic Analysis Report neared the end of beta, I recognised that the two features had converged significantly. The Agentic Analysis Report used elasticity (surfaced to users as \"impact\" to keep the language accessible) and organised its quadrants differently: strengths, weaknesses, nice-to-have, and a fourth left intentionally unlabelled. It did almost everything Focus Recommendations did, in more detail and with better methodology.",[15,433,434],{},"The gap was narrow but real: the Agentic Analysis Report did not yet support non-NPS fields or complex multi-pair surveys. I wrote up a roadmap to bring the two features to parity and retire Focus Recommendations, presented it to the product owner, validated the approach, and turned the items into prioritized backlog tickets. The main gaps to close were support for non-NPS fields and complex multi-pair surveys in the Agentic Analysis Report, and bringing its impact-satisfaction chart to the dashboard. Reusable, saveable filtersets were smaller but also on the list.",[15,436,437],{},"This was not a decision made at the outset; it was a product judgment call I made as the two features converged, close to the end of the Agentic Analysis Report beta.",[15,439,440],{},[68,441,442,443,447],{},"The dashboard widget that brought Focus Recommendations into the broader product is described in the ",[72,444,446],{"href":445},"\u002Fwork\u002Fcustomizable-dashboard","Customizable Dashboard case study ->",".",[25,449,250],{"id":249},[15,451,452],{},"Focus Recommendations shipped in August 2022 and became a key demo feature and a factor in closing at least one client. It represented a meaningful expansion of the product value proposition, from surfacing what customers were saying to telling clients what to do about it. The approach it validated was carried forward and improved in the Agentic Analysis Report.",{"title":255,"searchDepth":256,"depth":257,"links":454},[455,456,457,458,459,460],{"id":27,"depth":256,"text":28},{"id":34,"depth":256,"text":35},{"id":339,"depth":256,"text":340},{"id":78,"depth":256,"text":79},{"id":427,"depth":256,"text":428},{"id":249,"depth":256,"text":250},"Key driver analysis tool for CX satisfaction scores","\u002Fimages\u002Ffocus-recommendations\u002Ffocus-recommendations-thumbnail.png",{},{"title":307,"description":461},"work\u002Ffocus-recommendations",[276,277,467],"Data",[469,470,471,472],{"name":281,"img":282,"href":283},{"name":285,"img":286,"href":287},{"name":289,"img":290,"href":291},{"name":293,"img":294,"href":295},"4BDt-d7VgTGv6QmnKlZ6NFOt9X0Ym533sBkeRANCtmc",{"id":475,"title":476,"body":477,"description":639,"extension":267,"featureImage":487,"featured":21,"links":269,"meta":640,"navigation":21,"order":256,"path":445,"seo":641,"stem":642,"tags":643,"tools":644,"__hash__":649},"work_en\u002Fwork\u002Fcustomizable-dashboard.md","Customizable Dashboard",{"type":8,"value":478,"toc":631},[479,482,489,491,494,496,502,507,512,516,519,526,528,531,534,538,541,544,547,550,553,561,568,572,575,578,584,587,594,596,599,602,609,616,618,621,625,628],[11,480,476],{"id":481},"customizable-dashboard",[15,483,484],{},[116,485],{"alt":486,"src":487,"title":488},"A highly-configurable dashboard allowing at-a-glance insights","\u002Fimages\u002Fcustomizable-dashboard\u002Fdashboard-feature.png","The dashboard with Add Widget dialog open",[25,490,28],{"id":27},[15,492,493],{},"Designed and built a customizable dashboard from the ground up for an AI text analytics platform serving the CX industry. End-to-end ownership: competitive research, UX design, internal testing, and front-end implementation. The dashboard became the primary entry point to the application and a key factor in closing and renewing multiple clients.",[25,495,35],{"id":34},[15,497,498,501],{},[39,499,500],{},"Product:"," An AI text analytics platform for the CX industry. An NLP pipeline extracted topic-opinion pairs from free-form customer feedback, classifying them as praises, problems, suggestions, questions, or neutral, and scoring them. The platform integrated with many data sources and augmented analysis with generative AI.",[15,503,504,506],{},[39,505,41],{}," Sole designer and front-end implementer",[15,508,509,511],{},[39,510,53],{}," Initial release Q3-Q4 2021, with iterative feature releases through 2025",[25,513,515],{"id":514},"the-problem","The problem",[15,517,518],{},"The platform surfaced rich, structured insight from customer feedback (sentiment breakdowns, topic analysis, volume trends, source data) but only through static table and chart views. A fixed dashboard existed, but it was completely uncustomizable; every client saw the same thing regardless of what they actually needed to monitor. There was no way to tailor the interface to a specific use case, and the product's depth was not visible in sales demos. Clients had limited reason to log in regularly.",[15,520,521],{},[116,522],{"alt":523,"src":524,"title":525},"The previous dashboard had next to no customization","\u002Fimages\u002Fcustomizable-dashboard\u002Fold-dashboard.png","The old dashboard",[25,527,79],{"id":78},[15,529,530],{},"I led the project from competitive research through production implementation, designing and building a fully customizable dashboard with a layout editor, a configurable widget system, multiple chart types, internal sharing, public unauthenticated views, a dashboard switcher, and an add-widget flow.",[15,532,533],{},"Three problems shaped the most important decisions.",[87,535,537],{"id":536},"the-layout-editor","The layout editor",[15,539,540],{},"Resizing and repositioning widgets only happens in a dedicated edit mode, a deliberate architectural decision that keeps layout changes separate from normal dashboard use. Within that mode, the remaining challenge was making the interactions precise and clear: supporting drag and drop, communicating what resize and reposition gestures would do before a user committed to them, keeping the grid compact without overriding the intended layout, and ensuring click targets were distinct enough to avoid misfires. This required designing and speccing each widget state explicitly (base, edit, resize X, resize Y, hover, and dragging), each with its own affordances.",[15,542,543],{},"Given the complexity of the grid behaviour (compaction logic, resize constraints, drag interactions), I built code prototypes to explore and validate how the interactions would feel before committing to the full implementation. Some interaction problems only surface at runtime; prototyping in code rather than Figma meant the testing that followed was based on realistic behaviour.",[15,545,546],{},"Testing with internal users mostly validated the direction. One exception: the icon indicating a widget could be moved was not legible. We updated it and the problem resolved. The other interaction states and affordances held up without changes.",[15,548,549],{},"I scoped out one feature during the project: pre-built dashboard templates. They were unnecessary; users could build a suitable first dashboard quickly, the sales team typically set one up during onboarding, and a duplicate feature already gave anyone a path to reuse a dashboard as a starting point.",[15,551,552],{},"The dashboard also introduced a new filter model. The original static dashboard had a global filter applied across the whole view. We made a deliberate decision to remove this in favour of widget-level independence, keeping only sentiment filters as global. Each widget could carry its own filters, local and ephemeral, with the option to make the reusable. The tradeoff was intentional: widget independence was more valuable at this stage than global dashboard filtering and reduced the complexity of the feature. This was flagged early by the development team and integrated into the design.",[15,554,555],{},[18,556],{"src":557,"controls":21,"preload":22,"muted":21,"poster":558,"alt":559,"title":560},"\u002Fimages\u002Fcustomizable-dashboard\u002Flayout-editing.webm","\u002Fimages\u002Fcustomizable-dashboard\u002Flayout-editing.png","The dashboard allowed custom layouts, but tried to fill holes in the layout intelligently","Layout editing",[15,562,563],{},[116,564],{"alt":565,"src":566,"title":567},"Drag and drop interactions required in-depth interaction states and specs","\u002Fimages\u002Fcustomizable-dashboard\u002Finteraction-states.png","The spec for interaction states in widgets",[87,569,571],{"id":570},"the-color-system","The color system",[15,573,574],{},"The platform charts were built around a semantic color palette tied to feedback categories (green for praise, yellow for problems, blue for suggestions, light purple for questions, grey for neutral). These colors carried meaning. When we added chart types like time series, where colors represent data series rather than feedback categories, that palette could not be reused; the associations would be misleading, and five colors were not enough anyway. We needed a categorical palette that could distinguish up to 20 series clearly, with no implied meaning.",[15,576,577],{},"I followed IBM inclusive color sequence methodology closely, generating tints for each hue using Colorbox.io, working out the full palette in Figma, then adapting and extending our MUI theme to implement it systematically. Each color was designed to meet 3:1 contrast against light backgrounds.",[15,579,580],{},[116,581],{"alt":582,"src":583},"A core set of colours, selected for data visualization","\u002Fimages\u002Fcustomizable-dashboard\u002Fbase-palette.png",[15,585,586],{},"Contrast between colors was handled structurally: the grid was organized using a chevron skip so that only hues with sufficient contrast between them were adjacent in sequence, and a usage rule was established to always iterate through the palette in order rather than picking colors freely. The accessibility guarantees are built into the system; they do not depend on individual judgment calls at implementation time.",[15,588,589],{},[116,590],{"alt":591,"src":592,"title":593},"A repeating chevron pattern was used to sequence colours","\u002Fimages\u002Fcustomizable-dashboard\u002Fchevron-skip.png","The chevron-skip selection methodology",[87,595,307],{"id":312},[15,597,598],{},"Focus Recommendations is the application approach to Key Driver Analysis, combining a topic's correlation with satisfaction score changes against its average satisfaction score to surface what is actively driving client satisfaction or dissatisfaction, and where to focus efforts.",[15,600,601],{},"I was heavily involved in Focus Recommendations as a standalone feature. The dashboard widget was the piece that brought it into the broader product, translating the four-quadrant driver chart and actionable insights lists so it worked both on the dedicated Focus Recommendations page and as a resizable widget alongside other dashboard content. Adapting the feature filter logic to coexist with the dashboard filter architecture required close collaboration with development to map the differences and find a clean integration point.",[15,603,604],{},[116,605],{"alt":606,"src":607,"title":608},"The Focus Recommendations widgets presented their own unique challenges","\u002Fimages\u002Fcustomizable-dashboard\u002Ffocus-recommendations-widget.png","The Focus Recommendations widget",[15,610,611],{},[68,612,613,614,447],{},"Focus Recommendations is covered in depth as a ",[72,615,75],{"href":74},[25,617,250],{"id":249},[15,619,620],{},"The dashboard shipped in Q3-Q4 2021 and became the primary entry point to the application and the lead feature in client demos. It was cited as a key factor in closing and renewing several clients, meaningful stakes for a small company where each contract counted.",[25,622,624],{"id":623},"after-launch","After launch",[15,626,627],{},"The dashboard continued to evolve. The initial widget set was minimal and largely fixed (sentiment scores, volume, record counts, source breakdowns, top topics). These were progressively replaced by fully customizable chart widgets: bar charts, time series, data tables, pie charts, a number widget, and a reworked heatmap. A third wave added more complex, analytically advanced widgets: rich text notes, matrix questions, and Focus Recommendations.",[15,629,630],{},"A dashboard-level filter also shipped in a later cycle, reintroducing cross-dashboard filtering in a more powerful form. Applied across all widgets simultaneously, always narrowing rather than widening their individual filters, and independent of the application's global analysis filters, it allowed users to slice a whole dashboard without losing the independent context each widget carried. The filter model, designed upfront to support widget-level independence, extended cleanly to accommodate it.",{"title":255,"searchDepth":256,"depth":257,"links":632},[633,634,635,636,637,638],{"id":27,"depth":256,"text":28},{"id":34,"depth":256,"text":35},{"id":514,"depth":256,"text":515},{"id":78,"depth":256,"text":79},{"id":249,"depth":256,"text":250},{"id":623,"depth":256,"text":624},"Customizable analytics dashboard with a drag-and-drop editor",{},{"title":476,"description":639},"work\u002Fcustomizable-dashboard",[276,277,467],[645,646,647,648],{"name":281,"img":282,"href":283},{"name":285,"img":286,"href":287},{"name":289,"img":290,"href":291},{"name":293,"img":294,"href":295},"F4-uEASC5eatTDTn8iLzl4qQ6uRV4icC_N0ELhrkaRA",{"id":651,"title":652,"body":653,"description":752,"extension":267,"featureImage":660,"featured":753,"links":754,"meta":767,"navigation":21,"order":768,"path":769,"seo":770,"stem":771,"tags":772,"tools":774,"__hash__":795},"work_en\u002Fwork\u002Fschedio.md","Schedio: A Vue design system",{"type":8,"value":654,"toc":746},[655,658,662,665,669,685,691,694,698,707,713,719,722,726,729,735,737],[11,656,652],{"id":657},"schedio-a-vue-design-system",[116,659],{"src":660,"alt":661,"title":661},"\u002Fimages\u002Fschedio\u002Fschedio-feature.png","schedio",[15,663,664],{},"Schedio is a Vue component library and design system I built for Spartan Bio. The goal was to formalize design at a small company where efficiency and consistency mattered more, not less, because of the team's size. I initiated it independently, shipped v1 over a couple of months, and maintained it for two years. The name comes from the Greek word for design (schédio, more or less); Spartan likes Greek themes.",[25,666,668],{"id":667},"design-tokens","Design tokens",[15,670,671,672,678,679,684],{},"The first step was defining the system's foundational elements: type, colour, spacing, motion. I structured these as ",[72,673,677],{"href":674,"rel":675},"https:\u002F\u002Fwww.lightningdesignsystem.com\u002Fdesign-tokens\u002F",[676],"nofollow","design tokens"," using ",[72,680,683],{"href":681,"rel":682},"https:\u002F\u002Fgithub.com\u002Fsalesforce-ux\u002Ftheo",[676],"Theo",", which provided a single source of truth exportable in multiple formats. The tokens ended up informing work not just in Vue, but across our Windows (WPF) and React Native platforms, even where the components themselves couldn't be consumed directly.",[15,686,687],{},[116,688],{"alt":689,"src":690,"title":689},"Working on colors in Theo","\u002Fimages\u002Fschedio\u002Fschedio-tokens-colors.png",[15,692,693],{},"Some tokens, like transition easing and timing, only make sense in the context of components. I worked through the foundational tokens first, then developed them further alongside the component work.",[25,695,697],{"id":696},"component-library","Component library",[15,699,700,701,706],{},"I designed components in Adobe XD (Figma was new at the time and XD had better tooling for what I needed), generating static designs before building. ",[72,702,705],{"href":703,"rel":704},"https:\u002F\u002Fstorybook.js.org\u002F",[676],"Storybook"," provided the development sandbox and documentation layer. Some addons primarily supported React at the time, which required workarounds for Vue; none were significant, and the tradeoff was worth it. Our Windows developer could reference Storybook to understand design intent even when he couldn't consume the components directly.",[15,708,709],{},[116,710],{"alt":711,"src":712,"title":711},"Components in XD","\u002Fimages\u002Fschedio\u002Fschedio-xd.png",[15,714,715],{},[116,716],{"alt":717,"src":718,"title":717},"Schedio in Storybook","\u002Fimages\u002Fschedio\u002Fschedio-storybook.png",[15,720,721],{},"Every component was designed to WCAG 2.0 AA. I used Jest and Storybook to enforce accessibility standards during development rather than audit after the fact.",[25,723,725],{"id":724},"documentation","Documentation",[15,727,728],{},"Storybook is not ideal for non-technical documentation (usage guidelines, interaction philosophy, colour application). I needed somewhere to put it and didn't have the bandwidth to build a separate documentation site, so it stayed in Storybook alongside the components. For a small, mostly technical team, it worked. The limitation was a conscious tradeoff for the scale we were at.",[15,730,731],{},[116,732],{"alt":733,"src":734,"title":733},"Documentation for Schedio","\u002Fimages\u002Fschedio\u002Fschedio-logo-usage.png",[25,736,250],{"id":249},[15,738,739,740,745],{},"Schedio shipped as the foundation for Spartan's Vue corporate site and was used across internal tools. Its design tokens and interaction patterns informed work on our WPF and React Native platforms. Shopify's ",[72,741,744],{"href":742,"rel":743},"https:\u002F\u002Fgithub.com\u002FShopify\u002Fpolaris-react\u002F",[676],"Polaris"," was a significant influence on the approach, particularly its thinking on how a design system should serve a product team without constraining it.",{"title":255,"searchDepth":256,"depth":257,"links":747},[748,749,750,751],{"id":667,"depth":256,"text":668},{"id":696,"depth":256,"text":697},{"id":724,"depth":256,"text":725},{"id":249,"depth":256,"text":250},"A design system and component library for Spartan Bio",false,[755,758,761,764],{"title":756,"href":757},"Schedio","https:\u002F\u002Fspartanbio-design.netlify.app",{"title":759,"href":760},"Schedio fork on GitHub","https:\u002F\u002Fgithub.com\u002Falexkcollier\u002Fschedio",{"title":762,"href":763},"Schedio Tokens","https:\u002F\u002Fspartanbio.github.io\u002Fschedio-tokens\u002F",{"title":765,"href":766},"Schedio Tokens fork on GitHub","https:\u002F\u002Fgithub.com\u002Falexkcollier\u002Fschedio-tokens",{},4,"\u002Fwork\u002Fschedio",{"title":652,"description":752},"work\u002Fschedio",[276,277,773],"Design System",[775,779,783,785,787,791],{"name":776,"img":777,"href":778},"Adobe XD","\u002Fimages\u002Ftools\u002Fxd.svg","https:\u002F\u002Fwww.adobe.com\u002Fca\u002Fproducts\u002Fxd.html",{"name":780,"img":781,"href":782},"Vue.js","\u002Fimages\u002Ftools\u002Fvue.svg","https:\u002F\u002Fvuejs.org",{"name":705,"img":784,"href":703},"\u002Fimages\u002Ftools\u002Fstorybook.svg",{"name":683,"img":786,"href":681},"\u002Fimages\u002Ftools\u002Ftheo.png",{"name":788,"img":789,"href":790},"Sass","\u002Fimages\u002Ftools\u002Fsass.svg","https:\u002F\u002Fsass-lang.com",{"name":792,"img":793,"href":794},"Jest","\u002Fimages\u002Ftools\u002Fjest.png","https:\u002F\u002Fjestjs.io\u002F","sYoB4owvPDR5IRepvb7WHd95c-ymXeRRfJxEcvisWjI",{"id":797,"title":798,"body":799,"description":919,"extension":267,"featureImage":808,"featured":753,"links":269,"meta":920,"navigation":21,"order":921,"path":922,"seo":923,"stem":924,"tags":925,"tools":927,"__hash__":937},"work_en\u002Fwork\u002Fenvironmental-testing-app.md","Environmental Testing App",{"type":8,"value":800,"toc":912},[801,804,809,812,814,817,820,834,837,841,844,847,853,859,862,868,875,879,882,888,891,895,898,901,907,909],[11,802,798],{"id":803},"environmental-testing-app",[15,805,806],{},[116,807],{"alt":798,"src":808,"title":798},"\u002Fimages\u002Fenvironmental-testing-app\u002Flegionella-mobile-feature.jpg",[15,810,811],{},"I was the sole designer on a mobile client for Spartan's Legionella Test, working with a mobile developer to bring a laptop-based system to iOS and Android. Most core features were designed and built before the project was cancelled when the company wound down.",[25,813,515],{"id":514},[15,815,816],{},"The original system ran on a laptop connected to the Spartan Cube via cable, one laptop per Cube, wired. Facilities managers running tests across larger sites needed multiple systems, had to manually check each laptop for results, and were dealing with a significant physical footprint. The system worked; real-world use had made the limitations clear.",[15,818,819],{},"The redesign addressed these directly:",[214,821,822,825,828,831],{},[217,823,824],{},"Mobile control replacing the dedicated laptop",[217,826,827],{},"Wireless connectivity via Bluetooth Low Energy (BLE)",[217,829,830],{},"Support for monitoring multiple Cubes simultaneously",[217,832,833],{},"Results pushed to a remote server",[15,835,836],{},"Core features from the original were carried over: a guided test workflow, step-by-step instructions, and a searchable result log.",[25,838,840],{"id":839},"structure-and-wireframes","Structure and wireframes",[15,842,843],{},"I began by mapping the app's structure around use cases rather than data types, arriving at five sections: test workflow, Cube status, result log, settings, and water source management.",[15,845,846],{},"Wireframes followed for the key screens. The instruction screen needed primary actions reachable without stretching on large phones, which ruled out several top-heavy layouts early. For the result log, I worked through four approaches before the wireframes showed that a segmented list with sticky headers gave the best balance of information density and ease of use.",[15,848,849],{},[116,850],{"alt":851,"src":852,"title":851},"Instruction screen wireframes","\u002Fimages\u002Fenvironmental-testing-app\u002Finstructions-wire.png",[15,854,855],{},[116,856],{"alt":857,"src":858,"title":857},"Log screen wireframes","\u002Fimages\u002Fenvironmental-testing-app\u002Flog-wire.png",[15,860,861],{},"Navigation was an open question. I built a prototype in Adobe XD, loaded it on my phone, and ran hallway tests. The bottom bar layout won; participants liked the quick path to starting a test, and found the result log card on the landing screen confusing.",[15,863,864],{},[116,865],{"alt":866,"src":867,"title":866},"Landing screen wireframes","\u002Fimages\u002Fenvironmental-testing-app\u002Flanding-wire.png",[15,869,870],{},[18,871],{"src":872,"controls":21,"muted":21,"style":873,"poster":874},"\u002Fimages\u002Fenvironmental-testing-app\u002Fnavigation.webm","max-height: 400px;","\u002Fimages\u002Fenvironmental-testing-app\u002Fnavigation-poster.png",[25,876,878],{"id":877},"design-and-prototype","Design and prototype",[15,880,881],{},"After wireframing I moved to Framer, writing a fully interactive prototype with live data and coded interactions. This was the primary handoff tool; the developer flagged anything that couldn't be implemented or needed revision, and we worked through it together.",[15,883,884],{},[18,885],{"src":886,"controls":21,"muted":21,"style":873,"poster":887},"\u002Fimages\u002Fenvironmental-testing-app\u002Fprototype.webm","\u002Fimages\u002Fenvironmental-testing-app\u002Fprototype-poster.png",[15,889,890],{},"The Cube status screen required a workaround for BLE's fundamental limitation: Bluetooth only connects 1-to-1, which would have broken multi-Cube monitoring entirely. Working with the developer, we landed on reading the advertising packets Cubes broadcast passively rather than maintaining a continuous connection. For a running test, we combined a timer (tests take just under an hour) with any packet updates available when in range. Users out of range when a test completed got a notification; those nearby received the result from the BLE advertisement directly. Cubes could also be given meaningful names, and the result log supported filtering.",[116,892],{"src":893,"alt":894,"title":894},"\u002Fimages\u002Fenvironmental-testing-app\u002Fapplied-filters.png","Applied filters",[15,896,897],{},"One problem that wasn't resolved before the project ended: the result filter's double slider. The range of meaningful values was tightly clustered at the low end of a 0-1000 scale, making it difficult to use precisely. The fix was planned (replacing it with checkboxes) but wasn't scheduled before cancellation.",[25,899,277],{"id":900},"development",[15,902,903,904,906],{},"I extended the design tokens from ",[72,905,756],{"href":769}," in Theo to add a TypeScript definition format and React Native-specific transformations, giving the developer a consistent styling foundation. I also contributed to styling code on the implementation side.",[25,908,250],{"id":249},[15,910,911],{},"Most core features were designed and built before Spartan wound down. The project didn't reach production, but the design work held up; the wireframing and prototype process uncovered real usability issues early, and the BLE constraint produced a workable solution that would have been genuinely useful in the field.",{"title":255,"searchDepth":256,"depth":257,"links":913},[914,915,916,917,918],{"id":514,"depth":256,"text":515},{"id":839,"depth":256,"text":840},{"id":877,"depth":256,"text":878},{"id":900,"depth":256,"text":277},{"id":249,"depth":256,"text":250},"Run the Spartan Legionella Test with your phone.",{},5,"\u002Fwork\u002Fenvironmental-testing-app",{"title":798,"description":919},"work\u002Fenvironmental-testing-app",[276,926],"Mobile",[928,929,933,936],{"name":776,"img":777,"href":778},{"name":930,"img":931,"href":932},"Framer","\u002Fimages\u002Ftools\u002Fframer.svg","https:\u002F\u002Fwww.framer.com\u002F",{"name":934,"img":286,"href":935},"React Native","https:\u002F\u002Freactnative.dev\u002F",{"name":683,"img":786,"href":681},"1doCl4mLyfZLvTFMYIyKvQujPDW4L9OrkW6Orvj78a4",{"id":939,"title":940,"body":941,"description":1096,"extension":267,"featureImage":950,"featured":753,"links":269,"meta":1097,"navigation":21,"order":1098,"path":1099,"seo":1100,"stem":1101,"tags":1102,"tools":1104,"__hash__":1106},"work_en\u002Fwork\u002Fdna-test-ui.md","DNA Test UI, FDA Cleared",{"type":8,"value":942,"toc":1088},[943,946,951,954,958,961,964,967,984,987,993,997,1000,1005,1009,1012,1030,1034,1037,1043,1049,1052,1058,1061,1071,1075,1078,1083,1085],[11,944,940],{"id":945},"dna-test-ui-fda-cleared",[15,947,948],{},[116,949],{"alt":940,"src":950,"title":940},"\u002Fimages\u002Fdna-test-ui\u002Fcyp2c19-feature.png",[15,952,953],{},"The DNA Test UI is the software component of Spartan Bio's CYP2C19 Platform, a rapid DNA test run on the Spartan Cube analyser. I led the design with another designer, holding final approval on decisions, through Spartan's formal design control process. The product received FDA clearance and is still being marketed by the company that acquired Spartan's assets.",[25,955,957],{"id":956},"the-challenge","The challenge",[15,959,960],{},"Medical device software operates under tight constraints. Requirements are set early, documentation is rigorous, and changes after regulatory submission carry significant costs across the organization. Getting the design right before submission matters.",[15,962,963],{},"The original goal was a CLIA waived designation from the FDA, which would have allowed anyone to run the test with minimal training (comparable to a blood glucose meter). The chemistry ultimately landed it at high complexity, but the design target shaped our approach throughout: instructions had to be clear enough for non-specialists, workflows had to be reliable enough to run without error, and the interface had to withstand scrutiny.",[15,965,966],{},"Features were defined in the concept and feasibility stages alongside regulatory, technical, and end-user requirements:",[214,968,969,972,975,978,981],{},[217,970,971],{},"Guided workflows for running a test or a control",[217,973,974],{},"A searchable log of test and control results",[217,976,977],{},"User logins and permissions to protect patient data",[217,979,980],{},"An optional, time-based lock",[217,982,983],{},"An optional training module",[15,985,986],{},"We built prototypes in XD and used its handoff features in a tight loop with our Windows developer, refining requirements continuously through the process.",[15,988,989],{},[116,990],{"alt":991,"src":992,"title":991},"DNA Test UI in XD","\u002Fimages\u002Fdna-test-ui\u002Fcyp2c19-xd.png",[25,994,996],{"id":995},"guided-workflows","Guided workflows",[15,998,999],{},"Ensuring users could successfully run the test every time was central to the product's value. The guided workflow provided step-by-step instructions and illustrations at every stage, so users never had to guess what came next. For the most critical and complex step (tapping and mixing the sample), we included a video directly in the interface.",[15,1001,1002],{},[18,1003],{"src":1004,"controls":21,"preload":22,"muted":21,"poster":950},"\u002Fimages\u002Fdna-test-ui\u002Fcyp2c19-workflow.webm",[25,1006,1008],{"id":1007},"result-log","Result log",[15,1010,1011],{},"The log gave users access to all past test and control results, searchable for when records accumulated. Selecting a result showed extended detail. An export feature supported users who maintained their own records systems outside the device.",[15,1013,1014,1018,1022,1026],{},[116,1015],{"alt":1016,"src":1017,"title":1016},"Empty result log","\u002Fimages\u002Fdna-test-ui\u002Flog-empty.png",[116,1019],{"alt":1020,"src":1021,"title":1020},"Result log populated with results","\u002Fimages\u002Fdna-test-ui\u002Flog.png",[116,1023],{"alt":1024,"src":1025,"title":1024},"Log filtered to controls","\u002Fimages\u002Fdna-test-ui\u002Flog-search.png",[116,1027],{"alt":1028,"src":1029,"title":1028},"Result screen","\u002Fimages\u002Fdna-test-ui\u002Fresult.png",[25,1031,1033],{"id":1032},"logins-and-security","Logins and security",[15,1035,1036],{},"User logins protected potentially sensitive patient data. The login form gave clear feedback on failed attempts without revealing which credential was wrong. Users could also scan a barcode to authenticate, a common pattern in clinical settings where staff scan ID badges to access equipment.",[15,1038,1039],{},[116,1040],{"alt":1041,"src":1042,"title":1041},"Login screen","\u002Fimages\u002Fdna-test-ui\u002Flogin.png",[15,1044,1045],{},[116,1046],{"alt":1047,"src":1042,"title":1048},"Credential validation only shows something is wrong, not what is wrong","Invalid credentials",[15,1050,1051],{},"An optional time-based lock let users secure the system when away from it. Since the device can run a test while locked, we added test status to the lock screen; with one laptop per Cube, it was important to show whether the system was busy.",[15,1053,1054],{},[116,1055],{"alt":1056,"src":1057,"title":1056},"Locked system with test in progress","\u002Fimages\u002Fdna-test-ui\u002Flock-screen.png",[15,1059,1060],{},"Lock settings and user management were restricted to the system administrator.",[15,1062,1063,1067],{},[116,1064],{"alt":1065,"src":1066,"title":1065},"System settings","\u002Fimages\u002Fdna-test-ui\u002Fsettings.png",[116,1068],{"alt":1069,"src":1070,"title":1069},"User settings","\u002Fimages\u002Fdna-test-ui\u002Fsettings-users.png",[25,1072,1074],{"id":1073},"training-module","Training module",[15,1076,1077],{},"A built-in training module walked users through the entire workflow from sample collection to running the analyser, with clear instructions and supplementary guidance at each step. This supported the goal of minimising the training burden for new users.",[15,1079,1080],{},[116,1081],{"alt":1074,"src":1082,"title":1074},"\u002Fimages\u002Fdna-test-ui\u002Ftraining.png",[25,1084,250],{"id":249},[15,1086,1087],{},"The DNA testing platform received FDA clearance. The CLIA waived designation we designed toward wasn't achieved (a function of the test chemistry, not the software), but the design approach held up through the regulatory process. A version of the product is still being marketed by the company that acquired Spartan's assets.",{"title":255,"searchDepth":256,"depth":257,"links":1089},[1090,1091,1092,1093,1094,1095],{"id":956,"depth":256,"text":957},{"id":995,"depth":256,"text":996},{"id":1007,"depth":256,"text":1008},{"id":1032,"depth":256,"text":1033},{"id":1073,"depth":256,"text":1074},{"id":249,"depth":256,"text":250},"A medical device user interface designed for ease of use.",{},7,"\u002Fwork\u002Fdna-test-ui",{"title":940,"description":1096},"work\u002Fdna-test-ui",[276,1103],"Medical",[1105],{"name":776,"img":777,"href":778},"8xEL3nJp7PlojT1VYP4brBu-oY_2BI5zitWfsL6p5Ks",1782790338056]